> ## 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.

# Console behavior events

> Contract version 2. Send a client-generated batch UUID with immutable request contents on retries. Within your organization and signed-in person, the first successful response is replayed for 24 hours without writing more events or extending the window. After expiration, the UUID can identify a new batch. A different projected batch (events and dropped count) under a live UUID returns 409 batch_id_reused with no writes. Authentication, rate limits and complete batch validation apply before replay.

Any invalid event refuses the whole batch with indexed HTTP 400 and zero event or batch-receipt writes. Only successful responses are cached. Unknown kinds are refused; unknown detail fields are discarded. Device identifiers, idempotency keys and fields containing serial, udid, imei or email are never stored. An API key cannot report browser events.

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



## OpenAPI

````yaml /api/openapi.json post /v1/console/events
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/console/events:
    post:
      tags:
        - Usage
      summary: Console behavior events
      description: >-
        Contract version 2. Send a client-generated batch UUID with immutable
        request contents on retries. Within your organization and signed-in
        person, the first successful response is replayed for 24 hours without
        writing more events or extending the window. After expiration, the UUID
        can identify a new batch. A different projected batch (events and
        dropped count) under a live UUID returns 409 batch_id_reused with no
        writes. Authentication, rate limits and complete batch validation apply
        before replay.


        Any invalid event refuses the whole batch with indexed HTTP 400 and zero
        event or batch-receipt writes. Only successful responses are cached.
        Unknown kinds are refused; unknown detail fields are discarded. Device
        identifiers, idempotency keys and fields containing serial, udid, imei
        or email are never stored. An API key cannot report browser events.


        Hosted deployments only. A local checkout does not mount this route, so
        calling it there is a 404.
      operationId: postV1ConsoleEvents
      requestBody:
        description: At most 500 events and 262144 UTF-8 bytes, before field filtering.
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                batchId:
                  type: string
                  format: uuid
                  pattern: >-
                    ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$
                  minLength: 36
                  maxLength: 36
                  description: >-
                    Client UUID, retained unchanged across retries of the same
                    request.
                events:
                  type: array
                  minItems: 1
                  maxItems: 500
                  items:
                    oneOf:
                      - type: object
                        properties:
                          kind:
                            type: string
                            const: console.receipt_opened
                            maxLength: 200
                          atMs:
                            type: integer
                            minimum: 0
                            maximum: 4102444800000
                            description: >-
                              Browser epoch milliseconds through
                              2100-01-01T00:00:00Z (inclusive); not the database
                              time of record.
                          detail:
                            type: object
                            properties: {}
                            required: []
                            additionalProperties: true
                            description: >-
                              Only the listed fields are retained. Unknown
                              fields are discarded. Original detail is limited
                              to 4096 compact JSON bytes.
                        required:
                          - kind
                          - atMs
                        additionalProperties: true
                      - type: object
                        properties:
                          kind:
                            type: string
                            const: console.one_shot_mode
                            maxLength: 200
                          atMs:
                            type: integer
                            minimum: 0
                            maximum: 4102444800000
                            description: >-
                              Browser epoch milliseconds through
                              2100-01-01T00:00:00Z (inclusive); not the database
                              time of record.
                          detail:
                            type: object
                            properties:
                              mode:
                                type: string
                                enum:
                                  - manual
                                  - auto
                            required: []
                            additionalProperties: true
                            description: >-
                              Only the listed fields are retained. Unknown
                              fields are discarded. Original detail is limited
                              to 4096 compact JSON bytes.
                        required:
                          - kind
                          - atMs
                        additionalProperties: true
                      - type: object
                        properties:
                          kind:
                            type: string
                            const: console.let_it_continue
                            maxLength: 200
                          atMs:
                            type: integer
                            minimum: 0
                            maximum: 4102444800000
                            description: >-
                              Browser epoch milliseconds through
                              2100-01-01T00:00:00Z (inclusive); not the database
                              time of record.
                          detail:
                            type: object
                            properties:
                              agentRunId:
                                type: string
                                pattern: >-
                                  ^run_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                                minLength: 40
                                maxLength: 40
                              runId:
                                type: string
                                pattern: >-
                                  ^task_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                                minLength: 41
                                maxLength: 41
                            required: []
                            additionalProperties: true
                            description: >-
                              Only the listed fields are retained. Unknown
                              fields are discarded. Original detail is limited
                              to 4096 compact JSON bytes.
                        required:
                          - kind
                          - atMs
                        additionalProperties: true
                      - type: object
                        properties:
                          kind:
                            type: string
                            const: console.command_mode_entered
                            maxLength: 200
                          atMs:
                            type: integer
                            minimum: 0
                            maximum: 4102444800000
                            description: >-
                              Browser epoch milliseconds through
                              2100-01-01T00:00:00Z (inclusive); not the database
                              time of record.
                          detail:
                            type: object
                            properties: {}
                            required: []
                            additionalProperties: true
                            description: >-
                              Only the listed fields are retained. Unknown
                              fields are discarded. Original detail is limited
                              to 4096 compact JSON bytes.
                        required:
                          - kind
                          - atMs
                        additionalProperties: true
                      - type: object
                        properties:
                          kind:
                            type: string
                            const: console.run_pause
                            maxLength: 200
                          atMs:
                            type: integer
                            minimum: 0
                            maximum: 4102444800000
                            description: >-
                              Browser epoch milliseconds through
                              2100-01-01T00:00:00Z (inclusive); not the database
                              time of record.
                          detail:
                            type: object
                            properties:
                              agentRunId:
                                type: string
                                pattern: >-
                                  ^run_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                                minLength: 40
                                maxLength: 40
                              runId:
                                type: string
                                pattern: >-
                                  ^task_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                                minLength: 41
                                maxLength: 41
                              control:
                                type: string
                                enum:
                                  - pause
                                  - resume
                                  - done
                                  - stop
                            required: []
                            additionalProperties: true
                            description: >-
                              Only the listed fields are retained. Unknown
                              fields are discarded. Original detail is limited
                              to 4096 compact JSON bytes.
                        required:
                          - kind
                          - atMs
                        additionalProperties: true
                      - type: object
                        properties:
                          kind:
                            type: string
                            const: console.run_resume
                            maxLength: 200
                          atMs:
                            type: integer
                            minimum: 0
                            maximum: 4102444800000
                            description: >-
                              Browser epoch milliseconds through
                              2100-01-01T00:00:00Z (inclusive); not the database
                              time of record.
                          detail:
                            type: object
                            properties:
                              agentRunId:
                                type: string
                                pattern: >-
                                  ^run_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                                minLength: 40
                                maxLength: 40
                              runId:
                                type: string
                                pattern: >-
                                  ^task_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                                minLength: 41
                                maxLength: 41
                              control:
                                type: string
                                enum:
                                  - pause
                                  - resume
                                  - done
                                  - stop
                            required: []
                            additionalProperties: true
                            description: >-
                              Only the listed fields are retained. Unknown
                              fields are discarded. Original detail is limited
                              to 4096 compact JSON bytes.
                        required:
                          - kind
                          - atMs
                        additionalProperties: true
                      - type: object
                        properties:
                          kind:
                            type: string
                            const: console.run_done
                            maxLength: 200
                          atMs:
                            type: integer
                            minimum: 0
                            maximum: 4102444800000
                            description: >-
                              Browser epoch milliseconds through
                              2100-01-01T00:00:00Z (inclusive); not the database
                              time of record.
                          detail:
                            type: object
                            properties:
                              agentRunId:
                                type: string
                                pattern: >-
                                  ^run_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                                minLength: 40
                                maxLength: 40
                              runId:
                                type: string
                                pattern: >-
                                  ^task_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                                minLength: 41
                                maxLength: 41
                              control:
                                type: string
                                enum:
                                  - pause
                                  - resume
                                  - done
                                  - stop
                            required: []
                            additionalProperties: true
                            description: >-
                              Only the listed fields are retained. Unknown
                              fields are discarded. Original detail is limited
                              to 4096 compact JSON bytes.
                        required:
                          - kind
                          - atMs
                        additionalProperties: true
                      - type: object
                        properties:
                          kind:
                            type: string
                            const: console.run_stop
                            maxLength: 200
                          atMs:
                            type: integer
                            minimum: 0
                            maximum: 4102444800000
                            description: >-
                              Browser epoch milliseconds through
                              2100-01-01T00:00:00Z (inclusive); not the database
                              time of record.
                          detail:
                            type: object
                            properties:
                              agentRunId:
                                type: string
                                pattern: >-
                                  ^run_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                                minLength: 40
                                maxLength: 40
                              runId:
                                type: string
                                pattern: >-
                                  ^task_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                                minLength: 41
                                maxLength: 41
                              control:
                                type: string
                                enum:
                                  - pause
                                  - resume
                                  - done
                                  - stop
                            required: []
                            additionalProperties: true
                            description: >-
                              Only the listed fields are retained. Unknown
                              fields are discarded. Original detail is limited
                              to 4096 compact JSON bytes.
                        required:
                          - kind
                          - atMs
                        additionalProperties: true
                      - type: object
                        properties:
                          kind:
                            type: string
                            const: console.live_reconnect
                            maxLength: 200
                          atMs:
                            type: integer
                            minimum: 0
                            maximum: 4102444800000
                            description: >-
                              Browser epoch milliseconds through
                              2100-01-01T00:00:00Z (inclusive); not the database
                              time of record.
                          detail:
                            type: object
                            properties:
                              trigger:
                                type: string
                                enum:
                                  - user_leave
                                  - watchdog_stall
                                  - transport
                                  - no_first_frame
                                  - hidden_load
                              attempt:
                                type: integer
                                minimum: 0
                                maximum: 1000000
                            required: []
                            additionalProperties: true
                            description: >-
                              Only the listed fields are retained. Unknown
                              fields are discarded. Original detail is limited
                              to 4096 compact JSON bytes.
                        required:
                          - kind
                          - atMs
                        additionalProperties: true
                      - type: object
                        properties:
                          kind:
                            type: string
                            const: console.live_reconnect_exhausted
                            maxLength: 200
                          atMs:
                            type: integer
                            minimum: 0
                            maximum: 4102444800000
                            description: >-
                              Browser epoch milliseconds through
                              2100-01-01T00:00:00Z (inclusive); not the database
                              time of record.
                          detail:
                            type: object
                            properties:
                              trigger:
                                type: string
                                enum:
                                  - user_leave
                                  - watchdog_stall
                                  - transport
                                  - no_first_frame
                                  - hidden_load
                              attempts:
                                type: integer
                                minimum: 0
                                maximum: 1000000
                            required: []
                            additionalProperties: true
                            description: >-
                              Only the listed fields are retained. Unknown
                              fields are discarded. Original detail is limited
                              to 4096 compact JSON bytes.
                        required:
                          - kind
                          - atMs
                        additionalProperties: true
                      - type: object
                        properties:
                          kind:
                            type: string
                            const: console.get_started_step_seen
                            maxLength: 200
                          atMs:
                            type: integer
                            minimum: 0
                            maximum: 4102444800000
                            description: >-
                              Browser epoch milliseconds through
                              2100-01-01T00:00:00Z (inclusive); not the database
                              time of record.
                          detail:
                            type: object
                            properties:
                              steps:
                                type: array
                                items:
                                  type: string
                                  enum:
                                    - add-device
                                    - connect
                                    - first-run
                                    - first-takeover
                            required: []
                            additionalProperties: true
                            description: >-
                              Only the listed fields are retained. Unknown
                              fields are discarded. Original detail is limited
                              to 4096 compact JSON bytes.
                        required:
                          - kind
                          - atMs
                        additionalProperties: true
                      - type: object
                        properties:
                          kind:
                            type: string
                            const: console.cancel_run
                            maxLength: 200
                          atMs:
                            type: integer
                            minimum: 0
                            maximum: 4102444800000
                            description: >-
                              Browser epoch milliseconds through
                              2100-01-01T00:00:00Z (inclusive); not the database
                              time of record.
                          detail:
                            type: object
                            properties:
                              agentRunId:
                                type: string
                                pattern: >-
                                  ^run_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                                minLength: 40
                                maxLength: 40
                              runId:
                                type: string
                                pattern: >-
                                  ^task_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
                                minLength: 41
                                maxLength: 41
                            required: []
                            additionalProperties: true
                            description: >-
                              Only the listed fields are retained. Unknown
                              fields are discarded. Original detail is limited
                              to 4096 compact JSON bytes.
                        required:
                          - kind
                          - atMs
                        additionalProperties: true
                      - type: object
                        properties:
                          kind:
                            type: string
                            const: console.run_a_task_opened
                            maxLength: 200
                          atMs:
                            type: integer
                            minimum: 0
                            maximum: 4102444800000
                            description: >-
                              Browser epoch milliseconds through
                              2100-01-01T00:00:00Z (inclusive); not the database
                              time of record.
                          detail:
                            type: object
                            properties: {}
                            required: []
                            additionalProperties: true
                            description: >-
                              Only the listed fields are retained. Unknown
                              fields are discarded. Original detail is limited
                              to 4096 compact JSON bytes.
                        required:
                          - kind
                          - atMs
                        additionalProperties: true
                      - type: object
                        properties:
                          kind:
                            type: string
                            const: console.stream_stats
                            maxLength: 200
                          atMs:
                            type: integer
                            minimum: 0
                            maximum: 4102444800000
                            description: >-
                              Browser epoch milliseconds through
                              2100-01-01T00:00:00Z (inclusive); not the database
                              time of record.
                          detail:
                            type: object
                            properties:
                              transport:
                                type: string
                                enum:
                                  - edge-webrtc
                                  - provider-rtc
                                  - snapshot
                              role:
                                type: string
                                enum:
                                  - customer
                                  - ops
                              layer:
                                type: string
                                enum:
                                  - low
                                  - medium
                                  - high
                              frameTiming:
                                type: string
                                enum:
                                  - sync_points
                                  - edge_clock
                                  - receive_time
                                  - none
                              fps:
                                type: number
                                minimum: 0
                                maximum: 240
                              bitrateKbps:
                                type: number
                                minimum: 0
                                maximum: 1000000
                              packetLossPct:
                                type: number
                                minimum: 0
                                maximum: 100
                              frameLatencyMsP50:
                                type:
                                  - number
                                  - 'null'
                                minimum: 0
                                maximum: 600000
                              frameLatencyMsP95:
                                type:
                                  - number
                                  - 'null'
                                minimum: 0
                                maximum: 600000
                              firstFrameMs:
                                type:
                                  - number
                                  - 'null'
                                minimum: 0
                                maximum: 600000
                              freezeCount:
                                type: integer
                                minimum: 0
                                maximum: 1000000
                              reconnects:
                                type: integer
                                minimum: 0
                                maximum: 1000000
                              clickToDisplayMs:
                                type: array
                                items:
                                  type: number
                                  minimum: 0
                                  maximum: 600000
                                maxItems: 200
                              queueWaitMs:
                                type: array
                                items:
                                  type: number
                                  minimum: 0
                                  maximum: 600000
                                maxItems: 200
                            required:
                              - transport
                              - role
                              - layer
                              - frameTiming
                              - fps
                              - bitrateKbps
                              - packetLossPct
                              - frameLatencyMsP50
                              - frameLatencyMsP95
                              - freezeCount
                              - reconnects
                              - clickToDisplayMs
                              - queueWaitMs
                            additionalProperties: true
                            description: >-
                              Only the listed fields are retained. Unknown
                              fields are discarded. Original detail is limited
                              to 4096 compact JSON bytes.
                        required:
                          - kind
                          - atMs
                          - detail
                        additionalProperties: true
                dropped:
                  type: integer
                  minimum: 0
                  maximum: 1000000000
                  default: 0
                  description: How many events the queue dropped before this batch.
              required:
                - batchId
                - events
              additionalProperties: true
      responses:
        '200':
          description: >-
            The complete batch committed, or its original success body was
            replayed. No partial acceptance.
          content:
            application/json:
              schema:
                type: object
                properties:
                  contractVersion:
                    type: integer
                    const: 2
                  batchId:
                    type: string
                    format: uuid
                    minLength: 36
                    maxLength: 36
                  recorded:
                    type: integer
                    minimum: 1
                    maximum: 500
                  rejected:
                    type: array
                    maxItems: 0
                    items:
                      type: object
                      properties:
                        index:
                          type: integer
                        reason:
                          type: string
                          description: Validation reason.
                      required:
                        - index
                        - reason
                      additionalProperties: false
                required:
                  - contractVersion
                  - batchId
                  - recorded
                  - rejected
                additionalProperties: false
        '400':
          description: >-
            Zero event and batch-receipt writes. Event failures have their
            original indices; batch-level errors have an empty rejected array. A
            valid parsed batchId is echoed.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        const: invalid_argument
                      message:
                        type: string
                        description: Validation explanation without submitted values.
                    required:
                      - code
                      - message
                    additionalProperties: false
                  contractVersion:
                    type: integer
                    const: 2
                  batchId:
                    type: string
                    format: uuid
                    minLength: 36
                    maxLength: 36
                  recorded:
                    type: integer
                    const: 0
                  rejected:
                    type: array
                    maxItems: 500
                    items:
                      type: object
                      properties:
                        index:
                          type: integer
                          minimum: 0
                          maximum: 499
                        reason:
                          type: string
                          description: Validation reason without submitted values.
                      required:
                        - index
                        - reason
                      additionalProperties: false
                required:
                  - error
                  - contractVersion
                  - recorded
                  - rejected
                additionalProperties: false
        '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'
        '403':
          description: The credential lacks devices:read, or does not identify a person.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >-
            This live batch UUID already acknowledged different projected events
            or a different dropped count. No writes; retain queued events and
            investigate the batch identity before retrying.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        const: batch_id_reused
                      message:
                        type: string
                        description: Batch identity conflict without submitted values.
                    required:
                      - code
                      - message
                    additionalProperties: false
                  contractVersion:
                    type: integer
                    const: 2
                  batchId:
                    type: string
                    format: uuid
                    minLength: 36
                    maxLength: 36
                  recorded:
                    type: integer
                    const: 0
                  rejected:
                    type: array
                    maxItems: 0
                    items:
                      type: object
                      properties:
                        index:
                          type: integer
                        reason:
                          type: string
                          description: Validation reason.
                      required:
                        - index
                        - reason
                      additionalProperties: false
                required:
                  - error
                  - contractVersion
                  - batchId
                  - recorded
                  - rejected
                additionalProperties: false
        '413':
          description: >-
            The request body exceeds the server's limit (1 MiB). Refused before
            the body is parsed, so nothing was partially applied. Retrying the
            same body will fail the same way: send less. Per-field limits are
            tighter than this and are documented on the fields themselves; this
            is the backstop underneath them. The shape is the same on ordinary
            JSON surfaces, /vrx included. The explicitly configured APK content
            stream documents its own byte ceiling.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PayloadTooLargeError'
        '429':
          description: >-
            The existing per-credential allowance is exhausted. Replay attempts
            also consume allowance.


            Or: 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: Seconds to wait before retrying.
              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:
                oneOf:
                  - $ref: '#/components/schemas/Error'
                  - $ref: '#/components/schemas/RateLimitedError'
        '503':
          description: >-
            The authentication backend could not be reached. The service fails
            closed: an infrastructure fault is refused, never waved through.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
        - bearerAuth: []
components:
  schemas:
    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.
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - backend_resolution_failed
                - backend_not_implemented
                - device_unavailable
                - device_disconnected
                - lease_mismatch
                - lease_required
                - capability_unsupported
                - invalid_argument
                - backend_command_failed
                - idempotency_conflict
                - action_outcome_unknown
                - stale_frame
                - internal_error
                - unauthorized
                - permission_denied
                - run_not_found
                - frame_not_found
                - device_busy
                - admission_unavailable
                - checkout_unavailable
                - checkout_customer_balance
                - checkout_in_progress
                - quote_changed
                - payment_in_progress
                - out_of_stock
                - wrong_state
                - instance_not_served
                - reverification_required
                - not_found
                - receipt_not_found
                - rate_limited
                - payload_too_large
                - origin_not_allowed
                - api_key_from_browser_origin
                - key_predates_instance_attribution
                - org_not_served_by_instance
                - tenant_binding_unavailable
                - tenant_binding_unsettled
                - fleet_at_capacity
                - forbidden
                - service_unavailable
                - invalid_signature
                - invalid_event
                - not_settled
              description: >-
                The closed set of codes this service answers with on purpose, on
                MCP tools and REST alike (D152). What each one means and when
                you get it is on the errors page.
            message:
              type: string
              description: A human readable summary. Do not branch on it, branch on `code`.
            retryable:
              type: boolean
              description: >-
                Whether re-issuing the same call unchanged is meaningful. It is
                a property of the occurrence, not of the code, so read the field
                rather than inferring it.
          required:
            - code
            - message
          additionalProperties: true
          description: >-
            Specific errors add their own fields, such as `deviceId`, `reason`
            or `capability`. Read the ones you branch on and ignore the rest.
      required:
        - error
      additionalProperties: false
      description: >-
        The control surface error envelope. Every non 2xx JSON body on this
        surface has this shape.
    PayloadTooLargeError:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              const: payload_too_large
              description: Always `payload_too_large` on this response.
            message:
              type: string
              description: A human readable summary naming the limit in bytes.
          required:
            - code
            - message
          additionalProperties: false
      required:
        - error
      additionalProperties: false
      description: >-
        Returned when the request body exceeds the server limit. Identical on
        every surface, including /vrx.
    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.
  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.