Run a command
Queues argv to run in the Box and returns an operation with 202 Accepted. Poll the operation until its state is done, failed or unknown; a done exec's result holds the exit code and output. See Following a request.
The caller needs an explicit grant on the Box: the owner or admin role is not enough. API keys need the write scope, and their service account needs the grant.
- The Box must be desired
running. Wait untilssh.readyistruefirst: an exec accepted before the Box is running can fail withbox is not running at the requested generation. - The command runs as the caller's guest account, in its home directory unless
cwdis set, without a shell, a TTY or stdin; use["sh", "-c", "…"]for shell syntax. It has passwordlesssudoonly once the caller has an SSH key, so a service account's commands cannot rely onsudo; see Root and sudo. timeoutMsdefaults to 60,000 (60 s), and larger values than 600,000 (10 min) are lowered to it without an error. A command that runs out of time is killed and reportstimedOut: trueand exit code124.maxOutputBytesdefaults to 65,536 (64 KiB), and larger values than 1,048,576 (1 MiB) are lowered to it. It is one budget for stdout and stderr together; the rest is discarded andtruncatedistrue.- A non-zero exit code or a timeout still ends
done.failedcomes with anerror, for example when the Box stopped or the caller lost its grant before the command started.unknownmeans it was interrupted and may or may not have run. Neither is run again; see Operations record every request. - Only the caller sees the result. Other members of the organization can read the operation, but its
resultisnullfor them.
With an Idempotency-Key, repeating the request with the same body returns 202 with the operation the first request created, and runs nothing. Output is returned only when the command ends. See Run commands.
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.
Idempotency-Key?stringMakes 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.
1 <= length <= 200application/json- body
argv*array<>1 <= items <= 1024timeoutMs?integer100 <= value <= 9007199254740991maxOutputBytes?integer0 <= value <= 9007199254740991cwd?string^\/.*starts_withlength <= 4096The exec operation: new, or the original one for an Idempotency-Key replay.
application/json- response
id*stringThe operation's ID.
boxId*stringThe ID of the Box it runs on.
type*stringexec for a command, snapshot or restore.
"exec""snapshot""restore"state*OperationStatepending 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.
"pending""running""done""failed""unknown"attempt*numberHow 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*unknownnull 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*stringWhen 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.
curl -X POST 'https://api.cubicle.sh/v1/boxes/acme%2Fjob-1/exec' \ -H 'Idempotency-Key: 4f1c7c1e-6a43-4d5e-9b7e-0d2f6c0e9a51' \ -H 'Content-Type: application/json' \ -d '{ "argv": [ "uname", "-a" ], "timeoutMs": 30000}'{ "id": "9d2e4f6a-1b3c-4d5e-8f7a-6b8c0d2e4f1a", "boxId": "0f6c2a5e-3b1d-4c8e-9a7f-2d4e6b8c1a3f", "type": "exec", "state": "pending", "attempt": 0, "progress": null, "result": null, "error": null, "createdAt": "2026-11-05T10:16:00.000Z", "startedAt": null, "completedAt": null}
