> ## Documentation Index
> Fetch the complete documentation index at: https://docs.phoneuse.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How much copilot you have, and how much is gone

> Your organisation's monthly copilot allowance, what has been spent against it this period, and whether it is gone.

THE ALLOWANCE FOLLOWS THE SUBSCRIPTION, one per subscribed device, summed. A pay-as-you-go purchase includes none, so an organisation holding only those has an allowance of zero, which is a real answer, and one that is `exhausted` from the first token rather than a bar that never fills.

THE UNIT IS TOKENS and the counts cross the wire so that a client can compute a proportion. What a person is shown is the client's decision; the counts are here because a bar cannot be drawn without them.

READ `metered` BEFORE DRAWING ANYTHING. When it is false, `used` is zero because nothing on this deployment counts copilot use, not because nothing was spent. The two are indistinguishable from the number alone, and a bar drawn from the second one shows a measurement nobody made.

ANY SIGNED-IN PRINCIPAL of the organisation may read it, of either role, for the reason the price list is readable by both: a person who can use copilot should be able to see how much of it is left.

503 WHERE NO ALLOWANCE IS CONFIGURED. Reporting zero would show every customer as exhausted, and inventing a figure here would make this service a second answer to a question the price sheet owns.

Hosted deployments only. A local checkout does not mount this route, so calling it there is a 404.



## OpenAPI

````yaml /api/openapi.json get /v1/copilot-allowance
openapi: 3.1.0
info:
  title: Phonebase HTTP API
  version: 0.1.0
  summary: >-
    Every HTTP operation the control plane mounts, generated from the app's own
    route table.
  description: >-
    The control plane exposes two HTTP surfaces, and reading the boundary
    between them matters more than reading any single endpoint.


    The CONTROL surface is what your backend and your operators call. It takes a
    bearer token in the `Authorization` header, and two credential channels
    resolve to the same authorization context: an OAuth 2.1 access token for
    interactive clients, or an org scoped API key for headless ones.


    The DEVICE surface, under `/vrx/{runToken}/v1`, is what a worker calls while
    executing one run. Its credential is the run token in the url path, and it
    reads no `Authorization` header at all.


    Device control itself is not REST. An agent taps, swipes and reads the
    screen over the Model Context Protocol at `POST /mcp`, one tool call at a
    time. There is no `POST /v1/devices/{id}/tap`, and if you are looking for
    one, start with the tool reference instead.


    Operations marked `"x-phonebase-modes": ["hosted"]` exist only on a hosted
    deployment; a local checkout does not mount them.
servers:
  - url: '{origin}'
    description: Your control plane origin.
    variables:
      origin:
        default: https://mcp.phonebase.co
        enum:
          - https://mcp.phonebase.co
          - http://127.0.0.1:8788
        description: >-
          The hosted deployment serves the public origin its metadata document
          advertises, and that is the default here. Select the loopback entry
          instead when you are running a local checkout, which serves the port
          `PORT` names.
security: []
tags:
  - name: Apps
    description: Save immutable application builds and manage explicit device operations.
  - name: Managed Proxy
    description: >-
      Organization-owned fixed egress resources, independent one-time orders and
      verified network relationships.
  - name: Health
    description: Liveness, unauthenticated.
  - name: Gateway enrollment
    description: >-
      How a new gateway computer trades a one-time enrollment code for its
      tunnel credential. Unauthenticated: the code is the credential.
  - name: Gateway releases
    description: >-
      What a gateway computer installs: the current edge release of a channel.
      Called with the gateway's own credential.
  - name: MCP
    description: The JSON-RPC endpoint an agent drives devices through.
  - name: Copilot
    description: >-
      Drive a device by chatting. A signed in person's own conversations,
      streamed. Hosted deployments only.
  - name: Discovery
    description: Where to authenticate. Served on hosted deployments only.
  - name: Runs
    description: Start, watch and steer a run.
  - name: API keys
    description: Mint and revoke headless credentials. Hosted deployments only.
  - name: Device surface
    description: What a worker calls with its run token to observe and act.
  - name: Usage
    description: Read your org's own receipts and consumption. Hosted deployments only.
  - name: Devices
    description: Read the fleet your credential can see. Hosted deployments only.
  - name: Notifications
    description: >-
      What a person needs to know when they are not watching, and which emails
      they receive. Hosted deployments only.
  - name: Webhooks
    description: >-
      Subscribe your own system to what happens here, and read what was
      delivered. Hosted deployments only.
  - name: Provisioning
    description: >-
      Whether an organisation is provisioned, and how it becomes so. Hosted
      deployments only, and both operations answer a declared 503 on a
      deployment that cannot provision yet.
paths:
  /v1/copilot-allowance:
    get:
      tags:
        - Provisioning
      summary: How much copilot you have, and how much is gone
      description: >-
        Your organisation's monthly copilot allowance, what has been spent
        against it this period, and whether it is gone.


        THE ALLOWANCE FOLLOWS THE SUBSCRIPTION, one per subscribed device,
        summed. A pay-as-you-go purchase includes none, so an organisation
        holding only those has an allowance of zero, which is a real answer, and
        one that is `exhausted` from the first token rather than a bar that
        never fills.


        THE UNIT IS TOKENS and the counts cross the wire so that a client can
        compute a proportion. What a person is shown is the client's decision;
        the counts are here because a bar cannot be drawn without them.


        READ `metered` BEFORE DRAWING ANYTHING. When it is false, `used` is zero
        because nothing on this deployment counts copilot use, not because
        nothing was spent. The two are indistinguishable from the number alone,
        and a bar drawn from the second one shows a measurement nobody made.


        ANY SIGNED-IN PRINCIPAL of the organisation may read it, of either role,
        for the reason the price list is readable by both: a person who can use
        copilot should be able to see how much of it is left.


        503 WHERE NO ALLOWANCE IS CONFIGURED. Reporting zero would show every
        customer as exhausted, and inventing a figure here would make this
        service a second answer to a question the price sheet owns.


        Hosted deployments only. A local checkout does not mount this route, so
        calling it there is a 404.
      operationId: getV1CopilotAllowance
      responses:
        '200':
          description: This organisation's allowance and what is left of it.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CopilotAllowance'
        '401':
          description: No credential, or one that was refused.
          headers:
            WWW-Authenticate:
              description: >-
                A bearer challenge. On a hosted deployment it names the metadata
                document to discover the authorization server from, and it adds
                `error="invalid_token"` when a credential was presented and
                rejected.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedError'
        '429':
          description: >-
            Over the request budget for this caller. Hosted deployments only.
            Which budget applied depends on whether this request carried an
            `Authorization` header, not on which endpoint it was aimed at. Wait
            `Retry-After` seconds and retry the same request: the refusal
            happens before any work, so nothing was partially applied. See
            /api/rate-limits.
          headers:
            Retry-After:
              description: >-
                Whole seconds until one request is available again. Computed
                from the caller's own remaining allowance, not a fixed constant.
              schema:
                type: string
            RateLimit-Limit:
              description: >-
                The budget in effect for this caller class, in requests per
                minute.
              schema:
                type: string
            RateLimit-Remaining:
              description: >-
                Whole requests that were still available when this request was
                admitted. Zero on a 429.
              schema:
                type: string
            RateLimit-Reset:
              description: >-
                Seconds until the allowance is back to full. Longer than
                `Retry-After`, which is the wait for a single request.
              schema:
                type: string
            RateLimit-Policy:
              description: The budget and its window, as `<limit>;w=60`.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RateLimitedError'
        '503':
          description: >-
            This deployment states no copilot allowance (`checkout_unavailable`,
            the code the rest of this surface uses for an unconfigured
            deployment), or its provisioning store cannot be read right now
            (`admission_unavailable`, with `Retry-After`).
          headers:
            Retry-After:
              description: >-
                Seconds to wait before asking again. Sent with
                `admission_unavailable` only.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProvisioningUnavailableError'
      security:
        - bearerAuth: []
components:
  schemas:
    CopilotAllowance:
      type: object
      properties:
        included:
          type: integer
          description: >-
            Your monthly allowance in TOKENS, summed over your live subscription
            purchases. Zero is a real answer and not a missing one: pay as you
            go includes no allowance at all, so an organisation holding only
            pay-as-you-go devices has none.
        used:
          type: integer
          description: Spent this period, in TOKENS, input and output together.
        period:
          type: string
          description: >-
            The billing month both counts are measured in, as `YYYY-MM-DD`
            naming its first day. The same period `GET /v1/usage` reports device
            time against, so two bars on one screen cannot disagree about which
            month it is.
        usedFraction:
          type: number
          description: >-
            `used` over `included`, from 0 to 1 and CLAMPED at 1, because a bar
            cannot be more than full, and any overshoot is already visible in
            the two counts. Zero when nothing is included.
        exhausted:
          type: boolean
          description: >-
            The allowance is spent, and copilot drops to command mode. TRUE from
            the first token for an organisation whose allowance is zero.
        nearLimit:
          type: boolean
          description: >-
            Past four fifths of the allowance but not yet spent: the point at
            which a person is warned.
        metered:
          type: boolean
          description: >-
            Whether anything on this deployment actually counts copilot use.
            FALSE means `used` is zero because nothing measured it, not because
            nothing was spent, and a percentage drawn from that zero would be a
            number nobody observed. It is false on every deployment that serves
            no copilot.
      required:
        - included
        - used
        - period
        - usedFraction
        - exhausted
        - nearLimit
        - metered
      additionalProperties: false
      description: How much copilot this organisation has, and how much of it is gone.
    UnauthorizedError:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              const: unauthorized
              description: Always `unauthorized` on this response.
            reason:
              type: string
              enum:
                - missing_credentials
                - malformed_credentials
                - invalid_token
                - token_expired
                - wrong_audience
                - missing_org
                - missing_org_role
                - unknown_key
                - revoked_key
                - expired_key
              description: The closed set of ways authentication can fail.
            hint:
              type: string
              description: >-
                A next step in prose, on the reasons where there is one to give:
                `revoked_key`, `expired_key`, `missing_org_role`, and
                `invalid_token` when the account is not a member of the named
                organization. Absent otherwise, so branch on `reason` and show
                this if it is there.
          required:
            - code
            - reason
          additionalProperties: false
      required:
        - error
      additionalProperties: false
      description: >-
        A refused credential. `unknown_key` covers both a keyId nobody has and a
        secret that does not match, because telling those apart would enumerate
        keys for you. Revocation and expiry are distinguishable, since you owned
        that key.
    RateLimitedError:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              const: rate_limited
              description: Always `rate_limited` on this response.
            message:
              type: string
              description: >-
                A human readable summary. The numbers are in the headers, not in
                here.
          required:
            - code
            - message
          additionalProperties: false
      required:
        - error
      additionalProperties: false
      description: >-
        Over the request budget. Raised by the rate limiter before any handler
        runs, which is why its code is not one of the action codes: nothing was
        attempted, so no action failed.
    ProvisioningUnavailableError:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - admission_unavailable
                - checkout_unavailable
              description: >-
                `admission_unavailable`: the provisioning store cannot be read
                right now; retry after `Retry-After`. `checkout_unavailable`:
                this deployment is not configured for what was asked.
            message:
              type: string
              description: A human readable summary. Do not branch on it, branch on `code`.
          required:
            - code
            - message
          additionalProperties: false
      required:
        - error
      additionalProperties: false
      description: Provisioning cannot answer on this deployment right now.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        The control surface credential. Send `Authorization: Bearer <token>`.


        Two kinds of token are accepted and they are told apart by shape, not by
        a separate header. A token beginning `pbk_` is an org scoped API key,
        whose public half and secret half are generated together and of which
        only a hash of the secret is ever stored; anything else is treated as an
        OAuth 2.1 access token and verified against the authorization server's
        keys.


        Both resolve to the same context: an org, a principal and a set of
        scopes. Nothing downstream branches on which channel you used, with one
        deliberate exception, key management, which requires a signed-in person
        so that a key can never mint another key.


        Scopes are enforced when MCP tools are REGISTERED rather than when they
        are called, so a tool your credential cannot use is absent from
        `tools/list` rather than refused mid gesture.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.