---
title: "Create box"
method: POST
path: "/boxes"
tags: ["Box"]
---

# Create box

`POST /boxes`

Provision a new cloud computer. Store the returned `box.id` with your product job/session record.

## Request body

- CreateBoxRequest — Options for provisioning a new cloud computer.
  - `ttlSeconds` integer, nullable — Number of seconds before automatic archival. `null` disables auto-stop. The backend also accepts the string `infinite` for legacy compatibility; new clients should send null.
  - `env` object — Per-box environment variables injected into the box's tool environment, on top of the account environment's variables (per-box values win on conflicts). Keys must match `[A-Za-z_][A-Za-z0-9_]{0,127}`; at most 100 variables and 64KB total. Reserved names (`ASCII_TOKEN`, `ASCII_API_URL`, `AGENT_ID`, `PRODUCT_MODE`, `ENVIRONMENT_ID`, `BOX_ID`, `SERVICE_PREVIEW_TOKEN`, `BOX_CLI_TOKEN`) are rejected with `invalid_env`. Forked boxes inherit the source box's env unless the fork request supplies its own `env`.
  - `noEnv` boolean — Create a box with none of the secrets attached to your account (no environment variables, secret files, or credentials), confined to itself so it cannot act on your account or other boxes. For boxes you give to your own users. SSH, SCP, desktop, snapshots, and public URLs still work; pass `env` to give the box a secret of its own. A fork of a no-env box is always no-env.

## Response `202`

Box accepted for provisioning.

- CreateBoxResponse
  - `ok` boolean, required
  - `type` 'box.created', required — Stable success envelope discriminator added by v1.
  - `status` 'provisioning', required
  - `ttlSeconds` integer, nullable, required
  - `box` Box, required
    - `id` string, required
    - `name` string, required
    - `state` 'init' | 'provisioning' | 'provisioned' | 'cloning' | 'ready' | 'idle' | 'running' | 'archiving' | 'archived' | 'error', required
    - `url` string, uri, nullable — Machine URL when assigned.
    - `ip` string, nullable — Machine IPv4 address when assigned.
    - `createdAt` string, date-time, nullable
    - `updatedAt` string, date-time, nullable
    - `archiveAfter` string, date-time, nullable — Automatic archival time, or null when auto-stop is disabled.
    - `desktopAvailable` boolean, required
    - `desktopUrl` string, uri, nullable — Secret-bearing desktop stream URL when available. Redact from logs.
    - `snapshotAvailable` boolean, required
    - `snapshotCompletedAt` string, date-time, nullable — Timestamp of the most recent successfully completed snapshot, or null.
    - `subdomain` string, nullable — The box's stable three-word subdomain slug (e.g. "frazil-pneuma-rallye"), or null before one is assigned.
    - `lastSnapshotAttemptAt` string, date-time, nullable — Timestamp of the most recent snapshot attempt of any status (queued, in_progress, completed, failed, cancelled), or null. Use with snapshotCompletedAt to detect snapshots that keep failing.
    - `lastSnapshotStatus` 'queued' | 'in_progress' | 'completed' | 'failed' | 'cancelled' | 'null', nullable — Status of the most recent snapshot attempt, or null if none. A value other than completed while snapshotCompletedAt stays stale indicates failing snapshots.

## Other responses

- `401` — Missing or invalid bearer token.
- `402` — Account cannot currently create or operate Boxes. The error body may include a dashboard billing URL, but billing actions are not part of the v1 API.
- `409` — Request conflicts with current account or box state.
- `429` — Creation or active-box limit reached.

---

[API](https://skmtc.dev/ascii/apis/box-public-api-v1.md) · [All operations](https://skmtc.dev/ascii/apis/box-public-api-v1/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/ascii/box-public-api-v1/revisions/82d576f82046/schema)
