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

# Create the managed sandbox of a claim a self-hosted runner holds

> Creates a sandbox on OuterLayer's account at the sandbox provider for the claim the caller holds, and answers with the sandbox's address and secret. The gateway chooses the snapshot. The sandbox gets the processors and memory of the machine size, a disk no smaller than the snapshot's, and no direct network access. A claim has one sandbox at a time: a claim that has a sandbox gets that sandbox again. The claim counts as a managed build from this call on, and its time is billed as managed build-hours from the moment its sandbox has started, not from this call. The provider can take minutes to start a sandbox. With `waits: true`, the gateway keeps a sandbox that is slow to start and answers with it in the state `starting`, with an empty `secret` and `urlToken`. The gateway ends the sandbox when the claim is released or its lease expires, unless the runner keeps it (`keep-managed-sandbox`). A claim whose sandbox is kept gets a new sandbox, and the kept one ends. Refusals: `claim_expired` (410), `claim_not_held` (403), `managed_sandboxes_off` (403), `managed_sandboxes_unavailable` (403), `managed_build_held` (409, with `reason`: `trial_hours_used`, `spending_cap_reached`, `at_limit` or `unavailable`) and `sandbox_provider_refused` (502). A refused call binds no sandbox to the claim. The response is sent with `Cache-Control: no-store`.



## OpenAPI

````yaml /openapi.yaml post /v1/work-items/{workItemId}/claim/sandbox
openapi: 3.0.3
info:
  contact:
    email: hello@outerlayer.ai
    url: https://www.outerlayer.ai
  description: >-
    The OuterLayer Gateway API lets you ingest coding-agent sessions and record
    evidence of work programmatically.


    Most teams reach it through the `outerlayer` CLI, which calls it for them.

    Call it directly to build your own integration or to automate what the
    dashboard does.


    Versioning: every endpoint is prefixed with `/v1/`. Breaking changes ship
    under a new version prefix (`/v2/`, etc.) with a 90-day-minimum deprecation
    window; anything additive lands on the current prefix.


    Vocabulary: the dashboard calls this API's `app` a **factory** — the unit
    that owns a set of repositories, the agent sessions worked on them, and the
    evidence they produce. They are the same entity. The API keeps `app` in its
    paths, headers, and field names because those are a published contract; only
    the product surface was renamed.
  title: OuterLayer Gateway API
  version: '1.0'
servers:
  - description: Production (OuterLayer Cloud)
    url: https://api.outerlayer.ai
  - description: Local dev server (self-hosted gateway)
    url: http://localhost:9418
security:
  - AppId: []
    BearerAuth: []
tags:
  - description: >-
      What a CLI login token can read about its owner without naming a factory,
      such as the factories they can use.
    name: Account
  - description: >-
      The route a fleet machine asks for its next managed build on. A fleet
      machine is a machine OuterLayer operates.
    name: Fleet
  - description: >-
      The CLI version a gateway names to its runners, set with the gateway's
      runner version key.
    name: Runner version
  - description: >-
      Coding-agent session ingest (outerlayer sync) and content-addressed
      session images.
    name: Agents
  - description: >-
      Evidence artifacts (screenshots, recordings, reports, logs) emitted as
      proof of a change and anchored to pull requests.
    name: Artifacts
  - description: >-
      Pass/fail outcomes of checks run in your own CI or compute, anchored to
      pull requests with the run URL as proof.
    name: Emitted Results
  - description: >-
      The acceptance criteria of a work item, recorded as one list. The Criteria
      tab, its count and the item status read that list.
    name: Criteria
  - description: >-
      What any agent found wrong about a change under review or about a rule it
      ran on, recorded on a work item.
    name: Findings
  - description: >-
      Find, file and edit the issue a spec lives in, through OuterLayer, with no
      tracker credential on the caller's side.
    name: Specs
  - description: >-
      Add or remove a source's statement that it is working on an issue or pull
      request, and read what is currently live.
    name: Work Items
  - description: >-
      What the factory's GitHub App installation lets builds do on each
      connected repository, and whether each default branch requires a pull
      request.
    name: Repositories
  - description: >-
      The runs of a schedule automation: a runner claims a run, asks for its
      read token and ends it, and the run's agent reports each issue it found or
      that it found nothing.
    name: Schedule runs
  - description: >-
      A runner host's heartbeat — its CLI version, slots and last request for
      work — and the factory's list of hosts with a derived status.
    name: Hosts
  - description: Query server feature availability.
    name: Capabilities
  - description: Per-model LLM pricing data. Public, unauthenticated.
    name: Pricing
  - description: >-
      Create, list, and revoke factory API keys. Plaintext returned exactly once
      at creation.
    name: API Keys
  - description: >-
      Factory CRUD — a factory is owned by an organization and is the unit every
      other resource hangs off. Lets a headless agent provision one without the
      dashboard.
    name: Apps
  - description: >-
      Agent-coding session list and full transcript reads, with actor-privacy
      controls for machine keys.
    name: Sessions
  - description: >-
      Per-model token spend and fleet-wide agent behavior tiles, including
      two-window comparisons.
    name: Metrics
  - description: Synced-commit history of the app's `.outerlayer/` context tree.
    name: Context
  - description: >-
      Session→PR attribution: which agent sessions produced which pull requests,
      and what each attributed PR cost.
    name: PRs
  - description: Service health checks.
    name: Health
  - description: >-
      Org member and role administration, authenticated with an org-scoped
      management API key (`olk_…`) minted in the dashboard's settings.
    name: Org Management
  - description: OAuth 2.1 discovery metadata for MCP connector clients.
    name: OAuth
paths:
  /v1/work-items/{workItemId}/claim/sandbox:
    post:
      tags:
        - Work Items
      summary: Create the managed sandbox of a claim a self-hosted runner holds
      description: >-
        Creates a sandbox on OuterLayer's account at the sandbox provider for
        the claim the caller holds, and answers with the sandbox's address and
        secret. The gateway chooses the snapshot. The sandbox gets the
        processors and memory of the machine size, a disk no smaller than the
        snapshot's, and no direct network access. A claim has one sandbox at a
        time: a claim that has a sandbox gets that sandbox again. The claim
        counts as a managed build from this call on, and its time is billed as
        managed build-hours from the moment its sandbox has started, not from
        this call. The provider can take minutes to start a sandbox. With
        `waits: true`, the gateway keeps a sandbox that is slow to start and
        answers with it in the state `starting`, with an empty `secret` and
        `urlToken`. The gateway ends the sandbox when the claim is released or
        its lease expires, unless the runner keeps it (`keep-managed-sandbox`).
        A claim whose sandbox is kept gets a new sandbox, and the kept one ends.
        Refusals: `claim_expired` (410), `claim_not_held` (403),
        `managed_sandboxes_off` (403), `managed_sandboxes_unavailable` (403),
        `managed_build_held` (409, with `reason`: `trial_hours_used`,
        `spending_cap_reached`, `at_limit` or `unavailable`) and
        `sandbox_provider_refused` (502). A refused call binds no sandbox to the
        claim. The response is sent with `Cache-Control: no-store`.
      operationId: create-claim-sandbox
      parameters:
        - in: path
          name: workItemId
          required: true
          schema:
            type: string
        - description: >-
            HTTP Message Signature (RFC 9421) made with the runner key's host
            key: `runner=:<base64>:`.
          in: header
          name: Signature
          required: false
          schema:
            description: >-
              HTTP Message Signature (RFC 9421) made with the runner key's host
              key: `runner=:<base64>:`.
            type: string
        - description: >-
            The signature's covered components and parameters:
            `runner=("@method" "@path" "@query" "content-digest");created=<unix
            seconds>;nonce="<random>";keyid="<host key
            fingerprint>";alg="ed25519"`.
          in: header
          name: Signature-Input
          required: false
          schema:
            description: >-
              The signature's covered components and parameters:
              `runner=("@method" "@path" "@query"
              "content-digest");created=<unix
              seconds>;nonce="<random>";keyid="<host key
              fingerprint>";alg="ed25519"`.
            type: string
        - description: >-
            RFC 9530 digest of the request body, always sent, including for a
            request with none: `sha-256=:<base64>:`.
          in: header
          name: Content-Digest
          required: false
          schema:
            description: >-
              RFC 9530 digest of the request body, always sent, including for a
              request with none: `sha-256=:<base64>:`.
            type: string
      requestBody:
        content:
          application/json:
            schema:
              properties:
                idleMinutes:
                  description: >-
                    Minutes with no activity after which the provider ends the
                    sandbox. Kept inside 1 to 120.
                  type: number
                machine:
                  description: >-
                    The machine size. Absent, `small`. A claim that had a
                    sandbox before keeps the size of its first one.
                  enum:
                    - small
                    - large
                  type: string
                metadata:
                  additionalProperties:
                    maxLength: 100
                    type: string
                  description: >-
                    The runner's own labels for the sandbox, which a list
                    returns.
                  type: object
                timeLimitMinutes:
                  description: >-
                    Minutes of running time after which the provider ends the
                    sandbox. At most 1440.
                  type: number
                waits:
                  description: >-
                    Set `true` when the runner can wait for a sandbox that is
                    still starting. The gateway then answers 200 with the
                    sandbox in the state `starting`, and the runner reads it
                    until it has started. Absent, the gateway answers only with
                    a sandbox that has started, and a sandbox that is still
                    starting gets `sandbox_provider_refused` (502).
                  type: boolean
              type: object
      responses:
        '200':
          content:
            application/json:
              schema:
                properties:
                  data:
                    properties:
                      dataPlaneUrl:
                        description: The address the runner sends commands and files to.
                        type: string
                      id:
                        description: The provider's id of the sandbox.
                        type: string
                      machine:
                        description: >-
                          The machine size the sandbox was made with, which its
                          build is billed at.
                        enum:
                          - small
                          - large
                        type: string
                      metadata:
                        additionalProperties:
                          type: string
                        type: object
                      name:
                        type: string
                      secret:
                        description: >-
                          The sandbox's own secret. Hold it in memory only.
                          Empty in a list, while the state is `starting`, for a
                          kept sandbox, and when the claim of the sandbox is not
                          live and billed.
                        type: string
                      state:
                        description: >-
                          `starting`, `running`, `paused` or `ended`. A sandbox
                          that is `starting` has no usable address and no secret
                          yet, and its build is not billed until it has started.
                        type: string
                      tokenHeader:
                        description: >-
                          The name of the header that carries `secret` on a call
                          to `dataPlaneUrl`.
                        type: string
                      urlToken:
                        description: >-
                          The token a port address carries. Empty in a list,
                          while the state is `starting`, for a kept sandbox, and
                          when the claim of the sandbox is not live and billed.
                        type: string
                    required:
                      - id
                      - name
                      - state
                      - dataPlaneUrl
                      - secret
                      - urlToken
                      - tokenHeader
                      - machine
                      - metadata
                    type: object
                required:
                  - data
                type: object
          description: The sandbox of the claim.
        '400':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: The body is not valid.
        '401':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: >-
            Missing or invalid API key, or a runner key's signature was refused:
            `runner_key_signature_required` (the request carries no signature),
            `runner_key_signature_invalid` (it does not verify against the host
            key the key is bound to, or the body does not match its digest),
            `runner_key_signature_stale` (`created` is more than five minutes
            from the gateway's clock) or `runner_key_signature_replayed` (the
            nonce was accepted in the last five minutes).
        '403':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: >-
            Another key holds the lease (`claim_not_held`), managed sandboxes
            are off for the organization (`managed_sandboxes_off`), the gateway
            provides none (`managed_sandboxes_unavailable`), or the caller is
            not a runner key (`forbidden`).
        '404':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: No such work item.
        '409':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: >-
            The organization may not start another managed build now
            (`managed_build_held`). The body carries `reason`.
        '410':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: The item has no live lease (`claim_expired`).
        '502':
          content:
            application/json:
              schema:
                properties:
                  error:
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    type: object
                required:
                  - error
                type: object
          description: >-
            The sandbox provider refused the call or did not answer
            (`sandbox_provider_refused`). The body carries `providerCode` and
            `providerStatus`.
components:
  securitySchemes:
    AppId:
      description: Factory id the request is scoped to.
      in: header
      name: X-Outerlayer-App-Id
      type: apiKey
    BearerAuth:
      description: API key (sk_outerlayer_*)
      scheme: bearer
      type: http

````

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