Stop a Box
Sets the Box's desired state to stopped and returns it with 202 Accepted. The Node asks the guest to shut down, and turns it off if it has not stopped about 15 seconds later. Poll Get a Box until state is stopped and observed.generation equals desired.generation. Until then, state and observed show the Node's last report; see Following a request.
The caller needs a grant on the Box, or the owner or admin role in its organization. API keys need the write scope.
The Box keeps its disk, its private IP and its reserved CPU, memory and disk space. Its memory and running processes are lost, as is a hibernated Box's saved memory, and commands still running end with state unknown. Every accepted stop advances desired.generation and connectionGeneration, even when the Box is already stopped, and clears restartRequired. Snapshots and restores need a stopped Box.
See What stop, hibernate and delete keep.
AuthorizationBearer <token>A service account API key (cbk_…), used directly as the bearer token. read keys may call only GET routes.
box*stringThe Box's ID, ORG/NAME with the slash encoded as %2F, or a bare NAME, which ?org= narrows. See Box references.
org?stringThe organization's ID or name, to narrow a bare NAME in {box}. Ignored for an ID or ORG/NAME.
The Box with its new desired state.
application/json- response
storage?The state of background checkpoint uploads of the Box's disk and saved memory to remote storage. Every Box response includes it. It is informational: no route restores a Box from a checkpoint.
id*stringThe Box's ID. It never changes.
baseImage*BaseImageIdThe base image the Box's disk was created from. A Box created from a snapshot has its source Box's image.
"default""omarchy"org*The organization that owns the Box.
name*stringUnique among the organization's Boxes that are not deleted: the NAME in ORG/NAME.
node*The Node (host) the Box runs on. A Box never moves to another Node.
spec*The CPU, memory and disk reserved for the Box on its Node for its whole life, also while it is stopped or hibernated. A free Box (pooled) gives its CPU and memory back while it is stopped or hibernated.
desired*What the Box was last asked to be.
observed*|The Node's latest report on the Box, or null before its first report.
state*BoxStateThe observed state when the report is fresh. pending before the Node's first report, unknown when the report is stale or the Node is unhealthy, which means neither running nor stopped, and deleted once the Node has removed a deleted Box.
"pending""unknown""deleted""absent""provisioning""starting""running""stopping""stopped""hibernating""hibernated""deleting""failed"hibernateAt*|When the Box hibernates automatically: 60 minutes after it first reported running since its latest start; see Box lifecycle. null until that report, and whenever the Box is not desired running or restartRequired is true. After a failed hibernation it stays in the past until the retry.
hibernationRetryAt*|When Cubicle tries again to hibernate the Box after a failed attempt, 30 s after the first failure and doubling up to 5 min; otherwise null.
pooled*booleanA free Box: its CPU and memory are reserved only while it runs.
expiresAt*|When a stopped or hibernated free Box is deleted unless it is started again.
restartRequired*booleanWhether the Box's host restarted while the Box was desired running. The Box stays down until a start request, which clears it; a stop also clears it.
connectionGeneration*numberAdvances with every start, stop, hibernation (automatic ones too), delete and restore, and when the Box's host restarts, but not when a failed hibernation returns the Box to running. SSH and private-network traffic reaches the Box only once it runs at the new value; see Generations.
privateIp*|The Box's IPv4 address on its Node's private subnet, reachable only over Cubicle's private network. null until the Box is first provisioned; it then stays the same for the Box's life.
console*Whether the Dashboard console can be used now.
ssh*Whether the Box is ready for commands and SSH now.
deletion*|pending from an accepted delete until the Node has removed the Box, after which listings no longer show it; otherwise null. complete appears only when an Idempotency-Key replay of a create returns a Box removed since.
"pending""complete"nullcreatedAt*stringWhen the Box was created.
curl -X POST 'https://api.cubicle.sh/v1/boxes/acme%2Fjob-1/stop'{ "storage": { "enabled": true, "status": "unprotected", "checkpointId": null, "checkpointAt": null, "current": false, "processedBytes": 0, "totalBytes": 0, "error": null, "retryAt": null }, "id": "0f6c2a5e-3b1d-4c8e-9a7f-2d4e6b8c1a3f", "org": { "id": "6b1f3d2a-8c4e-4f7a-9b2d-1e5c7a9f3b6d", "name": "acme" }, "name": "job-1", "baseImage": "default", "node": { "id": "c3a9e1f7-5b2d-4a8c-8e6f-0d1b3c5e7a9f", "name": "node-1", "healthy": true }, "spec": { "vcpus": 2, "memoryMiB": 2048, "diskGiB": 12 }, "sourceSnapshotId": null, "desired": { "state": "stopped", "generation": 2 }, "observed": { "state": "running", "generation": 1, "observedAt": "2026-11-05T10:15:04.000Z", "ageSeconds": 2, "fresh": true, "error": null }, "state": "running", "hibernateAt": null, "hibernationRetryAt": null, "pooled": false, "expiresAt": null, "restartRequired": false, "connectionGeneration": 2, "privateIp": "10.20.30.17", "console": { "ready": false, "reason": "not_requested" }, "ssh": { "ready": false, "reason": "not_requested" }, "deletion": null, "createdAt": "2026-11-05T10:14:21.000Z"}
