Cubicle

Restore a Box from a snapshot

POST
/v1/boxes/{box}/restore

Queues replacing a stopped Box's disk with one of its own complete snapshots, and returns the restore operation with 202 Accepted. Poll the operation until it is done, then start the Box: it stays stopped. 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 must be desired stopped, and should be stopped at the current generation: otherwise the operation can fail with box must be stopped.
  • The snapshot must be this Box's. To use another Box's snapshot, create a Box from it.
  • The disk is replaced as a whole. The Box keeps its ID, name, private IP, size and grants.
  • connectionGeneration advances at once, and guest accounts are applied again from the current grants and SSH keys; see What a restore changes.
  • Until the operation ends, starting, stopping, hibernating and deleting the Box return 409 conflict.

With an Idempotency-Key, repeating the request with the same body returns 202 with the operation the first request created.

Authorization

headerAuthorizationBearer <token>

A service account API key (cbk_…), used directly as the bearer token. read keys may call only GET routes.

Path Parameters

box*string

The Box's ID, ORG/NAME with the slash encoded as %2F, or a bare NAME, which ?org= narrows. See Box references.

Query Parameters

org?string

The organization's ID or name, to narrow a bare NAME in {box}. Ignored for an ID or ORG/NAME.

Header Parameters

Idempotency-Key?string

Makes the request safe to retry: repeating it with the same key and body returns the first result instead of doing the work again. 1 to 200 characters; a UUID is a good choice.

Length1 <= length <= 200

Request Body

application/json
  1. body
snapshotId*string
Formatuuid

Response Body

The restore operation: new, or the original one for an Idempotency-Key replay.

application/json
  1. response
id*string

The operation's ID.

boxId*string

The ID of the Box it runs on.

type*string

exec for a command, snapshot or restore.

Value in"exec""snapshot""restore"
state*OperationState

pending until the Box's Node picks it up, then running, and finally done, failed or unknown. unknown means it was interrupted and its outcome is not known; it is never retried.

Value in"pending""running""done""failed""unknown"
attempt*number

How many times a Node has picked it up: 0 while pending, then 1.

progress*|

Reserved for progress notes. Current Nodes do not send any, so it is null.

result*unknown

null until done. A done exec holds an ExecResult, shown only to the member who requested it and null for everyone else. A done restore holds { "snapshotId": … }. A done snapshot holds an internal manifest; read the snapshot from the Box's snapshot list instead.

error*|

Why it failed or became unknown; otherwise null.

createdAt*string

When it was requested.

startedAt*|

When a Node picked it up, or null while pending.

completedAt*|

When it reached done, failed or unknown, or null before.

Example Request
curl -X POST 'https://api.cubicle.sh/v1/boxes/acme%2Fjob-1/restore' \  -H 'Idempotency-Key: 4f1c7c1e-6a43-4d5e-9b7e-0d2f6c0e9a51' \  -H 'Content-Type: application/json' \  -d '{  "snapshotId": "5a7c9e1b-3d5f-4a6b-8c0d-2e4f6a8b0c3d"}'
Example Response
{  "id": "6c8e0a2c-4e6a-4b8c-9e0a-4c6e8a0c2e5b",  "boxId": "0f6c2a5e-3b1d-4c8e-9a7f-2d4e6b8c1a3f",  "type": "restore",  "state": "pending",  "attempt": 0,  "progress": null,  "result": null,  "error": null,  "createdAt": "2026-11-05T10:30:00.000Z",  "startedAt": null,  "completedAt": null}