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

# Destroy a Sandbox

> You can rely on:
- Never deletes another generation of the sandbox.
- Returns once accepted: 204 when confirmed, else 202 with an operation that completes lifecycle work; GET /operations/{id} reports completion.
- While a destroy is unresolved, a repeated destroy is accepted as the same pending operation and makes no second provider call; once the destroy is confirmed, a repeat returns 204 with no body.

You can set: nothing.

Not promised: how long teardown takes; that the sandbox is already absent from listings on return.

Requests destruction on the original upstream account, including persistent sandbox
storage where the provider's destroy operation removes it. Separately owned volumes
are not deleted. DELETE returns once the provider accepts the destroy, always as 202
with the sandbox: `state` is `destroyed` when the provider confirmed within the request
and `destroying` while lifecycle work remains, and `operation_id` is set while work
remains. BoxRouter finishes an accepted destroy without the caller. GET
/operations/{operation_id} reports the operation's outcome; for an accepted destroy this
includes any remaining stop, final usage, and deletion work.

A repeat DELETE while destruction is unresolved returns 202 with the existing
operation_id and makes no second provider call. Once destruction is confirmed,
repeat DELETEs return 202 with the destroyed sandbox and no `operation_id`. Unknown or
unowned sandbox IDs return 404.




## OpenAPI

````yaml openapi.json DELETE /sandboxes/{sandbox_id}
openapi: 3.1.1
info:
  title: BoxRouter API
  version: 0.10.281
  description: >
    Hosted sandbox control using a BoxRouter API key. Provider credentials are

    configured separately and never included in workload requests. Same-origin
    browser

    sessions are also accepted. Browser mutations require the configured Origin
    and

    the session-bound X-CSRF-Token; after an organization switch, every
    cookie-authenticated

    mutation must also send X-BoxRouter-Selection-Version with the version read
    from /auth/me.

    A stale version returns 409 organization_changed before side effects; its
    details contain

    the current selection_version. Bearer keys do not require browser CSRF or
    selection headers. Core adapters

    execute on BoxRouter servers.

    Sandbox IDs are BoxRouter resource IDs; every access is scoped to the
    caller's

    workspace. Routing occurs only at creation. Subsequent operations retain the

    original provider, upstream account and billing mode.

    Mutation endpoints accept an Idempotency-Key. Clients should generate one
    per

    logical mutation and retain it for reconciliation. The server records
    workspace,

    method, path and request identity before dispatch. Buffered requests include
    the full

    body hash. Streaming uploads reserve the key first, lock concurrent
    dispatch, and

    finalize the body hash as bytes arrive; interrupted uploads remain
    unresolved and

    must not be redispatched. A replay must validate the complete body before
    returning

    a recorded success. Reusing a key with different input

    returns 409; identical input returns the recorded result or an
    unresolved-operation

    error without dispatching again. Records with unknown outcomes are retained
    until

    resolved; completed records remain available for at least 24 hours. This
    does not

    promise exactly-once upstream execution or authorize automatic mutation
    retries.


    ## Guarantees


    Each operation's description states what you can rely on, what you can set
    and what is not promised. These rules apply to all operations:


    - File operations may act with more authority than the command user: do not
    rely on file permissions to keep the file API out. Commands run as the
    command user.

    - Some features need capabilities. A request that names them runs only on
    infrastructure that supports them, and an operation the sandbox was not
    created for returns a clear error; behaviour never changes silently.
servers:
  - url: https://api.boxrouter.ai/api/v1
security:
  - BoxRouterKey: []
  - BrowserSession: []
tags:
  - name: agents
    description: Discover launch manifests available to this workspace.
  - name: identity
    description: Browser sign-in and self-service API-key administration.
  - name: organizations
    description: >-
      Browser-only team organizations, invitations and membership
      administration.
  - name: launches
    description: Create an interactive sandbox from an agent manifest.
  - name: launch-runs
    description: >-
      Reserve, list, observe, and stop unattended multi-copy launch runs and
      their copies.
  - name: sandboxes
    description: Create and manage owned sandbox resources.
  - name: commands
    description: Execute Bash commands in an existing sandbox.
  - name: files
    description: Transfer exact file bytes within an existing sandbox.
  - name: providers
    description: Discover the caller's eligible supply and capabilities.
  - name: operations
    description: Reconcile uncertain mutations without replaying them.
  - name: provider-accounts
    description: >-
      Manage encrypted hosted BYOK connections separately from workload
      requests.
  - name: credits
    description: >-
      Prepaid credit balance, purchases and saved payment methods; never
      required for BYOK work.
  - name: spend-limits
    description: >-
      The cap on the managed compute a workspace can spend; BYOK work never
      counts.
  - name: processes
    description: >-
      Background commands with streamed output and completion on every provider;
      stdin where supported.
  - name: previews
    description: URLs and enforced credentials for sandbox ports on every provider.
  - name: volumes
    description: 'BoxRouter Volumes: one folder with checkpoints, restorable on any provider'
  - name: terminals
    description: Real PTY sessions on every provider through a guest helper.
  - name: secrets
    description: Manage workspace-scoped secret values without returning them.
  - name: artifacts
    description: Temporary workspace-owned inputs for provider builds and file transfers.
  - name: pricing
    description: >-
      The providers' published prices, as dated versions anyone can read without
      a key.
  - name: github
    description: >-
      The shared GitHub App connection used by Deployments and Actions;
      installations remain workspace-scoped.
  - name: actions
    description: >-
      GitHub Actions settings, policy previews and workspace-owned run, job and
      placement projections.
  - name: routing
    description: >-
      Workspace-wide routing authority, per-provider funding order and
      availability preview.
  - name: images
    description: Prepare and remove workspace-scoped provider copies of images.
paths:
  /sandboxes/{sandbox_id}:
    parameters:
      - $ref: '#/components/parameters/SandboxId'
    delete:
      tags:
        - sandboxes
      summary: Destroy a sandbox
      description: >
        You can rely on:

        - Never deletes another generation of the sandbox.

        - Returns once accepted: 204 when confirmed, else 202 with an operation
        that completes lifecycle work; GET /operations/{id} reports completion.

        - While a destroy is unresolved, a repeated destroy is accepted as the
        same pending operation and makes no second provider call; once the
        destroy is confirmed, a repeat returns 204 with no body.


        You can set: nothing.


        Not promised: how long teardown takes; that the sandbox is already
        absent from listings on return.


        Requests destruction on the original upstream account, including
        persistent sandbox

        storage where the provider's destroy operation removes it. Separately
        owned volumes

        are not deleted. DELETE returns once the provider accepts the destroy,
        always as 202

        with the sandbox: `state` is `destroyed` when the provider confirmed
        within the request

        and `destroying` while lifecycle work remains, and `operation_id` is set
        while work

        remains. BoxRouter finishes an accepted destroy without the caller. GET

        /operations/{operation_id} reports the operation's outcome; for an
        accepted destroy this

        includes any remaining stop, final usage, and deletion work.


        A repeat DELETE while destruction is unresolved returns 202 with the
        existing

        operation_id and makes no second provider call. Once destruction is
        confirmed,

        repeat DELETEs return 202 with the destroyed sandbox and no
        `operation_id`. Unknown or

        unowned sandbox IDs return 404.
      operationId: destroySandbox
      parameters:
        - name: discard_unsaved
          in: query
          required: false
          description: >-
            Destroy even if saving the attached volume fails, discarding unsaved
            changes.
          schema:
            type: boolean
            default: false
      responses:
        '202':
          description: The sandbox after the provider accepted the destroy.
          headers:
            Server-Timing:
              $ref: '#/components/headers/ServerTiming'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Sandbox'
        '404':
          $ref: '#/components/responses/Error'
        '409':
          $ref: '#/components/responses/Error'
        default:
          $ref: '#/components/responses/Error'
components:
  parameters:
    SandboxId:
      name: sandbox_id
      in: path
      required: true
      description: Workspace-owned BoxRouter sandbox ID, not an upstream ID.
      schema:
        type: string
        minLength: 1
        pattern: ^[^\u0000]*$
  headers:
    ServerTiming:
      description: >
        Durations of server-side phases, for diagnosing slow requests. Phase
        names are not stable

        and may change.
      schema:
        type: string
      x-boxrouter-server-timing:
        version: 1
        unit: ms
        serviceAggregateMetric: service
        maxHeaderBytes: 8192
        maxOperationRows: 32
        decimalPlaces: 3
        safeNamePattern: ^[A-Za-z0-9_.:-]{1,64}$
        aggregates:
          - metric: service
            fieldStem: cloud
          - metric: database
            fieldStem: database
          - metric: code
            fieldStem: code
          - metric: provider_connect
            fieldStem: provider_connect
          - metric: provider_wait
            fieldStem: provider_wait
          - metric: accept
            fieldStem: accept
          - metric: queue
            fieldStem: queue
          - metric: admission
            fieldStem: admission
          - metric: encode
            fieldStem: encode
        aggregateGrammar:
          duration:
            parameter: dur
            type: number
            finite: true
            minimum: 0
          descriptionParameter: desc
          unknownDescription: unknown
          missingMeans: unreported
        operationGrammar:
          metric: op
          nameParameter: desc
          namePattern: safeNamePattern
          start:
            parameter: start
            type: number
            finite: true
            sign: signed
            relativeTo: recorderWindow
          duration:
            parameter: dur
            type: number
            finite: true
            minimum: 0
          outcomeParameter: outcome
          outcomes:
            - returned
            - raised
          requiresAggregateDependencyUnion: false
        omissionGrammar:
          metric: op-omitted
          count:
            parameter: desc
            type: integer
            minimum: 0
          duration:
            parameter: dur
            type: number
            finite: true
            minimum: 0
            sumOf: knownOmittedMeasuredRows
          requiresAggregateDependencyUnion: false
        coverageGrammar:
          metric: op-coverage
          descriptionParameter: desc
          unknownValue: unknown
          absentState: unreported
          states:
            - unknown
            - unreported
          absenceImpliesCompleteness: false
    RequestId:
      description: >-
        Server-generated correlation identifier; contains no credentials or
        payloads.
      schema:
        type: string
  schemas:
    Sandbox:
      type: object
      description: >
        A sandbox created from a settled body, returned by create, restore, get
        and list.

        Required fields are present; fields with no value are null, never
        absent. Optional

        fields may be absent when their source is not known. Listings do no

        provider I/O: they show the latest durably recorded state, and
        native_state,

        route.selection and recorder are null. Detail responses observe the
        provider live and

        record the normalized state unless a concurrent lifecycle change
        supersedes the read.
      required:
        - id
        - state
        - state_reason
        - failure
        - native_state
        - observed_at
        - state_recorded_at
        - created_at
        - ready_at
        - ended_at
        - labels
        - lifetime
        - route
        - contract
        - request
        - hidden_secrets
        - tcp_ports
        - recorder
        - limits
      properties:
        id:
          type: string
          minLength: 1
          maxLength: 128
          pattern: ^[^\u0000]*$
        state:
          type: string
          enum:
            - creating
            - running
            - paused
            - destroying
            - destroyed
            - error
            - unknown
          x-boxrouter-open-enum: true
          description: >
            Clients must tolerate values they do not know. A sandbox the
            provider stopped, or one

            stopped for being idle that can be started again, reads paused;
            resume brings either back.
        state_reason:
          type:
            - string
            - 'null'
          enum:
            - requested
            - lifetime
            - retention
            - idle_shutdown
            - external
            - null
          x-boxrouter-open-enum: true
          description: >-
            Why it is in this state. external is a change made at the provider,
            behind BoxRouter's back.
        failure:
          oneOf:
            - $ref: '#/components/schemas/SandboxFailure'
            - type: 'null'
          description: >
            The provider failure recorded with state=error, or null when no
            recorded failure

            explains the current state. Present on create, detail and list
            responses; list

            reads return the durable value without calling the provider.
        native_state:
          type:
            - string
            - 'null'
        observed_at:
          type: string
          format: date-time
          description: >
            Time the state source for this response was read: the owned-record
            lookup time

            for a list response, or the live provider-observation time for a
            detail response.
        state_recorded_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >
            Timestamp of the durable state source used for this response. This
            can be an

            existing lifecycle or lifetime record when the returned public state
            is derived

            from that source, and may predate observed_at. Null when no source
            timestamp is

            available or a concurrent lifecycle change supersedes the detail
            read.
        created_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            Time Cloud sent the first create request when that edge is
            available; otherwise the sandbox record's created time.
        expires_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >
            Enforced deadline from the recorded lifetime budget, including
            extensions. This

            is the same deadline exposed as lifetime.ends_at; null when no
            deadline is known.
        ready_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >
            Time Cloud received the first create response; when that edge is
            unavailable, the sandbox

            record's ready time. Null while creating. List and detail responses
            use the same value.
        ended_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >
            Time Cloud received the last destroy response; when that edge is
            unavailable, Cloud's

            record of confirmation or first observation that the sandbox was
            gone. Null while the

            sandbox has not ended. List and detail responses use the same value.
        created_at_source:
          anyOf:
            - $ref: '#/components/schemas/UsageSource'
            - type: 'null'
          description: >-
            Where `created_at` came from. Null when `created_at` is null. Always
            BoxRouter's own record.
        created_at_how:
          type:
            - string
            - 'null'
          minLength: 1
          description: >-
            One sentence saying how `created_at` was determined. Null when
            `created_at` is null.
        created_at_step:
          type:
            - integer
            - 'null'
          minimum: 1
          description: >-
            Null because `created_at` comes from a recorded lifecycle edge or
            Cloud's record.
        ready_at_source:
          anyOf:
            - $ref: '#/components/schemas/UsageSource'
            - type: 'null'
          description: >-
            Where `ready_at` came from. Null when `ready_at` is null. Lifecycle
            edges and Cloud's own record are `recorded`.
        ready_at_how:
          type:
            - string
            - 'null'
          minLength: 1
          description: >-
            One sentence saying how `ready_at` was determined. Null when
            `ready_at` is null.
        ready_at_step:
          type:
            - integer
            - 'null'
          minimum: 1
          description: >-
            Null because `ready_at` comes from a recorded lifecycle edge or
            Cloud's record.
        ended_at_source:
          anyOf:
            - $ref: '#/components/schemas/UsageSource'
            - type: 'null'
          description: >-
            Where `ended_at` came from. Null when `ended_at` is null. Lifecycle
            edges and Cloud's own record are `recorded`.
        ended_at_how:
          type:
            - string
            - 'null'
          minLength: 1
          description: >-
            One sentence saying how `ended_at` was determined. Null when
            `ended_at` is null.
        ended_at_step:
          type:
            - integer
            - 'null'
          minimum: 1
          description: >-
            Null because `ended_at` comes from a recorded lifecycle edge or
            Cloud's record.
        cost_source:
          anyOf:
            - $ref: '#/components/schemas/UsageSource'
            - type: 'null'
          description: >-
            Where `cost` came from. Null when `cost` is null. `provider` for a
            reported cost, `calculated` for a worked-out one, `unknown` when no
            cost could be worked out. The `cost_step` is 1 for a provider
            figure, then 2 provider times, 3 a checked billing boundary, 4 a
            range, 5 unknown.
        cost_how:
          type:
            - string
            - 'null'
          minLength: 1
          description: >-
            One sentence saying how `cost` was determined. Null when `cost` is
            null.
        cost_step:
          type:
            - integer
            - 'null'
          minimum: 1
          description: >
            The position of the source in BoxRouter's source order for this
            value, 1 being the best.

            Null when the value is BoxRouter's own record rather than a pick
            between sources.
        origin:
          oneOf:
            - $ref: '#/components/schemas/SandboxOrigin'
            - type: 'null'
          description: Durable creation provenance. Omitted when the source is not known.
        labels:
          type: object
          additionalProperties:
            type: string
        name:
          type:
            - string
            - 'null'
          description: Sandbox name from labels.name, when set.
        resources:
          type: object
          description: Resolved CPU, memory and disk resources; null values mean unknown.
          properties:
            cpu:
              type:
                - number
                - 'null'
              exclusiveMinimum: 0
            memory_mib:
              type:
                - integer
                - 'null'
              minimum: 1
            disk_mib:
              type:
                - integer
                - 'null'
              minimum: 1
        image:
          oneOf:
            - $ref: '#/components/schemas/SandboxImage'
            - type: 'null'
          description: >
            The image the sandbox runs and where that is known from. Null when
            nothing records

            it. Absent from responses of a Cloud that does not report it yet.
        image_setup:
          $ref: '#/components/schemas/SandboxImageSetup'
          description: >-
            Present only when this start waited for image setup on its chosen
            provider.
        usage:
          anyOf:
            - $ref: '#/components/schemas/Usage'
            - $ref: '#/components/schemas/LegacyZeroGpuUsage'
            - type: 'null'
          description: >
            What the sandbox used: its size, its running time per state, how
            often it was created,

            each fact with the source it came from. Null when nothing has been
            recorded or the

            response does not carry it. Absent from responses of a Cloud that
            does not report it yet.
        cost:
          oneOf:
            - $ref: '#/components/schemas/Cost'
            - $ref: '#/components/schemas/SandboxCostSummary'
            - type: 'null'
          description: >
            What the sandbox cost, with one word saying how far to trust it.
            Create and detail

            responses carry the full cost with its working; list rows carry only
            its label and

            total, from the same calculation. One object serves both, so the
            schema accepts either

            shape anywhere: a client that needs the working reads the detail.
            Null when no cost has

            been worked out. Absent from responses of a Cloud that does not
            report it yet.
        charge:
          oneOf:
            - $ref: '#/components/schemas/SandboxCharge'
            - type: 'null'
          description: >
            What BoxRouter charged to the workspace's credits for this sandbox:
            the reservation

            while it runs, then the amount charged once the provider's records
            are in. Present

            on credit-funded sandboxes in detail and list responses. Null for a
            sandbox paid with

            the workspace's own provider account (BYOK), for a credit-funded one
            whose

            reservation was released without a charge, and for one whose ledger
            record cannot be

            verified: BoxRouter reports no charge rather than a guess. `cost`
            still reports the

            provider's cost. Absent from create and other responses, and from a
            Cloud that does

            not report it yet. It is the ledger's amount, never derived from
            `cost` or from

            BoxRouter's clock.
        funded_until:
          type:
            - string
            - 'null'
          format: date-time
          description: >
            The time up to which the workspace's credits are reserved for this
            sandbox. A sandbox

            created without `lifetime_seconds` renews its reservation hourly
            while the balance

            covers it, so this moves later at each renewal; the sandbox ends at
            this time if the

            balance could not cover another hour. For a sandbox created with
            `lifetime_seconds`

            it is the end of that lifetime. Null for a sandbox paid with the
            workspace's own

            provider account (BYOK), which has no reservation. A reservation is
            a hold on the

            balance, never a cost: `charge` reports the credits reserved and
            then charged. Present

            on create and on detail and list reads; absent from a Cloud that
            does not report it yet.
        connectable:
          type: boolean
          description: >
            Whether interactive access to this sandbox is offered: a terminal,
            commands, files and

            processes. False for a sandbox an Actions job runs in, which holds
            that job's token and

            secrets; Cloud refuses these operations on it, before and after the
            job ends, and the

            dashboard shows no Connect action. True for every other sandbox. One
            rule, decided by

            Cloud; clients do not infer it from `origin`, which an Actions
            runner that has not yet

            served a job does not have. Present on detail and list reads; absent
            from a Cloud that

            does not report it yet.
        lifetime:
          $ref: '#/components/schemas/Lifetime'
        route:
          $ref: '#/components/schemas/SandboxRoute'
        contract:
          oneOf:
            - $ref: '#/components/schemas/Contract'
            - type: 'null'
          description: >-
            Null for a record with no recorded contract, such as one a
            provider-native route created.
        request:
          $ref: '#/components/schemas/SandboxRequestSnapshot'
        hidden_secrets:
          type:
            - object
            - 'null'
          propertyNames:
            $ref: '#/components/schemas/SecretName'
          additionalProperties:
            $ref: '#/components/schemas/HiddenSecretResult'
          description: >
            Public metadata for the request-only secret values, keyed by their
            submitted names.

            Each result contains only a placeholder and its allowed hosts. Null
            when the create

            submitted no secret values.
        tcp_ports:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/TcpPortEndpoint'
          description: >-
            Public host and port for each requested TCP listener, in request
            order.
        recorder:
          type:
            - object
            - 'null'
          description: >
            A tally of the gate calls made on this sandbox, allowed and refused,
            with the

            requirements line those calls relied on. It only tallies: it
            switches no gate on.
        limits:
          $ref: '#/components/schemas/SandboxLimits'
        volume:
          oneOf:
            - $ref: '#/components/schemas/VolumeAttachment'
            - type: 'null'
          description: Present when the sandbox is attached to a BoxRouter Volume.
        operation_id:
          type:
            - string
            - 'null'
          minLength: 1
          description: >
            Present on a destroy response: the workspace-owned destroy operation
            while lifecycle

            work remains (`state` is `destroying`), null once the destroy is
            confirmed. Absent

            from every other response.
        account:
          type: object
          required:
            - healthy
            - detail
          description: >
            Present only while the account's key no longer works (section 7);
            that sandbox's

            calls then answer account_unhealthy and state is unknown.
          properties:
            healthy:
              type: boolean
            detail:
              type:
                - string
                - 'null'
    SandboxFailure:
      type: object
      additionalProperties: false
      required:
        - summary
        - provider_state
        - native_code
        - native_message
        - observed_at
      description: >
        The most recent provider failure recorded with the sandbox's state. The
        summary is

        BoxRouter-authored plain language. `provider_state` is the raw provider
        status

        and is not covered by the sanitization guarantee; `native_code` and

        `native_message` contain only allowlisted, sanitized values. Repeated
        observations of the same failure keep the first

        observed_at; a changed failure gets a new timestamp. This object is
        stored with

        the state, cleared when the sandbox leaves error, and unchanged by
        unreadable

        provider observations.
      properties:
        summary:
          type: string
          minLength: 1
          maxLength: 200
          description: >
            BoxRouter-authored plain language chosen from a fixed set keyed by
            provider and

            provider_state. An unrecognised status uses "The provider reported
            this sandbox

            as failed."; it never guesses a cause.
        provider_state:
          type:
            - string
            - 'null'
          description: >-
            The provider's raw failure status, the same value native_state
            carries, or null if none was supplied.
        native_code:
          type:
            - string
            - 'null'
          pattern: ^[A-Za-z0-9_.:-]{1,64}$
          description: >-
            The provider's short structured failure code, or null if absent or
            unsafe.
        native_message:
          type:
            - string
            - 'null'
          maxLength: 512
          description: >-
            The provider's diagnostic text after redaction, or null if absent or
            unsafe.
        observed_at:
          type: string
          format: date-time
          description: When BoxRouter first observed this specific failure.
    UsageSource:
      description: >-
        Where a fact came from. provider: the provider's API told us, about this
        sandbox. published: the provider's docs or pricing page, not about this
        sandbox in particular. measured: BoxRouter checked it itself with a
        clock or in its own sandboxes. recorded: BoxRouter's own record of
        something it did or saw. calculated: worked out from other facts, each
        with its own source. unknown: nobody told us and we could not check.
      type: string
      enum:
        - provider
        - published
        - measured
        - recorded
        - calculated
        - unknown
    SandboxOrigin:
      description: >
        What created the sandbox, discriminated by source. github_actions is a
        BoxRouter

        Actions job; agents is an agent launch (POST /launches). Sandboxes
        created directly

        through the API have no origin.
      oneOf:
        - $ref: '#/components/schemas/ActionsSandboxOrigin'
        - $ref: '#/components/schemas/AgentsSandboxOrigin'
      discriminator:
        propertyName: source
        mapping:
          github_actions: '#/components/schemas/ActionsSandboxOrigin'
          agents: '#/components/schemas/AgentsSandboxOrigin'
    SandboxImage:
      type: object
      additionalProperties: false
      required:
        - value
        - source
      description: >
        The image a sandbox runs, with where that is known from: `recorded` for
        what the creation

        request asked for, `provider` where the provider reported which image or
        template it ran.
      properties:
        value:
          type: string
          minLength: 1
          description: >
            `standard` when the request omitted `image` (BoxRouter's standard
            image), `provider_default`

            when it opted out, `dockerfile` for an image built from a
            Dockerfile, or else the OCI

            reference or provider artifact the request named.
        source:
          $ref: '#/components/schemas/UsageSource'
    SandboxImageSetup:
      type: object
      required:
        - provider
        - duration_ms
      properties:
        provider:
          type: string
          minLength: 1
        duration_ms:
          type: integer
          minimum: 0
    Usage:
      title: Usage record
      description: >-
        What one sandbox used, as a collector saw it. One record is one coherent
        set of inputs for the calculator; where two sources disagree, a
        collector builds one record per source. Every fact carries where it came
        from, when it was observed and how. A fact nobody could establish has
        source `unknown` and a null value; it is never left out or filled with a
        default. `provider`, the record's key, is the only value without
        provenance.
      type: object
      additionalProperties: false
      required:
        - provider
        - started
        - region
        - size
        - intervals
        - creations
      properties:
        provider:
          description: The provider that ran the sandbox, as named in its price versions.
          type: string
          pattern: ^[a-z][a-z0-9-]*$
        class:
          description: >-
            The sandbox's class or runtime, which picks the rate set in the
            price version. If absent, it may be priced only when the price
            version has exactly one class; otherwise the cost is unknown.
          type: object
          additionalProperties: false
          required:
            - name
            - source
            - observed_at
            - how
          properties:
            name:
              type:
                - string
                - 'null'
              minLength: 1
            source:
              $ref: '#/components/schemas/UsageSource'
            observed_at:
              $ref: '#/components/schemas/PricingTimestamp'
            how:
              $ref: '#/components/schemas/UsageHow'
          if:
            $ref: '#/components/schemas/UsageIsUnknown'
          then:
            properties:
              name:
                type: 'null'
          else:
            properties:
              name:
                type: string
        started:
          description: When the sandbox started. It picks the price version in effect.
          type: object
          additionalProperties: false
          required:
            - at
            - source
            - observed_at
            - how
          properties:
            at:
              type:
                - string
                - 'null'
            source:
              $ref: '#/components/schemas/UsageSource'
            observed_at:
              $ref: '#/components/schemas/PricingTimestamp'
            how:
              $ref: '#/components/schemas/UsageHow'
          if:
            $ref: '#/components/schemas/UsageIsUnknown'
          then:
            properties:
              at:
                type: 'null'
          else:
            properties:
              at:
                $ref: '#/components/schemas/PricingTimestamp'
        region:
          description: The region the sandbox ran in, as the provider names it.
          type: object
          additionalProperties: false
          required:
            - name
            - source
            - observed_at
            - how
          properties:
            name:
              type:
                - string
                - 'null'
              minLength: 1
            source:
              $ref: '#/components/schemas/UsageSource'
            observed_at:
              $ref: '#/components/schemas/PricingTimestamp'
            how:
              $ref: '#/components/schemas/UsageHow'
          if:
            $ref: '#/components/schemas/UsageIsUnknown'
          then:
            properties:
              name:
                type: 'null'
          else:
            properties:
              name:
                type: string
        size:
          description: >-
            What the sandbox got. Each field is optional because a source may
            give only some of them; at least one is present unless the source is
            `unknown`. When GPUs are present, `gpu` and `gpu_model` are both
            recorded; without a GPU, both are absent.
          type: object
          additionalProperties: false
          required:
            - source
            - observed_at
            - how
          properties:
            cpu:
              description: vCPUs.
              type: number
              exclusiveMinimum: 0
            memory_mib:
              type: integer
              minimum: 1
            disk_mib:
              type: integer
              minimum: 1
            gpu:
              description: Number of allocated GPUs.
              type: integer
              minimum: 1
            gpu_model:
              description: The allocated model's gpu-registry identifier.
              type: string
              pattern: ^[a-z][a-z0-9-]*:[a-z0-9][a-z0-9-]*$
            source:
              $ref: '#/components/schemas/UsageSource'
            observed_at:
              $ref: '#/components/schemas/PricingTimestamp'
            how:
              $ref: '#/components/schemas/UsageHow'
          if:
            $ref: '#/components/schemas/UsageIsUnknown'
          then:
            not:
              anyOf:
                - required:
                    - cpu
                - required:
                    - memory_mib
                - required:
                    - disk_mib
                - required:
                    - gpu
                - required:
                    - gpu_model
          else:
            anyOf:
              - required:
                  - cpu
              - required:
                  - memory_mib
              - required:
                  - disk_mib
              - required:
                  - gpu
          allOf:
            - if:
                required:
                  - gpu
              then:
                required:
                  - gpu_model
            - if:
                required:
                  - gpu_model
              then:
                required:
                  - gpu
        intervals:
          description: >-
            Time in each billed state, one entry per period, in time order. A
            price version's minimum and increment rules apply to each entry.
          type: array
          minItems: 1
          items:
            type: object
            additionalProperties: false
            required:
              - state
              - seconds
              - source
              - observed_at
              - how
            properties:
              size:
                $ref: '#/components/schemas/UsageSize'
              snapshot_storage:
                $ref: '#/components/schemas/UsageSnapshotStorage'
              state:
                enum:
                  - running
                  - paused
                  - stopped
              seconds:
                description: >-
                  Exact seconds, or a range when a change was noticed late and
                  the period is only bounded.
                oneOf:
                  - type: number
                    minimum: 0
                  - $ref: '#/components/schemas/UsageRange'
                  - type: 'null'
              source:
                $ref: '#/components/schemas/UsageSource'
              observed_at:
                $ref: '#/components/schemas/PricingTimestamp'
              how:
                $ref: '#/components/schemas/UsageHow'
            if:
              $ref: '#/components/schemas/UsageIsUnknown'
            then:
              properties:
                seconds:
                  type: 'null'
            else:
              properties:
                seconds:
                  type:
                    - number
                    - object
        creations:
          description: >-
            How many times the sandbox was created: 1, plus any restores that
            the provider charges as a creation.
          type: object
          additionalProperties: false
          required:
            - count
            - source
            - observed_at
            - how
          properties:
            count:
              type:
                - integer
                - 'null'
              minimum: 0
            source:
              $ref: '#/components/schemas/UsageSource'
            observed_at:
              $ref: '#/components/schemas/PricingTimestamp'
            how:
              $ref: '#/components/schemas/UsageHow'
          if:
            $ref: '#/components/schemas/UsageIsUnknown'
          then:
            properties:
              count:
                type: 'null'
          else:
            properties:
              count:
                type: integer
        active_cpu:
          description: >-
            Seconds of CPU the sandbox actually used, for providers that bill
            active CPU. Absent where the provider does not bill it.
          type: object
          additionalProperties: false
          required:
            - seconds
            - source
            - observed_at
            - how
          properties:
            seconds:
              type:
                - number
                - 'null'
              minimum: 0
            source:
              $ref: '#/components/schemas/UsageSource'
            observed_at:
              $ref: '#/components/schemas/PricingTimestamp'
            how:
              $ref: '#/components/schemas/UsageHow'
          if:
            $ref: '#/components/schemas/UsageIsUnknown'
          then:
            properties:
              seconds:
                type: 'null'
          else:
            properties:
              seconds:
                type: number
        egress:
          description: >-
            Bytes the sandbox sent out. Absent where the provider does not bill
            it.
          type: object
          additionalProperties: false
          required:
            - bytes
            - source
            - observed_at
            - how
          properties:
            bytes:
              type:
                - integer
                - 'null'
              minimum: 0
            source:
              $ref: '#/components/schemas/UsageSource'
            observed_at:
              $ref: '#/components/schemas/PricingTimestamp'
            how:
              $ref: '#/components/schemas/UsageHow'
          if:
            $ref: '#/components/schemas/UsageIsUnknown'
          then:
            properties:
              bytes:
                type: 'null'
          else:
            properties:
              bytes:
                type: integer
        snapshot_storage:
          description: >-
            The stored snapshot size, or its known maximum when the provider
            does not report the actual size.
          type: object
          additionalProperties: false
          required:
            - source
            - observed_at
            - how
          properties:
            gb:
              type:
                - number
                - 'null'
              minimum: 0
            max_gb:
              type:
                - number
                - 'null'
              minimum: 0
            source:
              $ref: '#/components/schemas/UsageSource'
            observed_at:
              $ref: '#/components/schemas/PricingTimestamp'
            how:
              $ref: '#/components/schemas/UsageHow'
            bytes:
              description: Provider snapshot sizeBytes, kept as an exact integer.
              type: integer
              minimum: 0
          if:
            $ref: '#/components/schemas/UsageIsUnknown'
          then:
            properties:
              gb:
                type: 'null'
          else:
            anyOf:
              - required:
                  - gb
                properties:
                  gb:
                    type: number
              - required:
                  - bytes
    LegacyZeroGpuUsage:
      type: object
      additionalProperties: false
      required:
        - provider
        - started
        - region
        - size
        - intervals
        - creations
      properties:
        provider:
          $ref: '#/components/schemas/provider'
        class:
          $ref: '#/components/schemas/class'
        started:
          $ref: '#/components/schemas/started'
        region:
          $ref: '#/components/schemas/region'
        size:
          type: object
          additionalProperties: false
          required:
            - source
            - observed_at
            - how
          properties:
            cpu:
              $ref: '#/components/schemas/cpu'
            memory_mib:
              $ref: '#/components/schemas/memory_mib'
            disk_mib:
              $ref: '#/components/schemas/disk_mib'
            gpu:
              const: 0
            gpu_model:
              $ref: '#/components/schemas/gpu_model'
            source:
              $ref: '#/components/schemas/UsageSource'
            observed_at:
              $ref: '#/components/schemas/PricingTimestamp'
            how:
              $ref: '#/components/schemas/UsageHow'
          if:
            $ref: '#/components/schemas/UsageIsUnknown'
          then:
            $ref: '#/components/schemas/then'
          else:
            $ref: '#/components/schemas/else'
          allOf:
            - if:
                required:
                  - gpu
              then:
                required:
                  - gpu_model
            - if:
                required:
                  - gpu_model
              then:
                required:
                  - gpu
        intervals:
          $ref: '#/components/schemas/intervals'
        creations:
          $ref: '#/components/schemas/creations'
        active_cpu:
          $ref: '#/components/schemas/active_cpu'
        egress:
          $ref: '#/components/schemas/egress'
    Cost:
      title: Cost
      description: >-
        A provider-sourced sandbox cost. Unknown has a null total; known totals
        are exact decimal strings. Hourly rate-card quotes may be ranges.
      type: object
      additionalProperties: false
      required:
        - label
        - total
        - lines
        - held_back_by
        - exclusions
        - price_version
        - as_of
      properties:
        label:
          description: >-
            reported: a provider amount verified at list price; calculated:
            provider usage priced at stored list rates; unknown: required
            provider evidence or a rate is missing.
          enum:
            - reported
            - calculated
            - unknown
        total:
          description: An exact USD amount, low equal to high, or null for unknown.
          anyOf:
            - $ref: '#/components/schemas/CostTotalRange'
            - type: 'null'
        lines:
          description: >-
            The working: one line per charged resource. Empty when the
            provider's own figure is all we have, or when nothing could be
            worked out.
          type: array
          items:
            type: object
            additionalProperties: false
            required:
              - what
              - quantity
              - unit
              - rate
              - amount
              - quantity_source
            properties:
              what:
                enum:
                  - cpu
                  - memory
                  - disk
                  - gpu
                  - machine
                  - creation
                  - egress
                  - snapshot_storage
              quantity:
                $ref: '#/components/schemas/PricingDecimal'
              unit:
                description: >-
                  The price version's unit for this rate, for example
                  vcpu-second.
                type: string
                minLength: 1
              rate:
                $ref: '#/components/schemas/PricingDecimal'
                description: US dollars per unit, as the price version states it.
              amount:
                $ref: '#/components/schemas/PricingDecimal'
              quantity_source:
                $ref: '#/components/schemas/CostSource'
                description: >-
                  The source of the usage facts the quantity came from; the
                  least certain one when it came from several.
              text:
                description: >-
                  The line as a sentence a person reads, with its numbers: the
                  quantity, the rate and the amount.
                type: string
                minLength: 1
              sources:
                description: >-
                  Where each number of the line came from, as words: the
                  quantity, the rate and the amount.
                type: object
                additionalProperties: false
                required:
                  - amount
                properties:
                  quantity:
                    type: string
                    minLength: 1
                  rate:
                    type: string
                    minLength: 1
                  amount:
                    type: string
                    minLength: 1
        held_back_by:
          description: >-
            Reasons in plain words. Shared pricing findings are projected to
            their text for the HTTP response.
          type: array
          items:
            type: string
            minLength: 1
        exclusions:
          description: >-
            What the figure leaves out, such as plan fees, credits and
            discounts.
          type: array
          items:
            type: string
            minLength: 1
        price_version:
          description: >-
            The id of the price version used, which carries the quotes. Null
            when none was in effect.
          type:
            - string
            - 'null'
          pattern: >-
            ^[a-z][a-z0-9-]*@[0-9]{4}-[0-9]{2}-[0-9]{2}(?:-([01][0-9]|2[0-3])[0-5][0-9][0-5][0-9]Z)?$
        as_of:
          $ref: '#/components/schemas/PricingTimestamp'
          description: >-
            When Cloud calculated or recorded the cost. A sandbox that has not
            ended has no cost yet.
        per_hour:
          $ref: '#/components/schemas/CostMoneyRange'
          description: >-
            US dollars per hour for an ended sandbox; no hourly cost is returned
            while it is running.
        reported_figure:
          description: >-
            Where a `reported` total came from. Present exactly when the label
            is `reported`.
          type: object
          additionalProperties: false
          required:
            - source
            - observed_at
            - how
          properties:
            source:
              $ref: '#/components/schemas/CostSource'
              const: provider
            observed_at:
              $ref: '#/components/schemas/PricingTimestamp'
            how:
              description: The API call that returned the figure.
              type: string
              minLength: 1
        summary:
          description: >-
            The total as one sentence, or why there is none. The sentences of
            `lines[].text` add up to it.
          type: string
          minLength: 1
      allOf:
        - if:
            properties:
              label:
                const: unknown
            required:
              - label
          then:
            properties:
              total:
                type: 'null'
          else:
            properties:
              total:
                type: object
        - if:
            properties:
              label:
                const: reported
            required:
              - label
          then:
            required:
              - reported_figure
          else:
            not:
              required:
                - reported_figure
    SandboxCostSummary:
      type: object
      additionalProperties: false
      required:
        - label
        - total
      description: >
        The label and total of a sandbox's cost, as list rows carry them. Both
        are the full cost's:

        see the `cost` schema for what they mean. Actions billing adds the
        cost's `summary`, the one

        sentence that says what the total is or why there is none; list rows do
        not carry it.
      properties:
        label:
          $ref: '#/components/schemas/CostLabel'
        total:
          $ref: '#/components/schemas/CostTotal'
        summary:
          $ref: '#/components/schemas/summary'
      if:
        properties:
          label:
            const: unknown
        required:
          - label
      then:
        properties:
          total:
            type: 'null'
      else:
        properties:
          total:
            type: object
    SandboxCharge:
      type: object
      additionalProperties: false
      required:
        - status
        - reserved_nanodollars
        - held_nanodollars
        - lifetime_seconds
      description: >
        The credit ledger's account of one credit-funded sandbox, in billionths
        of a US dollar as

        exact decimal strings. `reserved` while it runs: the reservation is held
        and nothing is

        charged. `pending` once it has ended and the provider's records are not
        in: the charge

        is set from them, the reservation stays held, and no amount is reported
        until they

        arrive. `charged` once the records set the charge: `amount_nanodollars`
        is the current

        charge and `first_charged_nanodollars` the charge as first settled. A
        later correction

        moves the charge by its `delta_nanodollars` and never reopens the
        reservation.
      properties:
        status:
          type: string
          enum:
            - reserved
            - pending
            - charged
          x-boxrouter-open-enum: true
          description: Clients must handle unknown values explicitly.
        reserved_nanodollars:
          type: string
          maxLength: 19
          pattern: ^(0|[1-9][0-9]{0,18})$
          description: >-
            The credit reserved when the sandbox started, for the lifetime it
            asked for.
        held_nanodollars:
          type: string
          maxLength: 19
          pattern: ^(0|[1-9][0-9]{0,18})$
          description: >-
            What is still reserved from the balance for this sandbox. Zero once
            it is charged.
        lifetime_seconds:
          type:
            - integer
            - 'null'
          minimum: 1
          description: >-
            The lifetime the reservation was made for. Null when it is not
            recorded.
        funding:
          type: string
          enum:
            - fixed
            - rolling
            - ending_unfunded
          x-boxrouter-open-enum: true
          description: >
            How the sandbox's credits are reserved. `fixed`: all of the lifetime
            asked for was

            reserved when the sandbox started. `rolling`: the sandbox was
            created without a lifetime and

            credits are reserved one hour at a time, renewed before each hour
            ends; `funded_until` on

            the sandbox says how far it is funded. `ending_unfunded`: a renewal
            could not be

            funded from the balance, so the sandbox ends at `funded_until`.
            Clients must handle

            unknown values explicitly. Absent from a Cloud that does not report
            it yet.
        first_charged_nanodollars:
          type: string
          maxLength: 19
          pattern: ^(0|[1-9][0-9]{0,18})$
          description: >-
            The charge as first settled from the provider's records. Present
            only when charged.
        amount_nanodollars:
          type: string
          maxLength: 19
          pattern: ^(0|[1-9][0-9]{0,18})$
          description: >
            The charge now: the first charge moved by every correction. Present
            only when charged;

            a pending or reserved charge carries no amount.
        returned_nanodollars:
          type: string
          maxLength: 19
          pattern: ^(0|[1-9][0-9]{0,18})$
          description: >-
            What went back to the balance when the first charge was settled, the
            reservation less that charge. Present only when charged.
        create_fee_nanodollars:
          type: string
          maxLength: 19
          pattern: ^(0|[1-9][0-9]{0,18})$
          description: >
            The flat per-create fee the price book added to the first charge;
            zero while no book

            sets one. It is inside `amount_nanodollars`, not on top of it.
            Present only when

            charged, and absent from a Cloud that does not report it yet.
        basis:
          type:
            - string
            - 'null'
          enum:
            - reported
            - calculated
            - null
          x-boxrouter-open-enum: true
          description: >
            How the provider's cost for this sandbox was established, as
            `cost.label` says for it:

            `reported` for the provider's own figure, `calculated` for one
            worked out from its

            usage records. Null when the cost's source is not known. Present
            only when charged.
        settled_at:
          type: string
          format: date-time
          description: >-
            When the first charge was recorded in the ledger. Present only when
            charged.
        corrections:
          type: array
          maxItems: 1000
          description: >
            Later changes to the charge, oldest first, when the provider's
            records or reported cost

            for this sandbox changed after it was first charged. Independent
            credits an operator

            gives are not corrections. Present only when charged; empty when
            none.
          items:
            $ref: '#/components/schemas/SandboxChargeCorrection'
      allOf:
        - if:
            properties:
              status:
                const: charged
            required:
              - status
          then:
            required:
              - first_charged_nanodollars
              - amount_nanodollars
              - returned_nanodollars
              - settled_at
              - corrections
          else:
            properties:
              first_charged_nanodollars: false
              amount_nanodollars: false
              returned_nanodollars: false
              create_fee_nanodollars: false
              basis: false
              settled_at: false
              corrections: false
    Lifetime:
      type: object
      required:
        - seconds
        - remaining_seconds
        - ends_at
        - kept_until
        - at_end
        - max_seconds
        - extendable
      description: >
        How long the sandbox may live. It counts from the provider's create, as
        with the

        provider's own SDK (BoxRouter's clock starts when it sends the create).
        Whether paused

        time counts depends on the provider.
      properties:
        seconds:
          type:
            - integer
            - 'null'
          minimum: 0
          description: >
            The lifetime in seconds. 0 only for a sandbox that has no lifetime
            record (one that

            ended before lifetimes were recorded). Null for a sandbox created
            with no lifetime

            (`lifetime_seconds: null`), which runs until it is destroyed.
        remaining_seconds:
          type:
            - integer
            - 'null'
          minimum: 0
          description: >
            As of observed_at. Equal to seconds while creating, and frozen while
            the sandbox is not

            running. Null for a sandbox with no lifetime.
        ends_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >
            Set only while running. The end never comes before it; how soon
            after is not

            promised. Null while creating, paused or ended, and for a sandbox
            with no lifetime.
        kept_until:
          type:
            - string
            - 'null'
          format: date-time
          description: >
            While paused: when the sandbox is destroyed if it is not resumed, 30

            days after it last ran, sooner where the provider keeps it for less.
            Where the lifetime

            keeps counting while paused, the sandbox ends when the lifetime runs
            out, so

            kept_until is that moment when it falls inside the 30 days;
            extending the lifetime

            moves it. Where the clock stops while paused, the full 30 days
            apply.
        at_end:
          type:
            - string
            - 'null'
          enum:
            - destroy
            - pause
            - null
          description: >-
            What happens when the lifetime is used up. Null for a sandbox with
            no lifetime.
        max_seconds:
          description: >
            The route's longest single run, from one start to the next pause or
            end, as

            narrowed for this account. A declared number: an integer,
            "unlimited", "unknown"

            or a floor.
          oneOf:
            - type: integer
              minimum: 1
            - type: string
              enum:
                - unlimited
                - unknown
            - type: object
              required:
                - at_least
              additionalProperties: false
              properties:
                at_least:
                  type: integer
                  minimum: 1
        extendable:
          type: boolean
    SandboxRoute:
      type: object
      required:
        - provider
        - class
        - adapter_version
        - selection
      description: >
        The adapter that made this sandbox. Support questions start at
        adapter_version. A sandbox

        with no recorded contract still names its provider and account; its
        class and

        adapter_version are null.
      properties:
        id:
          type:
            - string
            - 'null'
        provider:
          type: string
        class:
          type:
            - string
            - 'null'
          description: >-
            The declaration's class, such as a provider's VM class; null when
            the adapter publishes one declaration.
        adapter_version:
          type:
            - string
            - 'null'
        account_id:
          type:
            - string
            - 'null'
        supply:
          type:
            - string
            - 'null'
        region:
          type:
            - string
            - 'null'
        native_id:
          type:
            - string
            - 'null'
          description: Provider-owned sandbox identifier; null when unavailable.
        selection:
          oneOf:
            - $ref: '#/components/schemas/SandboxRouteSelection'
            - type: 'null'
          description: Null in listings, which look at no route.
    Contract:
      type: object
      required:
        - spec_version
        - gates
        - resources
        - attested
      description: >-
        What this sandbox may use, fixed at creation. No gate is ever added to a
        running sandbox.
      properties:
        spec_version:
          type: string
          pattern: ^(boxspec|sandbox-provider-spec)/[0-9]+\.[0-9]+(-draft(\.[0-9]+)?)?$
        gates:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/GrantedGate'
        resources:
          type: object
          additionalProperties: true
          description: >-
            What was provisioned, plus the adapter's answers for long_running
            and extendable_lifetime. A value may be "unknown" or null.
        attested:
          type: object
          description: >-
            Which resource values rest on a dated citation rather than on
            adapter code.
          additionalProperties:
            type: object
            required:
              - source
              - read
            properties:
              source:
                type: string
              read:
                type: string
                format: date
    SandboxRequestSnapshot:
      type: object
      additionalProperties: true
      description: >
        The recorded creation request after server-side expansion and
        defaulting, without

        request-only secret values, environment values or labels. A sandbox can
        outlive the

        create-request schema that was current when it was made, so this
        historical snapshot

        accepts fields from earlier contract versions. Clients should interpret
        only fields

        they recognize and preserve unknown fields when displaying or storing
        the snapshot.
    HiddenSecretResult:
      type: object
      additionalProperties: false
      required:
        - placeholder
        - hosts
      properties:
        placeholder:
          type: string
          minLength: 1
          description: The safe token to place where this secret should be used.
        hosts:
          type: array
          uniqueItems: true
          items:
            allOf:
              - $ref: '#/components/schemas/SandboxProviderSpecHostname'
              - type: string
          description: Hosts to which the adapter sends this secret.
    TcpPortEndpoint:
      type: object
      additionalProperties: false
      required:
        - host
        - port
        - tls
      properties:
        host:
          type: string
          minLength: 1
        port:
          type: integer
          minimum: 1
          maximum: 65535
        tls:
          type: string
          enum:
            - none
            - terminated
    SandboxLimits:
      type: object
      properties:
        buffered_output_bytes:
          type: integer
          minimum: 1
          description: Maximum combined stdout/stderr for the buffered command endpoint.
        file_transfer_bytes:
          type: integer
          minimum: 1
          default: 1048576
          description: Maximum file size of `readFile` and `writeFile` on this route.
        upload_max_bytes:
          type: integer
          minimum: 0
          description: Per route, the largest file `createSandboxUpload` accepts.
        download_max_bytes:
          type: integer
          minimum: 0
          description: Per route, the largest file `createSandboxDownload` accepts.
        inline_transfer_max_bytes:
          type: integer
          minimum: 1
          description: >
            Largest file this route serves inline in one createSandboxDownload
            (send

            `inline_below`) or relays for upload, cheaper than its transfer
            link;

            absent when the route has none.
    VolumeAttachment:
      type: object
      additionalProperties: false
      required:
        - id
        - path
        - access
        - restored_checkpoint
        - restore_duration_ms
      properties:
        id:
          $ref: '#/components/schemas/VolumeId'
        path:
          type: string
        access:
          type: string
          enum:
            - write
            - read
            - shared
            - branch
        restored_checkpoint:
          type:
            - integer
            - 'null'
          minimum: 1
        restore_duration_ms:
          type:
            - integer
            - 'null'
          minimum: 0
    ApiErrorResponse:
      type: object
      required:
        - error
      description: >-
        The one error body every failing call answers. It leads with what to do:
        `retry` says whether to send the call again, `fix` says what to change,
        `outcome` says what happened, and `doc_url` links to the page that
        explains the code. Clients retry `retry: safe` for you with the same
        idempotency key.
      x-sandbox-provider-spec-codes:
        - no_eligible_route
        - knob_not_named
        - unrecognised_word
        - invalid_request
        - not_named
        - gate_unavailable
        - account_unhealthy
        - lifetime_limit
        - lifetime_used_up
        - not_running
        - invalid_state
        - sandbox_ended
        - not_found
        - provider_error
        - timeout
        - contract_violation
      properties:
        error:
          type: object
          required:
            - code
            - message
            - request_id
            - outcome
            - retry
            - retry_after_seconds
          properties:
            code:
              type: string
              description: >
                Stable machine category. Operation failures use
                SandboxProviderSpec error codes,

                including invalid_request, invalid_state, not_found,
                unauthorized,

                incompatible_requirements, no_eligible_route,
                capacity_unavailable,

                capability_unavailable, contract_violation, resource_limit,
                timeout and

                provider_error. Hosted service failures add method_not_allowed,

                unauthenticated, forbidden, actions_sandbox_protected,

                insufficient_credit, spend_limit_exceeded,

                provider_not_enabled, credentials_rejected, conflict,
                rate_limited, provider_quota, request_timeout, overloaded,

                database_unavailable, payment_method_required, payment_declined,
                promotion_already_redeemed, account_exists, and internal_error.
                unsupported_feature and

                output_limit are earlier names still returned by some routes.

                Organization and membership operations also use
                organization_changed, last_admin,

                stale_membership, directory_managed and change_in_progress. Key
                ownership and

                invitation operations use idempotency_key_reused and conflict.

                Credit refunds and purchase quotes also use
                refund_window_closed,

                nothing_to_refund, refund_below_minimum, refund_in_progress,

                purchase_in_progress, dispute_open, already_refunded,

                refund_amount_changed, refund_fee_unavailable, quote_changed,

                session_required, refund_daily_limit, refund_rate_limit,

                refund_retry_requires_support, idempotency_key_reused and
                fraud_review.

                Card setup adds card_setup_rate_limit (429, with Retry-After): a
                workspace may start five

                card setups an hour.

                A provider that refuses the request for its own plan or quota
                limit answers

                429 provider_quota with the provider's words in native_message;
                rate_limited is

                BoxRouter's own limit.

                Routing Prevent Overrides refuses a request containing
                preferences.order,

                preferences.sort or preferences.allow_fallbacks with
                routing_overrides_forbidden,

                outcome not_started and details.fields naming the prohibited
                inputs. No provider

                effect occurs.

                Launch operations also use invalid_request, secret_missing,
                agent_not_found,

                no_eligible_route and launch_failed.

                A process or terminal is observed by one API task. When that
                task stops, process

                output, result and stdin answer 410 process_observer_lost
                (reading or cancelling the

                process still works), and a terminal on a provider that cannot
                reattach it answers

                410 terminal_observer_lost. invalid_observer_hop (403) refuses
                an internal hop

                between API tasks that is not signed; clients never send one.

                Opening a preview that the provider answered with other access
                than the request

                asked for returns 502 preview_access_refused: that preview is
                never returned, and

                details say whether it was ended.

                Starting a process with wait_for_port answers 409
                port_not_listening, outcome partial,

                when the process exits before the port accepts connections or
                the port stays closed for

                30 seconds; the process is ended and details carry the output so
                far.

                A request that must store content (a volume, a saved artifact)
                under transient content

                retention answers 409 privacy_persistence_conflict with outcome
                not_started.

                A sandbox request that stops before anything is created also
                answers

                lifetime_cap_exceeded, knob_not_named and unrecognised_word
                (400), and price_unknown and

                policy_denied (409), each with outcome not_started; the Actions
                codes job_claim_lost,

                actions_authority_changed, actions_candidate_ceiling_withdrawn
                and

                actions_candidate_outside_ceiling (409) say the job's claim,
                settings or admitted routes

                changed; provider_budget_exhausted (409) says a run's provider
                budget allows no

                further create. A create that names an image Cloud cannot use
                answers 400

                image_architecture_unsupported, image_digest_resolution_failed,

                image_preparation_unsupported or
                private_image_managed_route_unavailable, and

                privacy_admission_unavailable when privacy cannot be enforced;
                each says what to change.

                Launch and source-repository refusals name the repository or
                manifest fault (code_ref_not_found,

                code_repository_*, source_*, invalid_source_manifest,
                invalid_manifest_encoding,

                invalid_run_spec, repository_*, reserved_env_refused,
                launch_run_position_conflict,

                code_reference_moved, dockerfile_context_unsupported,
                image_tag_unresolved,

                recovery_sandbox_mismatch); the GitHub-side ones
                (source_rate_limited,

                source_resolution_failed, source_resolution_timeout,
                code_repository_resolution_failed)

                are safe to resend. image_setup_timeout,
                managed_funding_unavailable,

                lifetime_funding_conflict, candidate_admission_unavailable,
                secrets_unavailable and the

                Actions candidate codes (actions_candidate_record_invalid,
                actions_create_budget_exhausted,

                actions_create_format_mismatch) complete the creation and
                extension refusals.

                dispatch_limit_reached, inline_secret_values_refused and
                launch_incomplete come from

                launch runs, provider_policy_unknown from an operation whose
                privacy evidence cannot be

                verified, and quota_exceeded from a full managed provider
                account.

                Volume operations also use volume_busy, volume_lease_lost,
                volume_not_attached,

                volume_incompatible, volume_save_failed and
                volume_restore_failed. Creating a

                sandbox on a volume whose writer is ending waits for the release
                (at most 120

                seconds) before it can answer volume_busy.

                A team member's new personal API key is paused until WorkOS
                membership sync catches

                up: it answers 403 forbidden whose message and fix say the key
                becomes active once

                the team membership syncs, usually within a minute, and the call
                can be retried.

                Clients must preserve and handle unknown categories explicitly.
              x-boxrouter-error-codes:
                account_exists:
                  - 409
                account_unhealthy:
                  - 402
                actions_authority_changed:
                  - 409
                actions_candidate_ceiling_withdrawn:
                  - 409
                actions_candidate_outside_ceiling:
                  - 409
                actions_candidate_record_invalid:
                  - 409
                actions_create_budget_exhausted:
                  - 409
                actions_create_format_mismatch:
                  - 409
                actions_sandbox_protected:
                  - 403
                agent_not_found:
                  - 404
                already_refunded:
                  - 409
                authorization_error:
                  - 403
                candidate_admission_unavailable:
                  - 503
                capability_unavailable:
                  - 409
                  - 503
                capability_unverified:
                  - 409
                card_setup_rate_limit:
                  - 429
                change_in_progress:
                  - 409
                code_ref_not_found:
                  - 404
                code_reference_moved:
                  - 409
                code_repository_not_authorized:
                  - 403
                code_repository_not_found:
                  - 404
                code_repository_not_private:
                  - 400
                code_repository_not_public:
                  - 404
                code_repository_resolution_failed:
                  - 502
                command_failed:
                  - 409
                command_observation_busy:
                  - 409
                conflict:
                  - 409
                contract_violation:
                  - 409
                credentials_rejected:
                  - 409
                  - 422
                database_unavailable:
                  - 503
                directory_managed:
                  - 409
                dispatch_limit_reached:
                  - 409
                dispute_open:
                  - 409
                dockerfile_context_unsupported:
                  - 400
                expired:
                  - 410
                forbidden:
                  - 403
                fraud_review:
                  - 409
                gate_unavailable:
                  - 409
                idempotency_key_reused:
                  - 409
                  - 422
                identity_unavailable:
                  - 503
                image_architecture_unsupported:
                  - 400
                image_digest_resolution_failed:
                  - 400
                image_preparation_unsupported:
                  - 400
                image_setup_timeout:
                  - 504
                image_tag_unresolved:
                  - 400
                inline_secret_values_refused:
                  - 422
                insufficient_credit:
                  - 402
                internal_error:
                  - 500
                invalid_manifest_encoding:
                  - 400
                invalid_observer_hop:
                  - 403
                invalid_request:
                  - 400
                  - 413
                  - 422
                  - 428
                invalid_run_spec:
                  - 400
                invalid_source_manifest:
                  - 400
                invalid_state:
                  - 409
                job_claim_lost:
                  - 409
                knob_not_named:
                  - 400
                last_admin:
                  - 409
                launch_failed:
                  - 409
                launch_incomplete:
                  - 409
                launch_run_position_conflict:
                  - 409
                lifetime_cap_exceeded:
                  - 400
                lifetime_funding_conflict:
                  - 409
                lifetime_limit:
                  - 409
                lifetime_used_up:
                  - 409
                managed_funding_unavailable:
                  - 503
                method_not_allowed:
                  - 405
                no_eligible_route:
                  - 409
                not_found:
                  - 404
                not_named:
                  - 409
                not_running:
                  - 409
                nothing_to_refund:
                  - 409
                organization_changed:
                  - 409
                output_limit:
                  - 413
                overloaded:
                  - 503
                payment_declined:
                  - 402
                payment_method_required:
                  - 409
                payment_provider_rejected:
                  - 502
                payment_provider_unavailable:
                  - 503
                payments_unavailable:
                  - 503
                policy_denied:
                  - 409
                port_not_listening:
                  - 409
                preview_access_refused:
                  - 502
                price_unknown:
                  - 409
                privacy_admission_unavailable:
                  - 400
                privacy_persistence_conflict:
                  - 409
                private_image_managed_route_unavailable:
                  - 400
                process_observer_lost:
                  - 410
                promotion_already_redeemed:
                  - 409
                promotion_code_invalid:
                  - 404
                provider_budget_exhausted:
                  - 409
                provider_error:
                  - 502
                provider_not_enabled:
                  - 409
                provider_policy_unknown:
                  - 409
                provider_quota:
                  - 429
                purchase_in_progress:
                  - 409
                quota_exceeded:
                  - 429
                quote_changed:
                  - 409
                rate_limited:
                  - 429
                recovery_sandbox_mismatch:
                  - 409
                refund_amount_changed:
                  - 409
                refund_below_minimum:
                  - 409
                refund_daily_limit:
                  - 429
                refund_fee_unavailable:
                  - 409
                refund_in_progress:
                  - 409
                refund_rate_limit:
                  - 429
                refund_retry_requires_support:
                  - 409
                refund_window_closed:
                  - 409
                repository_file_unsupported:
                  - 400
                repository_too_large:
                  - 400
                request_timeout:
                  - 408
                reserved_env_refused:
                  - 400
                  - 422
                resource_limit:
                  - 413
                  - 507
                routing_overrides_forbidden:
                  - 400
                run_limit_exceeded:
                  - 429
                sandbox_ended:
                  - 410
                secret_missing:
                  - 400
                secrets_unavailable:
                  - 503
                session_required:
                  - 403
                source_file_not_found:
                  - 400
                source_file_too_large:
                  - 413
                source_rate_limited:
                  - 503
                source_ref_not_found:
                  - 400
                source_repository_not_accessible:
                  - 404
                source_repository_not_found:
                  - 400
                source_repository_not_private:
                  - 400
                source_repository_not_public:
                  - 400
                source_resolution_failed:
                  - 502
                source_resolution_timeout:
                  - 504
                spend_limit_exceeded:
                  - 402
                stale_membership:
                  - 409
                terminal_closed:
                  - 410
                terminal_observer_lost:
                  - 410
                timeout:
                  - 504
                unauthenticated:
                  - 401
                unavailable:
                  - 503
                unrecognised_word:
                  - 400
                unsupported_feature:
                  - 422
                volume_busy:
                  - 409
                volume_incompatible:
                  - 409
                volume_lease_lost:
                  - 409
                volume_not_attached:
                  - 409
                volume_restore_failed:
                  - 502
                volume_save_failed:
                  - 409
                  - 502
                volume_unavailable:
                  - 409
                wrong_region:
                  - 421
              x-boxrouter-error-retry:
                account_exists: after_fix
                account_unhealthy: after_fix
                actions_authority_changed: after_fix
                actions_candidate_ceiling_withdrawn: after_fix
                actions_candidate_outside_ceiling: after_fix
                actions_candidate_record_invalid: after_fix
                actions_create_budget_exhausted: after_fix
                actions_create_format_mismatch: after_fix
                actions_sandbox_protected: never
                agent_not_found: after_fix
                already_refunded: never
                authorization_error: check_outcome
                candidate_admission_unavailable: never
                capability_unavailable: check_outcome
                capability_unverified: after_fix
                card_setup_rate_limit: safe
                change_in_progress: safe
                code_ref_not_found: after_fix
                code_reference_moved: after_fix
                code_repository_not_authorized: after_fix
                code_repository_not_found: after_fix
                code_repository_not_private: after_fix
                code_repository_not_public: after_fix
                code_repository_resolution_failed: safe
                command_failed: after_fix
                command_observation_busy: safe
                conflict: check_outcome
                contract_violation: check_outcome
                credentials_rejected: after_fix
                database_unavailable: check_outcome
                directory_managed: never
                dispatch_limit_reached: after_fix
                dispute_open: after_fix
                dockerfile_context_unsupported: after_fix
                expired: check_outcome
                forbidden: after_fix
                fraud_review: safe
                gate_unavailable: after_fix
                idempotency_key_reused: after_fix
                identity_unavailable: safe
                image_architecture_unsupported: after_fix
                image_digest_resolution_failed: after_fix
                image_preparation_unsupported: after_fix
                image_setup_timeout: after_fix
                image_tag_unresolved: after_fix
                inline_secret_values_refused: after_fix
                insufficient_credit: after_fix
                internal_error: never
                invalid_manifest_encoding: after_fix
                invalid_observer_hop: after_fix
                invalid_request: after_fix
                invalid_run_spec: after_fix
                invalid_source_manifest: after_fix
                invalid_state: check_outcome
                job_claim_lost: after_fix
                knob_not_named: after_fix
                last_admin: after_fix
                launch_failed: check_outcome
                launch_incomplete: check_outcome
                launch_run_position_conflict: after_fix
                lifetime_cap_exceeded: after_fix
                lifetime_funding_conflict: after_fix
                lifetime_limit: check_outcome
                lifetime_used_up: after_fix
                managed_funding_unavailable: safe
                method_not_allowed: after_fix
                no_eligible_route: after_fix
                not_found: check_outcome
                not_named: after_fix
                not_running: after_fix
                nothing_to_refund: never
                organization_changed: safe
                output_limit: check_outcome
                overloaded: safe
                payment_declined: after_fix
                payment_method_required: after_fix
                payment_provider_rejected: check_outcome
                payment_provider_unavailable: check_outcome
                payments_unavailable: safe
                policy_denied: after_fix
                port_not_listening: after_fix
                preview_access_refused: never
                price_unknown: after_fix
                privacy_admission_unavailable: after_fix
                privacy_persistence_conflict: after_fix
                private_image_managed_route_unavailable: after_fix
                process_observer_lost: check_outcome
                promotion_already_redeemed: never
                promotion_code_invalid: after_fix
                provider_budget_exhausted: never
                provider_error: check_outcome
                provider_not_enabled: after_fix
                provider_policy_unknown: after_fix
                provider_quota: after_fix
                purchase_in_progress: safe
                quota_exceeded: safe
                quote_changed: after_fix
                rate_limited: safe
                recovery_sandbox_mismatch: check_outcome
                refund_amount_changed: after_fix
                refund_below_minimum: never
                refund_daily_limit: safe
                refund_fee_unavailable: safe
                refund_in_progress: safe
                refund_rate_limit: safe
                refund_retry_requires_support: never
                refund_window_closed: never
                repository_file_unsupported: after_fix
                repository_too_large: after_fix
                request_timeout: safe
                reserved_env_refused: after_fix
                resource_limit: check_outcome
                routing_overrides_forbidden: after_fix
                run_limit_exceeded: after_fix
                sandbox_ended: check_outcome
                secret_missing: after_fix
                secrets_unavailable: never
                session_required: never
                source_file_not_found: after_fix
                source_file_too_large: after_fix
                source_rate_limited: safe
                source_ref_not_found: after_fix
                source_repository_not_accessible: after_fix
                source_repository_not_found: after_fix
                source_repository_not_private: after_fix
                source_repository_not_public: after_fix
                source_resolution_failed: safe
                source_resolution_timeout: safe
                spend_limit_exceeded: after_fix
                stale_membership: after_fix
                terminal_closed: after_fix
                terminal_observer_lost: after_fix
                timeout: check_outcome
                unauthenticated: after_fix
                unavailable: safe
                unrecognised_word: after_fix
                unsupported_feature: after_fix
                volume_busy: after_fix
                volume_incompatible: after_fix
                volume_lease_lost: after_fix
                volume_not_attached: after_fix
                volume_restore_failed: check_outcome
                volume_save_failed: check_outcome
                volume_unavailable: after_fix
                wrong_region: after_fix
            message:
              type: string
            details:
              type: object
              description: >
                Code-specific context, spelled for programs. no_eligible_route
                carries considered,

                excluded, closest and nearest; knob_not_named the knob and its
                values;

                unrecognised_word the path, the word and the known ones;
                not_named the gate, what

                the call needed beyond the grant and the corrected requirements
                line; gate_unavailable

                the gate and account; lifetime_limit the ceiling and this run. A
                creation that

                stopped before a sandbox existed may also carry
                `fallbacks_allowed`, `stopped_reason`

                and `attempts`, spelled and bounded as in the sandbox route
                selection.

                capability_unavailable may identify the needed capability. A
                launch preparation failure can follow sandbox creation;

                inspect outcome and cleanup details before creating another.
                Clients must

                preserve fields they do not know.
              properties:
                selection_version:
                  type: integer
                  minimum: 0
                  description: >-
                    Current selected organization version for
                    organization_changed.
                considered:
                  type: integer
                  minimum: 0
                  description: no_eligible_route only; how many routes were considered.
                excluded:
                  type: array
                  description: >-
                    no_eligible_route only; every considered route that cannot
                    serve the request. Each entry names its `provider` and the
                    checks it failed (`failed` for a sandbox request, `reasons`
                    and `exclusions` for a launch); clients must preserve fields
                    they do not know.
                  items:
                    type: object
                    required:
                      - provider
                    properties:
                      provider:
                        type: string
                closest:
                  type:
                    - object
                    - 'null'
                  description: >-
                    no_eligible_route only; the excluded route that fails fewest
                    checks, or null.
                nearest:
                  type: array
                  description: >-
                    no_eligible_route only; the smallest changes that would make
                    a route eligible, nearest first. An entry names the change
                    (`change` and `then_eligible` for a sandbox request,
                    `provider`, `distance` and `failing` for a launch); clients
                    must preserve fields they do not know.
                  items:
                    type: object
                requirement:
                  type: string
                  description: >-
                    The SandboxProviderSpec family whose requirement would make
                    this operation available.
                purchase_id:
                  type: string
                  description: >-
                    Retained failed credit purchase ID, when a saved-card charge
                    was declined.
                preview:
                  $ref: '#/components/schemas/CreditRefundPreview'
                  description: >-
                    Current refund preview returned with 409
                    refund_amount_changed.
                quote:
                  $ref: '#/components/schemas/CreditPurchaseQuote'
                  description: Current purchase quote returned with 409 quote_changed.
                redemption:
                  $ref: '#/components/schemas/CreditPromotion'
                  description: >-
                    Original promotion redemption returned with 409
                    promotion_already_redeemed.
                scope:
                  type: string
                  enum:
                    - workspace
                  description: >-
                    spend_limit_exceeded only; which configured cap refused
                    admission.
                period:
                  type: string
                  enum:
                    - total
                    - daily
                    - monthly
                  description: spend_limit_exceeded only; the cap period that applies.
                limit_nanodollars:
                  type: integer
                  minimum: 1
                  description: spend_limit_exceeded only; exact configured USD nanodollars.
                requested_nanodollars:
                  type: integer
                  minimum: 1
                  description: spend_limit_exceeded only; exact proposed managed hold.
                sign_in_method:
                  type: string
                  description: >-
                    account_exists only: how the existing account with this
                    verified address signs in (google, github, email or other).
                masked_email:
                  type: string
                  description: >-
                    account_exists only: that account's address, masked as
                    `t…@gmail.com`.
                failure_reason:
                  type: string
                  maxLength: 100
                  description: >-
                    Short safe card-decline reason; raw Stripe messages are not
                    returned.
                names:
                  type: array
                  uniqueItems: true
                  items:
                    $ref: '#/components/schemas/SecretName'
                  description: All manifest secret names that could not be resolved.
                fields:
                  type: array
                  uniqueItems: true
                  items:
                    type: string
                    enum:
                      - preferences.order
                      - preferences.sort
                      - preferences.allow_fallbacks
                  description: >-
                    routing_overrides_forbidden only; the prohibited request
                    inputs.
                volume_id:
                  type: string
                  description: BoxRouter Volume ID involved in the error.
                writer_sandbox_id:
                  type: string
                  description: >-
                    volume_busy only; the sandbox that holds the volume's writer
                    lease, when it is a recorded sandbox.
                checkpoint:
                  type: integer
                  minimum: 1
                  description: Volume checkpoint involved in the error.
                limit_bytes:
                  type: integer
                  minimum: 0
                observed_bytes:
                  type: integer
                  minimum: 0
                mismatch:
                  type: object
                  additionalProperties: false
                  required:
                    - field
                    - recorded
                    - requested
                  properties:
                    field:
                      type: string
                      enum:
                        - image
                        - arch
                    recorded:
                      type: string
                    requested:
                      type: string
                volume_phase:
                  type: string
                  enum:
                    - check
                    - branch
                    - lease
                    - identity
                    - install
                    - credential
                    - mount
                    - metadata
                    - checkpoint
                    - commit
                    - write
                phase:
                  type: string
                  enum:
                    - code
                    - setup
                    - files
                    - background
                    - previews
                  description: Preparation phase that failed.
                command:
                  type: string
                  description: Command whose nonzero exit stopped launch preparation.
                exit_code:
                  type: integer
                  description: >-
                    Exit code of the failed command, or of the process that
                    exited before its port listened.
                stderr_tail:
                  type: string
                  description: >
                    At most the final 4 KiB of stderr from the failed command,
                    with resolved secret values

                    redacted. port_not_listening carries the same tail of the
                    process's stderr.
                stdout_tail:
                  type: string
                  description: >-
                    port_not_listening only; at most the final 4 KiB of the
                    process's stdout.
                agent:
                  type: string
                  description: Unknown catalog agent name.
                port:
                  type: integer
                  minimum: 1
                  maximum: 65535
                  description: >-
                    The sandbox port whose preview was refused
                    (preview_access_refused) or that never accepted connections
                    (port_not_listening).
                revoked:
                  type: boolean
                  description: >
                    preview_access_refused only; true when the unwanted preview
                    was ended and no

                    access to the port remains. False: it may still be reachable
                    (outcome unknown).
                preview_id:
                  type: string
                  description: >
                    preview_access_refused only; the identifier the provider
                    gave the preview that may

                    still be reachable. Present only for a public preview.
                url:
                  type: string
                  format: uri
                  description: >
                    preview_access_refused only; the address of a public preview
                    that may still be

                    reachable. Never present for a private preview, whose
                    address holds a credential,

                    and never when it was ended.
            request_id:
              type: string
            doc_url:
              type:
                - string
                - 'null'
              format: uri
              description: >-
                Where the documentation explains this code:
                `https://boxrouter.ai/docs/error-codes#` followed by the code,
                for example
                `https://boxrouter.ai/docs/error-codes#no_eligible_route`. The
                page has one anchored row per code with what it means and what
                to do. BoxRouter sends it with every error; it is null for a
                code that has no documented row. Clients must accept an error
                body that omits it.
            fix:
              type:
                - string
                - 'null'
              minLength: 1
              description: >-
                Actionable change for the caller when the request cannot be
                completed. A refusal (4xx) always carries one; a server or
                provider fault, including an error event that ends a terminal or
                process stream, can answer null.
            operation_id:
              type:
                - string
                - 'null'
              description: >-
                Durable server operation ID for reconciliation after uncertain
                mutations.
            outcome:
              type: string
              enum:
                - not_started
                - completed
                - partial
                - unknown
              description: >
                What is known about the requested side effect. `not_started`
                means nothing ran

                anywhere, at BoxRouter or at a provider; a launch-setup or
                process-start failure

                after dispatch is `partial` or `unknown`. Unknown and partial
                forbid automatic

                replay and always carry `retry: check_outcome`. An HTTP status
                alone does not establish

                outcome.

                Many refusals report not_started before the provider is asked
                anything. A read

                (GET or HEAD) has no side effect to be unsure about, so its
                failures report

                not_started and carry the code's own retry value. A launch
                preparation failure

                happens after the sandbox was created and setup commands may
                already have run, and

                deleting the sandbox does not undo effects outside it: it
                reports partial once the

                cleanup is confirmed and unknown if it is not. A process that
                wait_for_port ended

                reports partial. volume_restore_failed on a resume or create,

                and volume_save_failed after the guest was read, report unknown
                or partial; they

                carry the operation_id when the call was recorded, and their fix
                does not offer to

                send the call again unchanged.
            retry:
              type: string
              enum:
                - safe
                - after_fix
                - check_outcome
                - never
              x-boxrouter-open-enum: true
              description: >
                What the caller may do next, fixed per code
                (x-boxrouter-error-retry): safe resends the

                same request, after_fix changes the request or setup first,
                check_outcome reads

                `outcome` and the resource before resending, never does not
                resend. Branch on this

                instead of the HTTP status.
            retry_after_seconds:
              type:
                - integer
                - 'null'
              minimum: 0
              description: >-
                How long to wait before a `retry: safe` resend, as the
                Retry-After header says it; null when there is no wait to name.
            provider:
              type:
                - string
                - 'null'
            native_code:
              type:
                - string
                - 'null'
              description: >-
                The provider's machine-readable error code, unchanged, when it
                reports one.
            native_status:
              type:
                - integer
                - 'null'
              description: >-
                The provider's HTTP status, unchanged, when the failure came
                from a provider response.
            native_message:
              type:
                - string
                - 'null'
              maxLength: 4096
              description: >-
                The provider's own error message when it answered with an HTTP
                4xx refusal (for example a plan limit); null otherwise. Capped
                at 512 characters, with whitespace collapsed. Credential secrets
                and token-shaped strings are removed before return. The literal
                `[redacted]` marker is used when all credential secret fields
                are at least 12 characters; legacy saved secrets shorter than 12
                characters are removed without the marker.
    ActionsSandboxOrigin:
      type: object
      description: >
        A sandbox a BoxRouter Actions job ran in. source, run_id and job_id come
        from the

        placement and are always present; every other fact is omitted when Cloud
        does not

        know it.
      additionalProperties: false
      required:
        - source
        - run_id
        - job_id
      properties:
        source:
          type: string
          enum:
            - github_actions
        repository:
          type: string
          minLength: 1
          description: >
            owner/name, from the job's GitHub webhook; for jobs admitted before
            the webhook was

            recorded, from the workspace's GitHub repository binding for the
            same repository ID.
        workflow:
          type:
            - string
            - 'null'
          minLength: 1
          description: Workflow name from the job's GitHub webhook or run.
        run_id:
          type: string
          minLength: 1
          maxLength: 128
          pattern: ^[^\u0000]*$
          description: BoxRouter Actions run ID used by the Actions dashboard deep link.
        run_number:
          type:
            - integer
            - 'null'
          minimum: 1
          description: GitHub run number from the run.
        job_id:
          type: string
          minLength: 1
          maxLength: 128
          pattern: ^[^\u0000]*$
          description: BoxRouter Actions job ID.
        job_name:
          type: string
          minLength: 1
          description: Job name from the job's GitHub webhook.
        run_url:
          type: string
          format: uri
          description: GitHub run page, built from repository and the GitHub run ID.
        job_url:
          type: string
          format: uri
          description: >
            GitHub job page: the job's html_url from its webhook, else built
            from repository and

            the GitHub run and job IDs.
    AgentsSandboxOrigin:
      type: object
      description: A sandbox created by an agent launch.
      additionalProperties: false
      required:
        - source
        - launch_id
        - agent
        - agent_name
      properties:
        source:
          type: string
          enum:
            - agents
        launch_id:
          type: string
          minLength: 1
          maxLength: 128
          pattern: ^[^\u0000]*$
          description: Launch operation ID, as in GET /launches/{operation_id}.
        agent:
          type: string
          minLength: 1
          description: >-
            The launched manifest's name; the agent catalog ID for catalog
            agents, such as claude-code.
        agent_name:
          type: string
          minLength: 1
          description: >-
            Display name from the agent catalog, such as Claude Code; the
            manifest name for agents outside the catalog.
        repository:
          type:
            - string
            - 'null'
          minLength: 1
          description: >-
            Repository as owner/name when the launch checked out code; null or
            absent when it had none.
        sha:
          type:
            - string
            - 'null'
          pattern: ^[0-9a-f]{40}$
          description: >-
            Commit checked out for the launch; null or absent when it had no
            code.
    PricingTimestamp:
      description: A UTC time, ending in Z.
      type: string
      format: date-time
      pattern: >-
        ^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\.[0-9]+)?Z$
    UsageHow:
      description: >-
        How the fact was obtained: the API call, the page URL, the record, or
        why it is unknown.
      type: string
      minLength: 1
    UsageSize:
      description: >-
        What the sandbox got. Each field is optional because a source may give
        only some of them; at least one is present unless the source is
        `unknown`. When GPUs are present, `gpu` and `gpu_model` are both
        recorded; without a GPU, both are absent.
      type: object
      additionalProperties: false
      required:
        - source
        - observed_at
        - how
      properties:
        cpu:
          description: vCPUs.
          type: number
          exclusiveMinimum: 0
        memory_mib:
          type: integer
          minimum: 1
        disk_mib:
          type: integer
          minimum: 1
        gpu:
          description: Number of allocated GPUs.
          type: integer
          minimum: 1
        gpu_model:
          description: The allocated model's gpu-registry identifier.
          type: string
          pattern: ^[a-z][a-z0-9-]*:[a-z0-9][a-z0-9-]*$
        source:
          $ref: '#/components/schemas/UsageSource'
        observed_at:
          $ref: '#/components/schemas/PricingTimestamp'
        how:
          $ref: '#/components/schemas/UsageHow'
      if:
        $ref: '#/components/schemas/UsageIsUnknown'
      then:
        not:
          anyOf:
            - required:
                - cpu
            - required:
                - memory_mib
            - required:
                - disk_mib
            - required:
                - gpu
            - required:
                - gpu_model
      else:
        anyOf:
          - required:
              - cpu
          - required:
              - memory_mib
          - required:
              - disk_mib
          - required:
              - gpu
      allOf:
        - if:
            required:
              - gpu
          then:
            required:
              - gpu_model
        - if:
            required:
              - gpu_model
          then:
            required:
              - gpu
    UsageSnapshotStorage:
      description: >-
        The stored snapshot size, or its known maximum when the provider does
        not report the actual size.
      type: object
      additionalProperties: false
      required:
        - source
        - observed_at
        - how
      properties:
        gb:
          type:
            - number
            - 'null'
          minimum: 0
        max_gb:
          type:
            - number
            - 'null'
          minimum: 0
        source:
          $ref: '#/components/schemas/UsageSource'
        observed_at:
          $ref: '#/components/schemas/PricingTimestamp'
        how:
          $ref: '#/components/schemas/UsageHow'
        bytes:
          description: Provider snapshot sizeBytes, kept as an exact integer.
          type: integer
          minimum: 0
      if:
        $ref: '#/components/schemas/UsageIsUnknown'
      then:
        properties:
          gb:
            type: 'null'
      else:
        anyOf:
          - required:
              - gb
            properties:
              gb:
                type: number
          - required:
              - bytes
    UsageRange:
      description: A bounded quantity.
      type: object
      additionalProperties: false
      required:
        - low
        - high
      properties:
        low:
          type: number
          minimum: 0
        high:
          type: number
          minimum: 0
    provider:
      description: The provider that ran the sandbox, as named in its price versions.
      type: string
      pattern: ^[a-z][a-z0-9-]*$
    class:
      description: >-
        The sandbox's class or runtime, which picks the rate set in the price
        version. If absent, it may be priced only when the price version has
        exactly one class; otherwise the cost is unknown.
      type: object
      additionalProperties: false
      required:
        - name
        - source
        - observed_at
        - how
      properties:
        name:
          type:
            - string
            - 'null'
          minLength: 1
        source:
          $ref: '#/components/schemas/UsageSource'
        observed_at:
          $ref: '#/components/schemas/PricingTimestamp'
        how:
          $ref: '#/components/schemas/UsageHow'
      if:
        $ref: '#/components/schemas/UsageIsUnknown'
      then:
        properties:
          name:
            type: 'null'
      else:
        properties:
          name:
            type: string
    started:
      description: When the sandbox started. It picks the price version in effect.
      type: object
      additionalProperties: false
      required:
        - at
        - source
        - observed_at
        - how
      properties:
        at:
          type:
            - string
            - 'null'
        source:
          $ref: '#/components/schemas/UsageSource'
        observed_at:
          $ref: '#/components/schemas/PricingTimestamp'
        how:
          $ref: '#/components/schemas/UsageHow'
      if:
        $ref: '#/components/schemas/UsageIsUnknown'
      then:
        properties:
          at:
            type: 'null'
      else:
        properties:
          at:
            $ref: '#/components/schemas/PricingTimestamp'
    region:
      description: The region the sandbox ran in, as the provider names it.
      type: object
      additionalProperties: false
      required:
        - name
        - source
        - observed_at
        - how
      properties:
        name:
          type:
            - string
            - 'null'
          minLength: 1
        source:
          $ref: '#/components/schemas/UsageSource'
        observed_at:
          $ref: '#/components/schemas/PricingTimestamp'
        how:
          $ref: '#/components/schemas/UsageHow'
      if:
        $ref: '#/components/schemas/UsageIsUnknown'
      then:
        properties:
          name:
            type: 'null'
      else:
        properties:
          name:
            type: string
    cpu:
      description: vCPUs.
      type: number
      exclusiveMinimum: 0
    memory_mib:
      type: integer
      minimum: 1
    disk_mib:
      type: integer
      minimum: 1
    gpu_model:
      description: The allocated model's gpu-registry identifier.
      type: string
      pattern: ^[a-z][a-z0-9-]*:[a-z0-9][a-z0-9-]*$
    intervals:
      description: >-
        Time in each billed state, one entry per period, in time order. A price
        version's minimum and increment rules apply to each entry.
      type: array
      minItems: 1
      items:
        type: object
        additionalProperties: false
        required:
          - state
          - seconds
          - source
          - observed_at
          - how
        properties:
          size:
            $ref: '#/components/schemas/UsageSize'
          snapshot_storage:
            $ref: '#/components/schemas/UsageSnapshotStorage'
          state:
            enum:
              - running
              - paused
              - stopped
          seconds:
            description: >-
              Exact seconds, or a range when a change was noticed late and the
              period is only bounded.
            oneOf:
              - type: number
                minimum: 0
              - $ref: '#/components/schemas/UsageRange'
              - type: 'null'
          source:
            $ref: '#/components/schemas/UsageSource'
          observed_at:
            $ref: '#/components/schemas/PricingTimestamp'
          how:
            $ref: '#/components/schemas/UsageHow'
        if:
          $ref: '#/components/schemas/UsageIsUnknown'
        then:
          properties:
            seconds:
              type: 'null'
        else:
          properties:
            seconds:
              type:
                - number
                - object
    creations:
      description: >-
        How many times the sandbox was created: 1, plus any restores that the
        provider charges as a creation.
      type: object
      additionalProperties: false
      required:
        - count
        - source
        - observed_at
        - how
      properties:
        count:
          type:
            - integer
            - 'null'
          minimum: 0
        source:
          $ref: '#/components/schemas/UsageSource'
        observed_at:
          $ref: '#/components/schemas/PricingTimestamp'
        how:
          $ref: '#/components/schemas/UsageHow'
      if:
        $ref: '#/components/schemas/UsageIsUnknown'
      then:
        properties:
          count:
            type: 'null'
      else:
        properties:
          count:
            type: integer
    active_cpu:
      description: >-
        Seconds of CPU the sandbox actually used, for providers that bill active
        CPU. Absent where the provider does not bill it.
      type: object
      additionalProperties: false
      required:
        - seconds
        - source
        - observed_at
        - how
      properties:
        seconds:
          type:
            - number
            - 'null'
          minimum: 0
        source:
          $ref: '#/components/schemas/UsageSource'
        observed_at:
          $ref: '#/components/schemas/PricingTimestamp'
        how:
          $ref: '#/components/schemas/UsageHow'
      if:
        $ref: '#/components/schemas/UsageIsUnknown'
      then:
        properties:
          seconds:
            type: 'null'
      else:
        properties:
          seconds:
            type: number
    egress:
      description: Bytes the sandbox sent out. Absent where the provider does not bill it.
      type: object
      additionalProperties: false
      required:
        - bytes
        - source
        - observed_at
        - how
      properties:
        bytes:
          type:
            - integer
            - 'null'
          minimum: 0
        source:
          $ref: '#/components/schemas/UsageSource'
        observed_at:
          $ref: '#/components/schemas/PricingTimestamp'
        how:
          $ref: '#/components/schemas/UsageHow'
      if:
        $ref: '#/components/schemas/UsageIsUnknown'
      then:
        properties:
          bytes:
            type: 'null'
      else:
        properties:
          bytes:
            type: integer
    CostTotalRange:
      description: 'Exact USD total: low equals high.'
      type: object
      additionalProperties: false
      required:
        - low
        - high
      properties:
        low:
          $ref: '#/components/schemas/PricingDecimal'
        high:
          $ref: '#/components/schemas/PricingDecimal'
    PricingDecimal:
      description: >-
        A non-negative decimal number as a string, in plain notation without an
        exponent.
      type: string
      pattern: ^(0|[1-9][0-9]*)(\.[0-9]+)?$
    CostSource:
      description: >-
        Where a fact came from. The same six values as the usage record's
        source; a test keeps the two lists equal.
      type: string
      enum:
        - provider
        - published
        - measured
        - recorded
        - calculated
        - unknown
    CostMoneyRange:
      $ref: '#/components/schemas/CostDecimalRange'
      description: US dollars as a range; low equals high when the amount is exact.
    CostLabel:
      description: >-
        reported: a provider amount verified at list price; calculated: provider
        usage priced at stored list rates; unknown: required provider evidence
        or a rate is missing.
      enum:
        - reported
        - calculated
        - unknown
    CostTotal:
      description: An exact USD amount, low equal to high, or null for unknown.
      anyOf:
        - $ref: '#/components/schemas/CostTotalRange'
        - type: 'null'
    summary:
      description: >-
        The total as one sentence, or why there is none. The sentences of
        `lines[].text` add up to it.
      type: string
      minLength: 1
    SandboxChargeCorrection:
      type: object
      additionalProperties: false
      required:
        - at
        - delta_nanodollars
        - reason
      properties:
        at:
          type: string
          format: date-time
          description: When the ledger recorded the correction.
        delta_nanodollars:
          type: string
          maxLength: 20
          pattern: ^(-?[1-9][0-9]{0,18})$
          description: >-
            The change to the charge. Positive means the charge went up and the
            difference was taken from the balance; negative means it went down
            and the difference was returned to it.
        reason:
          type: string
          enum:
            - provider_revised
          x-boxrouter-open-enum: true
          description: >
            Why the charge moved. `provider_revised`: the provider's records or
            reported cost for

            this sandbox changed. Clients must handle unknown values explicitly.
    SandboxRouteSelection:
      type: object
      required:
        - considered
        - eligible
        - ranked_by
        - excluded
        - attempts
      description: >-
        Which routes were considered, how they were ranked and why each other
        one was excluded.
      properties:
        considered:
          type: integer
          minimum: 0
        eligible:
          type: integer
          minimum: 0
        ranked_by:
          type:
            - string
            - 'null'
          enum:
            - price
            - time
            - providers
            - order
            - null
          x-boxrouter-choices:
            price:
              label: Price
              line: Lowest hourly price first.
              measure: price
              better: lower
            time:
              label: Time
              line: Shortest run time measured on reference workloads first.
              measure: time
              better: lower
            providers:
              label: Providers
              line: The hard list order.
            order:
              label: Order
              line: A soft provider preference.
          description: >-
            The sort used; providers for the hard list order; order for a soft
            provider preference; or null for the router's default.
        excluded:
          type: array
          items:
            $ref: '#/components/schemas/ExcludedRoute'
        preparation_skips:
          type: array
          description: >-
            Routes skipped after eligibility because image or provider
            preparation failed.
          items:
            $ref: '#/components/schemas/CreationPreparationSkip'
        attempts:
          type: array
          description: >
            Adapters that refused this create before the one that made it, in
            dispatch order. Only

            dispatches appear; routes skipped before dispatch are in `excluded`.
            Normally empty:

            BoxRouter tries the next eligible adapter once when a refusal is
            definite.
          items:
            type: object
            required:
              - provider
              - native_code
              - native_status
            properties:
              provider:
                type: string
              native_code:
                type:
                  - string
                  - 'null'
              native_status:
                type:
                  - integer
                  - 'null'
              route_id:
                type:
                  - string
                  - 'null'
                maxLength: 128
                description: The route this dispatch used.
              account_id:
                type:
                  - string
                  - 'null'
                maxLength: 128
                description: The connected account this dispatch used.
              supply:
                type:
                  - string
                  - 'null'
                maxLength: 32
                description: 'The funding authority of this dispatch: byok or managed.'
              cause:
                $ref: '#/components/schemas/CreationRouteCause'
        fallbacks_allowed:
          type: boolean
          description: >-
            The effective allow_fallbacks after inheritance. Absent when the
            create predates this field.
        stopped_reason:
          $ref: '#/components/schemas/CreationStoppedReason'
        funding_group:
          $ref: '#/components/schemas/FundingGroup'
          description: >-
            Frozen payer group of the selected route. Absent on older responses;
            definite pre-create fallback stays in this group after dispatch.
        workspace_mode:
          type: string
          enum:
            - automatic
            - cheapest
            - fastest
            - custom
          x-boxrouter-open-enum: true
          x-boxrouter-choices:
            automatic:
              label: Auto
              line: A random draw weighted toward lower hourly price.
            cheapest:
              label: Cheapest
              line: Lowest hourly price first.
              measure: price
              better: lower
            fastest:
              label: Fastest
              line: Shortest run time measured on reference workloads first.
              measure: time
              better: lower
            custom:
              label: Custom
              line: Your exact provider order, top to bottom.
          description: Effective workspace mode at admission; absent on older responses.
    GrantedGate:
      type: object
      required:
        - variant
        - basis
        - granted
        - also
        - settings
        - unavailable
      description: One gate as granted to this sandbox.
      properties:
        variant:
          type: integer
          minimum: 0
          description: >-
            Index into the declaration of route.adapter_version. Only meaningful
            with that version.
        basis:
          type: string
          enum:
            - implemented
            - proven
          description: >-
            The weakest basis among the granted values; for a gate granted with
            no named knob, the variant's own.
        granted:
          type: object
          additionalProperties: true
          description: >
            One entry per knob the request named: the granted values for a
            pick-one knob, the

            string "any" where the request said so, the boolean for a yes/no
            knob, the declared

            number for a number knob. This is what the code may rely on.
        also:
          type: object
          additionalProperties: true
          description: >-
            The variant's other answers, including declared limits, for
            information. Calls that depend on them are refused.
        settings:
          type: object
          additionalProperties: true
        unavailable:
          type:
            - string
            - 'null'
          description: >-
            Set when the account has since lost the gate; that gate's calls then
            answer gate_unavailable.
    SandboxProviderSpecHostname:
      type: string
      oneOf:
        - pattern: >-
            ^(?=.{1,253}(?![\s\S]))(?![0-9.]+(?![\s\S]))[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?(?:\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*(?![\s\S])
        - pattern: >-
            ^(?=.{3,255}(?![\s\S]))\*\.(?![0-9.]+(?![\s\S]))[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?(?:\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*(?![\s\S])
    VolumeId:
      type: string
      pattern: ^vol_[0-9a-f]{32}$
      description: >-
        BoxRouter-managed Volume ID. Provider-native volume requirements are not
        accepted.
    CreditRefundPreview:
      type: object
      additionalProperties: false
      required:
        - unused
        - held_excluded
        - fee
        - principal
        - tax
        - total
        - card
      properties:
        unused:
          type: integer
          minimum: 0
          description: Unused purchased credit in US cents, before held credit is excluded.
        held_excluded:
          type: integer
          minimum: 0
          description: Credit held for running sandboxes, in US cents.
        fee:
          type: integer
          minimum: 0
          description: Original Stripe processing fee retained, in US cents.
        principal:
          type: integer
          minimum: 0
          description: Tax-exclusive principal returned to the original card, in US cents.
        tax:
          type: integer
          minimum: 0
          description: Tax Stripe adds to the credit note, in US cents.
        total:
          type: integer
          minimum: 0
          description: Total Stripe will refund, in US cents.
        card:
          $ref: '#/components/schemas/MaskedCreditCard'
    CreditPurchaseQuote:
      type: object
      additionalProperties: false
      required:
        - amount
        - tax
        - total
        - address_required
      properties:
        amount:
          type: integer
          minimum: 1
          description: >-
            Tax-exclusive credit amount in US cents; this is what is added to
            the balance.
        fee_minor:
          type: integer
          minimum: 0
          description: >-
            BoxRouter's purchase fee in US cents, computed by the server and
            charged on top of amount. Tax applies to amount plus fee. Absent on
            older services.
        tax:
          type: integer
          minimum: 0
          description: Estimated tax in US cents, on the credits and the fee.
        total:
          type: integer
          minimum: 1
          description: >-
            Estimated total to charge in US cents: amount plus fee_minor plus
            tax.
        address_required:
          type: boolean
        missing:
          type: array
          items:
            type: string
          description: Required billing address fields missing for an exact tax quote.
    CreditPromotion:
      type: object
      additionalProperties: false
      required:
        - code
        - amount_nanodollars
        - description
        - redeemed_at
      properties:
        code:
          type: string
          description: The code in its canonical upper-case form.
        amount_nanodollars:
          type: string
          maxLength: 19
          pattern: >-
            ^(?:[1-9][0-9]{0,17}|[1-8][0-9]{18}|9[0-1][0-9]{17}|92[0-1][0-9]{16}|922[0-2][0-9]{15}|9223[0-2][0-9]{14}|92233[0-6][0-9]{13}|922337[0-1][0-9]{12}|92233720[0-2][0-9]{10}|922337203[0-5][0-9]{9}|9223372036[0-7][0-9]{8}|92233720368[0-4][0-9]{7}|922337203685[0-3][0-9]{6}|9223372036854[0-6][0-9]{5}|92233720368547[0-6][0-9]{4}|922337203685477[0-4][0-9]{3}|9223372036854775[0-7][0-9]{2}|922337203685477580[0-7])$
          description: >-
            Credit granted, in billionths of a US dollar, as a canonical
            positive signed 64-bit nanodollar string.
        description:
          type: string
          description: What the credit is for, as the promotion describes it.
        redeemed_at:
          type: string
          format: date-time
    SecretName:
      type: string
      minLength: 1
      maxLength: 128
      pattern: ^[A-Z][A-Z0-9_]{0,127}$
    CostDecimalRange:
      type: object
      additionalProperties: false
      required:
        - low
        - high
      properties:
        low:
          $ref: '#/components/schemas/PricingDecimal'
        high:
          $ref: '#/components/schemas/PricingDecimal'
    ExcludedRoute:
      type: object
      required:
        - provider
        - class
        - account_id
        - failed
      description: One candidate that was not eligible, with every check it failed.
      properties:
        provider:
          type: string
        class:
          type:
            - string
            - 'null'
        account_id:
          type:
            - string
            - 'null'
        failed:
          type: array
          items:
            $ref: '#/components/schemas/FailedCheck'
    CreationPreparationSkip:
      type: object
      additionalProperties: false
      required:
        - provider
        - reason_code
      description: >-
        A route skipped locally before any provider dispatch. It is not an
        attempt.
      properties:
        provider:
          type: string
          minLength: 1
        route_id:
          type:
            - string
            - 'null'
          maxLength: 128
          description: The route that was skipped.
        account_id:
          type:
            - string
            - 'null'
          maxLength: 128
          description: The connected account of the skipped route.
        reason_code:
          type: string
          minLength: 1
        cause:
          $ref: '#/components/schemas/CreationRouteCause'
    CreationRouteCause:
      type: string
      minLength: 1
      maxLength: 64
      enum:
        - key_rejected
        - plan_unbuildable
        - privacy_denied
        - not_ready
        - not_dispatched
        - provider_create_failed
      x-boxrouter-open-enum: true
      description: >
        Why one route did not create the sandbox, in a bounded word:
        `key_rejected` (the provider

        refused the saved key), `plan_unbuildable` (the route matched but its
        create could not be

        built), `privacy_denied` (the workspace's privacy settings refused the
        route),

        `not_ready` (the route's provider session was not ready in time),
        `not_dispatched`

        (refused locally before any provider call) and `provider_create_failed`
        (the provider was

        asked and the create failed). Clients must tolerate values they do not
        know.
    CreationStoppedReason:
      type:
        - string
        - 'null'
      enum:
        - fallbacks_disabled
        - no_eligible_route
        - uncertain_outcome
        - authority_changed
        - deadline_reached
        - cancelled
        - null
      x-boxrouter-open-enum: true
      description: >
        Why creation stopped dispatching further routes: `fallbacks_disabled`
        (allow_fallbacks was

        false and the one permitted dispatch was refused), `no_eligible_route`
        (every remaining

        route was excluded), `uncertain_outcome` (a dispatch may have allocated;
        never retried, reconcile

        with the operation), `authority_changed` (account, funding or privacy
        authority no longer

        permits the next route), `deadline_reached` and `cancelled`. Null when a
        route created the

        sandbox. Clients must tolerate values they do not know.
    FundingGroup:
      type: string
      enum:
        - prioritized
        - credits
        - fallback
      x-boxrouter-open-enum: true
      description: >-
        The frozen payer group; no cross-group retry after a dispatch refusal at
        launch.
    MaskedCreditCard:
      type: object
      additionalProperties: false
      properties:
        brand:
          type:
            - string
            - 'null'
          description: Card brand; absent for Link methods.
        last4:
          type:
            - string
            - 'null'
          pattern: ^[0-9]{4}$
          description: Last four card digits; absent for Link methods.
        type:
          type: string
          enum:
            - card
            - link
          x-boxrouter-open-enum: true
        email:
          type: string
          format: email
          description: Link account email; present only when type is link.
      allOf:
        - if:
            properties:
              type:
                const: link
            required:
              - type
          then:
            required:
              - email
            properties:
              brand:
                type: 'null'
              last4:
                type: 'null'
        - if:
            properties:
              type:
                const: card
            required:
              - type
          then:
            required:
              - brand
              - last4
            properties:
              brand:
                type: string
              last4:
                type: string
                pattern: ^[0-9]{4}$
    FailedCheck:
      type: object
      required:
        - reason
      description: >
        One failed check, in the order they are made: baseline, then the gates
        in the spec's

        order with extras last, then conflicts, resources and basis.
      properties:
        reason:
          type: string
          description: >
            gate_not_listed, gate_unsupported, gate_unavailable, knob_mismatch,
            knob_unknown,

            conflict, resource_mismatch, resource_unknown, not_proven,
            limit_exceeded,

            bound_elsewhere, extra_mismatch, declaration_unusable,
            variant_unusable,

            baseline_failed, account_unchecked, account_unhealthy,
            standard_image_unavailable,

            not_allowed, `not connected`, `not enabled`, price_unknown,
            insufficient_credit,

            spend_limit_exceeded, outside_funding_authority, unfunded or
            class_not_selected.

            `standard_image_unavailable` means the account has no verified copy
            of the standard image

            for the route's exact region, image version and digest; its `fix`
            field gives the setup fix.

            It is distinct from `baseline_failed`, which means the provider
            cannot meet the requested

            contract. `price_unknown` means the payer's price is unknown;
            `insufficient_credit` means

            the payer has fewer credits than required; `spend_limit_exceeded`
            means the applicable

            spend limit prevents the request. These typed funding refusals apply
            only when a payer

            exists. `unfunded` means no provider key and no credits, not merely
            zero available credits.

            `outside_funding_authority` means the matched route is outside the
            funding ceiling selected

            for this request. `not connected` means the provider is served by
            this deployment but no

            account is connected to this workspace; `not enabled` means the
            provider is not served by

            this deployment. `class_not_selected` means a matched sibling class
            lost the

            one-class-per-route selection while its route remains inside the
            authority ceiling; it

            excludes the class, not the route. `open_ended_unfit` means the
            provider can end a

            sandbox, so it cannot serve one with `lifetime_seconds: null`;
            `open_ended_needs_byok`

            means that request was made on a credit-funded route. Clients must
            tolerate reasons

            they do not know.
        gate:
          type: string
        knob:
          type: string
        resource:
          type: string
        extra:
          type: string
        limit:
          type: string
        detail:
          type:
            - string
            - 'null'
        details:
          type: object
          description: >
            Structured facts for the refusal, such as available and required
            credits or the applicable

            spend limit.
          additionalProperties: true
        fix:
          type:
            - string
            - 'null'
          description: Setup action for this failed check, when one is available.
        asked:
          description: What the request asked for, in the request's own form.
        offered:
          description: What the declaration offers, in the declaration's own form.
        narrowed_by:
          type:
            - string
            - 'null'
          enum:
            - account
            - null
        between:
          type: array
          items:
            type: string
        value:
          description: The one value that caused the failure, when one did.
  responses:
    Error:
      description: >
        Structured error. `retry` says whether to send the call again (`now`,
        `after_fix`, `inspect` or `never`) and `retry_after_seconds` how long to
        wait first. Unowned and unknown resource IDs both return 404. Admission
        overload returns 503 with code overloaded, outcome not_started and
        Retry-After. It reserves no operation and dispatches no provider work.
        Shared workspace/provider admission budgets return 429 with code
        rate_limited, outcome not_started and Retry-After. An incomplete request
        body can return 408 request_timeout before dispatch. Durable-state
        failures return 503 database_unavailable with outcome unknown; do not
        infer that execution did not occur. A read (GET or HEAD) that meets the
        same failure changed nothing: its message says the state is temporarily
        unavailable, and it is safe to repeat. A provider that cannot be reached
        when a create is prepared returns 502 provider_error with outcome
        not_started; nothing was created, and the create can be retried with the
        same Idempotency-Key or sent to another provider with `providers`.

        Native errors are sanitized; upstream credentials, request bodies and

        another workspace's metadata are never included. Server-Timing is
        present only when the response reached Dispatcher or held-response
        preparation; an earlier response, including pre-Dispatcher admission
        overload, may omit it.
      headers:
        X-Request-ID:
          $ref: '#/components/headers/RequestId'
        Server-Timing:
          $ref: '#/components/headers/ServerTiming'
        Retry-After:
          description: >-
            Seconds before retrying an eligible read; not permission to replay a
            mutation.
          schema:
            type: integer
            minimum: 0
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
  securitySchemes:
    BoxRouterKey:
      type: http
      scheme: bearer
      description: BoxRouter API key; never an upstream provider key.
    BrowserSession:
      type: apiKey
      in: cookie
      name: __Host-boxrouter_session
      description: >-
        HttpOnly server-side session. Local HTTP uses boxrouter_session. Browser
        mutations require the session CSRF token and the configured Origin;
        execution API keys cannot administer sessions or customer keys.

````

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