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

# Box Public API v1

> Create, manage, prompt, observe, and expose Box sandboxes from your own products.

Use the Box Public API from services, CI jobs, hosted workers, and product automation code. For typed clients, start with the [Box SDKs](/box/sdks/overview), [Python SDK](/box/sdks/python), or [TypeScript/JavaScript SDK](/box/sdks/typescript).

## Recommended flow

1. Create a Box API key with `box api-key create` or in the dashboard.
2. Create a box with `POST /boxes`, or resume/fork an existing box when the user is continuing prior work.
3. Poll `GET /boxes/{boxId}` until the box is `ready` or `idle`.
4. Queue work with `POST /boxes/{boxId}/prompt`.
5. Read `GET /boxes/{boxId}/events` while work is running.
6. Use `POST /boxes/{boxId}/desktop` when the user or your support team needs live computer-use visibility.
7. Stop/archive, resume, fork, or delete the box according to your retention policy.

Everything the Box CLI does programmatically is available here: first-class endpoints cover lifecycle, prompts, events, files, desktop, and snapshots. Anything else, including in-box tools like `host` and `lux`, package installs, or your own scripts, is driven through [`POST /boxes/{boxId}/commands`](/box/api/reference/agent/execute-box-command). For high-frequency or streaming control, run your own daemon in the box; see [the daemon pattern](/box/platform-guide#bring-your-own-harness-the-daemon-pattern).

## Base URL

```text theme={null}
https://ascii.dev/api/box/v1
```

## Authentication

Pass a Box API key as a bearer token on every request:

```bash theme={null}
curl -sS "https://ascii.dev/api/box/v1/boxes" \
  -H "Authorization: Bearer $BOX_API_KEY"
```

Create, rotate, and revoke service keys with the `box api-key` CLI command or in the Box dashboard. For key lifecycle guidance, see [API Keys](/box/api-keys).

<Warning>
  Treat Box API keys and returned desktop URLs as secrets. Desktop and VNC URLs can contain access tokens and should not be logged or persisted unredacted.
</Warning>

## Response envelope

Every v1 JSON response has an explicit success discriminator:

```json theme={null}
{
  "ok": true,
  "type": "box.list",
  "boxes": []
}
```

| Field  | Description                                                                                                    |
| ------ | -------------------------------------------------------------------------------------------------------------- |
| `ok`   | `true` for success, `false` for failure.                                                                       |
| `type` | Stable response or event discriminator, such as `box.list`, `box.created`, `box.stopping`, or `prompt.queued`. |

## Error model

HTTP status remains authoritative. Error bodies also use a structured JSON envelope:

```json theme={null}
{
  "ok": false,
  "type": "box.error",
  "status": 409,
  "code": "provider_not_configured",
  "message": "Prompting is locked until Codex is configured on the Agents page.",
  "error": {
    "code": "provider_not_configured",
    "message": "Prompting is locked until Codex is configured on the Agents page.",
    "status": 409,
    "details": {
      "provider": "codex",
      "setupUrl": "https://box.ascii.dev/dashboard?tab=agents"
    }
  },
  "requestId": "req_..."
}
```

| Status | Typical codes                                                                                               | What to do                                                                                               |
| ------ | ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `400`  | `invalid_json`, `prompt_required`, `provider_required`, `invalid_name`, `no_changes`, `machine_not_running` | Fix the request body, wait for the box machine to start, or retry once the box reaches a runnable state. |
| `401`  | `unauthorized`                                                                                              | Provide a valid bearer token.                                                                            |
| `402`  | `billing_required`                                                                                          | Send the user to the returned billing URL.                                                               |
| `404`  | `not_found`                                                                                                 | Refresh local state; the box or key no longer exists.                                                    |
| `409`  | `account_not_ready`, `provider_not_configured`, `box_not_promptable`, `resume_failed`, `fork_failed`        | Resolve the prerequisite or resource-state conflict.                                                     |
| `429`  | `rate_limited`, `daily_limit_reached`, `limit_reached`                                                      | Back off and show the limit message.                                                                     |
| `5xx`  | `invalid_json_response`, `stream_failed`, `http_500`                                                        | Retry idempotent calls with jitter and include `requestId` in support logs.                              |

## Box lifecycle

A Box moves through these states:

| State                                    | Meaning                                              | Client behavior                                                             |
| ---------------------------------------- | ---------------------------------------------------- | --------------------------------------------------------------------------- |
| `provisioning`, `provisioned`, `cloning` | The sandbox is being created or prepared.            | Poll `GET /boxes/{boxId}`.                                                  |
| `ready`, `idle`                          | The box can accept prompts and interactive access.   | Prompt, open desktop, SSH, or inspect events.                               |
| `running`                                | The Box is actively working.                         | Read events; interrupt only when the caller intends to stop current work.   |
| `archiving`                              | Stop/snapshot is in progress.                        | Poll until `archived` or another terminal state.                            |
| `archived`                               | The machine is stopped; a snapshot may be available. | Resume or fork.                                                             |
| `error`                                  | Provisioning or runtime failed.                      | Show the error and let the user stop, delete, resume, or fork when allowed. |

<Note>
  `idle` and `running` only reflect work queued through `POST /boxes/{boxId}/prompt`. Processes you run yourself, over SSH or the command endpoint, do not change the state: a box can show `idle` while your own agent works inside it.
</Note>

## Providers, models, and reasoning

`POST /boxes/{boxId}/prompt` accepts the same providers Box uses in the dashboard. The API accepts `codex` and `claude-code`; `claude` is accepted as an alias for `claude-code` by the current backend, but `claude-code` is the canonical value to store in integrations.

Model ids come from the same catalog used by the dashboard model selector. If you omit `model`, Box uses the user's saved dashboard default for that provider. Prefer the listed model ids for predictable behavior.

| Provider      | Models                                                | Reasoning effort values                                                                                                                                    | Default   |
| ------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| `codex`       | `gpt-5.5`, `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.3-codex` | `none`, `low`, `medium`, `high`, `xhigh` (`gpt-5.3-codex` supports `low`, `medium`, `high`, `xhigh`)                                                       | `gpt-5.4` |
| `claude-code` | `claude-fable-5`, `opus`, `sonnet`, `haiku`           | `claude-fable-5`: `low`, `medium`, `high`, `max`; `opus`: `low`, `medium`, `high`, `max`; `sonnet`: `low`, `medium`, `high`; `haiku`: no reasoning control | `sonnet`  |

Use the dashboard's provider setup page to configure credentials before prompting. If credentials are missing, the API returns `provider_not_configured` with a setup URL.

## Request examples

Set shared variables:

```bash theme={null}
export BOX_API_BASE="https://ascii.dev/api/box/v1"
export BOX_API_KEY="box_your_secret_here"
```

Create a one-hour box and store its id:

```bash theme={null}
BOX_ID=$(curl -sS -X POST "$BOX_API_BASE/boxes" \
  -H "Authorization: Bearer $BOX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ttlSeconds":3600}' | jq -r '.box.id')
```

Create a box without automatic archival:

```bash theme={null}
curl -sS -X POST "$BOX_API_BASE/boxes" \
  -H "Authorization: Bearer $BOX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ttlSeconds":null}'
```

Poll readiness:

```bash theme={null}
curl -sS "$BOX_API_BASE/boxes/$BOX_ID" \
  -H "Authorization: Bearer $BOX_API_KEY"
```

Prompt a Box to work in a repo:

```bash theme={null}
curl -sS -X POST "$BOX_API_BASE/boxes/$BOX_ID/prompt" \
  -H "Authorization: Bearer $BOX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "codex",
    "model": "gpt-5.4",
    "reasoningEffort": "medium",
    "prompt": "Work on the selected repo: run tests, fix failures, commit the result, and report the preview URL if you start a server."
  }'
```

Read Box work and lifecycle events:

```bash theme={null}
curl -sS "$BOX_API_BASE/boxes/$BOX_ID/events" \
  -H "Authorization: Bearer $BOX_API_KEY"
```

Get a desktop streaming URL for live inspection:

```bash theme={null}
curl -sS -X POST "$BOX_API_BASE/boxes/$BOX_ID/desktop?vnc=1" \
  -H "Authorization: Bearer $BOX_API_KEY"
```

To return a VNC URL that does not require an access token, send:

```bash theme={null}
curl -sS -X POST "$BOX_API_BASE/boxes/$BOX_ID/desktop?vnc=1" \
  -H "Authorization: Bearer $BOX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"publicAccess":true}'
```

Stop/archive a box when the workflow is complete:

```bash theme={null}
curl -sS -X POST "$BOX_API_BASE/boxes/$BOX_ID/stop" \
  -H "Authorization: Bearer $BOX_API_KEY"
```

## Endpoint reference

| Endpoint                                | Reference                                                                                                         |
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `GET /me`                               | [Get current Box user](/box/api/reference/account/get-current-box-user)                                           |
| `GET /limits`                           | [Get Box limits](/box/api/reference/account/get-box-limits)                                                       |
| `GET /repos`                            | [List GitHub repositories available to Box](/box/api/reference/account/list-github-repositories-available-to-box) |
| `POST /repos`                           | [Select repository for Boxes](/box/api/reference/account/select-repository-for-boxes)                             |
| `GET /api-keys`                         | [List API keys](/box/api/reference/account/list-api-keys)                                                         |
| `GET /secrets`                          | [Get Box secrets setup](/box/api/reference/account/get-box-secrets-setup)                                         |
| `POST /secrets`                         | [Update Box secrets setup](/box/api/reference/account/update-box-secrets-setup)                                   |
| `GET /boxes`                            | [List boxes](/box/api/reference/boxes/list-boxes)                                                                 |
| `POST /boxes`                           | [Create box](/box/api/reference/boxes/create-box)                                                                 |
| `GET /boxes/{boxId}`                    | [Get box](/box/api/reference/boxes/get-box)                                                                       |
| `PATCH /boxes/{boxId}`                  | [Update box](/box/api/reference/boxes/update-box)                                                                 |
| `POST /boxes/{boxId}/stop`              | [Stop and archive box](/box/api/reference/boxes/stop-and-archive-box)                                             |
| `POST /boxes/{boxId}/resume`            | [Resume box](/box/api/reference/boxes/resume-box)                                                                 |
| `POST /boxes/{boxId}/fork`              | [Fork box](/box/api/reference/boxes/fork-box)                                                                     |
| `POST /boxes/{boxId}/prompt`            | [Prompt Box](/box/api/reference/agent/prompt-box-agent)                                                           |
| `GET /boxes/{boxId}/events`             | [List box events](/box/api/reference/agent/list-box-events)                                                       |
| `GET /boxes/{boxId}/prompts/{promptId}` | [Get prompt run status](/box/api/reference/agent/get-prompt-run-status)                                           |
| `GET /boxes/{boxId}/files`              | [Read a file from a Box](/box/api/reference/agent/read-box-file)                                                  |
| `PUT /boxes/{boxId}/files`              | [Write a file in a Box](/box/api/reference/agent/write-box-file)                                                  |
| `POST /boxes/{boxId}/commands`          | [Execute a command in a Box](/box/api/reference/agent/execute-box-command)                                        |
| `GET /boxes/{boxId}/artifacts`          | [Download a Box artifact](/box/api/reference/agent/download-box-artifact)                                         |
| `POST /boxes/{boxId}/interrupt`         | [Interrupt running work](/box/api/reference/agent/interrupt-running-agent-work)                                   |
| `POST /boxes/{boxId}/desktop`           | [Get desktop streaming URL](/box/api/reference/agent/get-desktop-streaming-url)                                   |
| `POST /boxes/{boxId}/sshkey`            | [Configure box SSH key](/box/api/reference/agent/configure-box-ssh-key)                                           |
| `GET /snapshots`                        | [List snapshots](/box/api/reference/snapshots/list-snapshots)                                                     |
| `GET /boxes/{boxId}/snapshots`          | [List box snapshots](/box/api/reference/snapshots/list-box-snapshots)                                             |
| `GET /boxes/{boxId}/snapshots/latest`   | [Get latest box snapshot](/box/api/reference/snapshots/get-latest-box-snapshot)                                   |
| `GET /snapshots/{snapshotId}/tree`      | [Get snapshot file tree](/box/api/reference/snapshots/get-snapshot-tree)                                          |
| `GET /snapshots/{snapshotId}/files`     | [Download a file or folder from a snapshot](/box/api/reference/snapshots/get-snapshot-file)                       |
| `GET /snapshots/{snapshotId}/download`  | [Get snapshot download](/box/api/reference/snapshots/get-snapshot-download)                                       |
