Sandboxes
edge*stringRegion tag of the sandboxes the socket will carry, or _. Routing only.
Switching Protocols: the sandbox-events WebSocket (subprotocol rlp.events.v1). Authenticated by a single-use ticket from POST /events/{edge}/ticket, carried as Sec-WebSocket-Protocol: rlp.events.v1, rlp.ticket.<ticket>; frames are JSON per clients/contract/sandbox-events-protocol.json.
curl -X GET 'https://example.com/events/string'AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: read:sandboxes
edge*stringRegion tag of the sandboxes the socket will carry (the part after the dash in a sandbox id), or _ when the ids carry no tag. Routing only: the cell accepts any sandbox it owns.
A single-use ticket for one GET /events/{edge} upgrade
application/json- response
POST /events/{edge}/ticket response.
expires_in_ms*integerMilliseconds until the ticket expires unused.
int640 <= valuesubprotocol*stringThe subprotocol to negotiate alongside the ticket.
ticket*stringOpaque, single-use; present it as the rlp.ticket.<ticket>
subprotocol on the upgrade.
curl -X POST 'https://example.com/events/string/ticket'{ "expires_in_ms": 0, "subprotocol": "string", "ticket": "string"}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: read:sandboxes
limit?integerPage size (list mode). Clamped server-side; ignored with ids.
int64cursor?stringOpaque continuation token from a previous page's next_cursor (or a
row's own cursor). Ignored with ids.
ids?stringComma-separated external sandbox ids (max 200) — switches to batch-wait mode. Malformed/unowned ids are silently omitted from the result.
wait?stringBatch-wait mode: block until at least one id reaches this status (or a terminal state).
wait_exact?stringLike wait, but the status must be reached exactly (terminal-bound
states other than the target do not satisfy it). Takes precedence.
timeout_ms?integerMax time to block in batch-wait mode, ms. Clamped to [0, 60000]; default 30000.
int640 <= valuelabels?stringLabel filter (list mode, migration 0053): a JSON-encoded object
{"k":"v",...}. Only sandboxes whose labels CONTAIN every pair are
returned. Malformed / non-object => 400. Ignored with ids.
Sandboxes in the project (keyset-paginated, newest first) — or, with ids=, a snapshot of the requested set after the optional wait
application/json- response
Response shape for GET /sandboxes. Schema-only (the handler assembles the JSON):
in list mode vms is the keyset page (each item a sandbox row plus its
created_at + per-row resume cursor) and next_cursor the whole-page
continuation (null on the last page). In batch-wait mode (?ids=) vms is
a snapshot of every requested id the caller owns (plain sandbox rows, no
created_at/cursor) and next_cursor is absent.
next_cursor?string|nullvms*array<>curl -X GET 'https://example.com/sandboxes'{ "next_cursor": "string", "vms": [ { "class": "string", "cpu": 0.1, "create_ttl_expires_at": "2019-08-24T14:15:22Z", "error": "string", "host_ip": "string", "id": "string", "image": null, "manifest_name": "string", "mem_max_mib": 0, "mem_mib": 0, "name": "string", "port_map": null, "region": "string", "runner_id": "string", "scratch_max_mib": 0, "scratch_mib": 0, "snapshot": null, "status": "string", "user": "string", "vcpus": 0, "vcpus_max": 0, "created_at": "2019-08-24T14:15:22Z", "cursor": "string", "gpu_host_count": 0, "labels": null, "lifecycle": { "idle_timeout_at": "string", "idle_timeout_secs": 0, "last_activity_at": "string", "last_activity_source": "string", "on_idle_timeout": null, "on_timeout": null, "timeout_at": "string", "timeout_secs": 0, "wake_on_request": true }, "mac_boot_mode": "string", "mac_checkpoint_state": "string", "os_family": "string", "persistent": true, "spot": true, "spot_evicted_at": "2019-08-24T14:15:22Z", "toolbox_proxy_url": "string", "windows_image": "string" } ]}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
application/json- body
POST /sandboxes body (PLAN-CREATION-SHAPE §2).
image is a string: a registered name or a typed img_… id; omitted, the
cell's platform default image (PLAN-PLATFORM-IMAGES.md).
Dockerfile-in-create, registry refs, and the old VmImageInput object
forms are removed — use POST /images to build first.
cpu?|doublecpu_arch?string|nullcpu_type?string|nullcreate_ttl?|Budget in seconds for the sandbox to reach running before being
deleted. Omitted => DAYTONA_CREATE_TTL_DEFAULT (3600). -1 =>
DAYTONA_CREATE_TTL_MAX (86400). 0/<-1/>MAX => 400.
int64env?Sandbox-specific environment variables (real values, verbatim). Names
must be POSIX-ish identifiers ([A-Za-z_][A-Za-z0-9_]*); names in the
platform's reserved namespaces (the daemon's own RLP prefix followed
by an underscore, and DAYTONA_* other than DAYTONA_SANDBOX_TOKEN,
DAYTONA_API_URL, DAYTONA_OTEL_ENDPOINT and DAYTONA_DOCKER_START)
fail the create with 400 naming the key.
idempotency_key?string|nullimage?|Image name or img_… id. Omit to boot the platform default image.
labels?lifecycle?null|mem_max_mib?|Per-sandbox memory limit in MiB; same semantics as vcpus_max.
int32mem_mib?|int32name?string|nullnetwork_policy?null|persistent?booleanports?array<>region?string|nullscratch_max_mib?|Per-sandbox disk limit in MiB: the writable layer's size. Same semantics
as vcpus_max; a disk-snapshot restore requires it equal to the
captured disk, or absent.
int32scratch_mib?|int32secrets?array<string>spot?booleanuser?string|nullvcpus?|int32vcpus_max?|Per-sandbox vCPU limit in whole vCPUs (PLAN-BURSTABLE-ONLY.md): the boot shape and the CPU ceiling. Absent => the system cap. Set equal to the request for a fixed shape.
int32volumes?array<>wait?|Server-hold seconds. Omitted => DAYTONA_CREATE_WAIT_MAX (3).
0 => respond immediately. <0 => 400.
int64Sandbox admitted (status may be queued/pending/running depending on wait), or an idempotent replay of an earlier create
application/json- response
Response for POST /sandboxes — the fresh create, the idempotent replay, and the
snapshot-restore paths all share this shape. Field order is alphabetical to
keep the wire bytes identical to the former serde_json::json! construction.
access_token?|The sandbox's data-plane access token, returned ONCE at create time.
Null on an idempotent replay (the original create already returned
it). While the deployment's data-plane compat window is open (the
ship default) this is the non-expiring per-VM dtnv_… token; once
the deployment flips compat off it is a full-grant sandbox JWT whose
expiry rides in access_token_expires_at (PLAN-SANDBOX-TOKEN-JWT.md).
passwordaccess_token_expires_at?|Expiry of access_token (RFC 3339). Null while the compat window has
access_token carrying the non-expiring dtnv_ credential, and null
on an idempotent replay; set once the compat flip makes
access_token a sandbox JWT — mint a fresh token via
POST /sandboxes/{id}/access-token before it lapses.
date-timecreate_ttl_expires_at?|date-timeimage?null|job_id?|Create/restore job id. Null on an idempotent replay.
uuidname*stringSandbox name (caller-provided or the generated sandbox-<short-id>).
reservation_id?|macOS only: the external id of the Mac lease whose slot admitted the sandbox — one of the organization's leases, or the one this create bought. Omitted for every other class.
status*stringInitial lifecycle status — pending, or the sandbox's current status on
an idempotent replay.
toolbox_proxy_url*stringThe sandbox's own region's toolbox proxy base URL, the same value
GET /sandboxes/{id} carries — exec/fs/preview traffic must target
this, not a global proxy.
vm_id*stringExternal sandbox id: base58-encoded UUID with a -<region> suffix
(e.g. 7fJk2mQpXv9dLc3RtY-use1); a bare UUID in single-region mode.
wait_cap*integerint640 <= valuecurl -X POST 'https://example.com/sandboxes' \ -H 'Content-Type: application/json' \ -d '{}'{ "access_token": "pa$$word", "access_token_expires_at": "2019-08-24T14:15:22Z", "create_ttl_expires_at": "2019-08-24T14:15:22Z", "image": null, "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f", "name": "string", "reservation_id": "string", "status": "string", "toolbox_proxy_url": "string", "vm_id": "string", "wait_cap": 0}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
application/json- body
POST /sandboxes/from-snapshot body (PLAN-CREATION-SHAPE §2).
Shared fields only — no cpu/memory/disk/spot/env/user (those are fixed by
the captured memory image). deny_unknown_fields makes the compile-time
absence of those fields a runtime 400 for callers who send them.
Only the fields a memory restore honours today. volumes and secrets
are not fields of this body until restore_vm_internal supports them — a
silently dropped field is worse than a 400, and PLAN-CREATION-SHAPE §2
makes the difference a shape fact (deny_unknown_fields) rather than a
runtime guard. Neither is persistent: the restored sandbox inherits the
persistence of the sandbox the snapshot was captured from.
create_ttl?|int64idempotency_key?string|nulllabels?lifecycle?null|name?string|nullports?array<>region?string|nullsnapshot*stringSnapshot name or snap_… id. Required.
wait?|int64Sandbox restore admitted (or an idempotent replay)
application/json- response
Response for POST /sandboxes — the fresh create, the idempotent replay, and the
snapshot-restore paths all share this shape. Field order is alphabetical to
keep the wire bytes identical to the former serde_json::json! construction.
access_token?|The sandbox's data-plane access token, returned ONCE at create time.
Null on an idempotent replay (the original create already returned
it). While the deployment's data-plane compat window is open (the
ship default) this is the non-expiring per-VM dtnv_… token; once
the deployment flips compat off it is a full-grant sandbox JWT whose
expiry rides in access_token_expires_at (PLAN-SANDBOX-TOKEN-JWT.md).
passwordaccess_token_expires_at?|Expiry of access_token (RFC 3339). Null while the compat window has
access_token carrying the non-expiring dtnv_ credential, and null
on an idempotent replay; set once the compat flip makes
access_token a sandbox JWT — mint a fresh token via
POST /sandboxes/{id}/access-token before it lapses.
date-timecreate_ttl_expires_at?|date-timeimage?null|job_id?|Create/restore job id. Null on an idempotent replay.
uuidname*stringSandbox name (caller-provided or the generated sandbox-<short-id>).
reservation_id?|macOS only: the external id of the Mac lease whose slot admitted the sandbox — one of the organization's leases, or the one this create bought. Omitted for every other class.
status*stringInitial lifecycle status — pending, or the sandbox's current status on
an idempotent replay.
toolbox_proxy_url*stringThe sandbox's own region's toolbox proxy base URL, the same value
GET /sandboxes/{id} carries — exec/fs/preview traffic must target
this, not a global proxy.
vm_id*stringExternal sandbox id: base58-encoded UUID with a -<region> suffix
(e.g. 7fJk2mQpXv9dLc3RtY-use1); a bare UUID in single-region mode.
wait_cap*integerint640 <= valuecurl -X POST 'https://example.com/sandboxes/from-snapshot' \ -H 'Content-Type: application/json' \ -d '{ "snapshot": "string"}'{ "access_token": "pa$$word", "access_token_expires_at": "2019-08-24T14:15:22Z", "create_ttl_expires_at": "2019-08-24T14:15:22Z", "image": null, "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f", "name": "string", "reservation_id": "string", "status": "string", "toolbox_proxy_url": "string", "vm_id": "string", "wait_cap": 0}Create a GPU sandbox. Behind a feature flag: GPU sandboxes are experimental and available only to organizations with the gpu_sandboxes feature flag enabled; other organizations get 403 FEATURE_FLAG_DISABLED.
AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
application/json- body
cpu?|doublecreate_ttl?|int64env?Sandbox-specific environment variables (real values, verbatim). Names
must satisfy the shared guest-env rules: POSIX-ish identifiers, and
names in the platform's reserved namespaces (the daemon's own RLP
prefix followed by an underscore, and DAYTONA_ other than
DAYTONA_SANDBOX_TOKEN, DAYTONA_API_URL, DAYTONA_OTEL_ENDPOINT and
DAYTONA_DOCKER_START) fail the create with 400 naming the key.
gpu?array<string>gpu_host?integerint320 <= valueidempotency_key?string|nullimage*stringlabels?lifecycle?null|mem_max_mib?|Per-sandbox memory limit in MiB; same semantics as vcpus_max.
int32mem_mib?|int32name?string|nullports?array<>region?|Target region slug (PLAN-REGIONS.md). Absent => resolved default.
scratch_max_mib?|Per-sandbox disk limit in MiB: the writable layer's size. Same semantics
as vcpus_max; a disk-snapshot restore requires it equal to the
captured disk, or absent.
int32scratch_mib?|int32secrets?array<string>user?string|nullvcpus?|int32vcpus_max?|Per-sandbox vCPU limit in whole vCPUs (PLAN-BURSTABLE-ONLY.md): the boot shape and the CPU ceiling. Absent => the system cap. Set equal to the request for a fixed shape.
int32wait?|int64GPU sandbox admitted (or an idempotent replay)
application/json- response
Response for POST /sandboxes — the fresh create, the idempotent replay, and the
snapshot-restore paths all share this shape. Field order is alphabetical to
keep the wire bytes identical to the former serde_json::json! construction.
access_token?|The sandbox's data-plane access token, returned ONCE at create time.
Null on an idempotent replay (the original create already returned
it). While the deployment's data-plane compat window is open (the
ship default) this is the non-expiring per-VM dtnv_… token; once
the deployment flips compat off it is a full-grant sandbox JWT whose
expiry rides in access_token_expires_at (PLAN-SANDBOX-TOKEN-JWT.md).
passwordaccess_token_expires_at?|Expiry of access_token (RFC 3339). Null while the compat window has
access_token carrying the non-expiring dtnv_ credential, and null
on an idempotent replay; set once the compat flip makes
access_token a sandbox JWT — mint a fresh token via
POST /sandboxes/{id}/access-token before it lapses.
date-timecreate_ttl_expires_at?|date-timeimage?null|job_id?|Create/restore job id. Null on an idempotent replay.
uuidname*stringSandbox name (caller-provided or the generated sandbox-<short-id>).
reservation_id?|macOS only: the external id of the Mac lease whose slot admitted the sandbox — one of the organization's leases, or the one this create bought. Omitted for every other class.
status*stringInitial lifecycle status — pending, or the sandbox's current status on
an idempotent replay.
toolbox_proxy_url*stringThe sandbox's own region's toolbox proxy base URL, the same value
GET /sandboxes/{id} carries — exec/fs/preview traffic must target
this, not a global proxy.
vm_id*stringExternal sandbox id: base58-encoded UUID with a -<region> suffix
(e.g. 7fJk2mQpXv9dLc3RtY-use1); a bare UUID in single-region mode.
wait_cap*integerint640 <= valuecurl -X POST 'https://example.com/sandboxes/gpu' \ -H 'Content-Type: application/json' \ -d '{ "image": "string"}'{ "access_token": "pa$$word", "access_token_expires_at": "2019-08-24T14:15:22Z", "create_ttl_expires_at": "2019-08-24T14:15:22Z", "image": null, "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f", "name": "string", "reservation_id": "string", "status": "string", "toolbox_proxy_url": "string", "vm_id": "string", "wait_cap": 0}Restore a GPU checkpoint snapshot into a new GPU sandbox. Behind a feature flag: GPU sandboxes are experimental and available only to organizations with the gpu_sandboxes feature flag enabled; other organizations get 403 FEATURE_FLAG_DISABLED.
AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
application/json- body
Only the fields a checkpoint restore honours today. volumes,
object_store_mounts, egress_policy, secrets and persistent are not
fields of this body at all — a GPU checkpoint restore cannot apply them, and
PLAN-CREATION-SHAPE §2 makes that a shape fact (deny_unknown_fields), not
a runtime 400.
create_ttl?|int64idempotency_key?string|nulllabels?lifecycle?null|name?string|nullports?array<>region?string|nullsnapshot*stringwait?|int64GPU checkpoint restore admitted (or an idempotent replay)
application/json- response
Response for POST /sandboxes — the fresh create, the idempotent replay, and the
snapshot-restore paths all share this shape. Field order is alphabetical to
keep the wire bytes identical to the former serde_json::json! construction.
access_token?|The sandbox's data-plane access token, returned ONCE at create time.
Null on an idempotent replay (the original create already returned
it). While the deployment's data-plane compat window is open (the
ship default) this is the non-expiring per-VM dtnv_… token; once
the deployment flips compat off it is a full-grant sandbox JWT whose
expiry rides in access_token_expires_at (PLAN-SANDBOX-TOKEN-JWT.md).
passwordaccess_token_expires_at?|Expiry of access_token (RFC 3339). Null while the compat window has
access_token carrying the non-expiring dtnv_ credential, and null
on an idempotent replay; set once the compat flip makes
access_token a sandbox JWT — mint a fresh token via
POST /sandboxes/{id}/access-token before it lapses.
date-timecreate_ttl_expires_at?|date-timeimage?null|job_id?|Create/restore job id. Null on an idempotent replay.
uuidname*stringSandbox name (caller-provided or the generated sandbox-<short-id>).
reservation_id?|macOS only: the external id of the Mac lease whose slot admitted the sandbox — one of the organization's leases, or the one this create bought. Omitted for every other class.
status*stringInitial lifecycle status — pending, or the sandbox's current status on
an idempotent replay.
toolbox_proxy_url*stringThe sandbox's own region's toolbox proxy base URL, the same value
GET /sandboxes/{id} carries — exec/fs/preview traffic must target
this, not a global proxy.
vm_id*stringExternal sandbox id: base58-encoded UUID with a -<region> suffix
(e.g. 7fJk2mQpXv9dLc3RtY-use1); a bare UUID in single-region mode.
wait_cap*integerint640 <= valuecurl -X POST 'https://example.com/sandboxes/gpu/from-snapshot' \ -H 'Content-Type: application/json' \ -d '{ "snapshot": "string"}'{ "access_token": "pa$$word", "access_token_expires_at": "2019-08-24T14:15:22Z", "create_ttl_expires_at": "2019-08-24T14:15:22Z", "image": null, "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f", "name": "string", "reservation_id": "string", "status": "string", "toolbox_proxy_url": "string", "vm_id": "string", "wait_cap": 0}Create a macOS sandbox on a Mac the organization leases. Behind a feature flag: macOS sandboxes are available only to organizations with the macos_sandboxes feature flag enabled; other organizations get 403 FEATURE_FLAG_DISABLED.
AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
application/json- body
POST /sandboxes/macos body. deny_unknown_fields: fields of other classes
(volumes, egress, docker, gpu, resource requests and limits, …) are named
400s. There is no size: every macOS sandbox gets a fixed half of the Mac's
cores and memory (each limit equal to its request), reported on the
sandbox once it runs.
auto_renew?|With reservation: "new" only: whether the bought lease renews itself
while a sandbox is active on it. Defaults to the organization's
auto-reserve setting.
create_ttl?|Seconds the sandbox may take to reach running (default
DAYTONA_CREATE_TTL_DEFAULT, -1 = the server max). Past it the
sandbox is deleted. The budget runs while the sandbox waits for a Mac,
including one whose lease this create bought: that lease stays bought
and charged when the sandbox is deleted.
int64env?Sandbox-specific environment variables. Names must satisfy the shared guest-env rules.
idempotency_key?|Idempotency key; the Idempotency-Key header wins if both are set.
It also covers a lease the create buys: a retry never buys two.
image*stringThe macOS base image, by name or img_… id: one of the global macOS
images the deployment seeds from DAYTONA_MACOS_GOLDEN_IMAGES
(base-macos unless configured otherwise). The Mac clones the base it
holds under that name.
labels?Control-plane-only labels.
lifecycle?null|name?|Optional sandbox name (defaults to sandbox-<short-id>).
persistent?booleanKeep the disk across stop and lease end: every stop writes a
checkpoint, and start restores it on any Mac the organization leases.
ports?array<>region?|Target region slug. Absent => the named reservation's region, else the resolved default.
reservation?|Which Mac lease admits the sandbox. Absent: a free slot on one of the
organization's leases in the region; with none free and the
organization's auto-reserve setting on, the create buys a 24-hour
lease (origin: auto, auto_renew: true) and the sandbox waits in
pending until a Mac takes it. "new": always buy a lease for this
sandbox (no opt-in needed). A reservation id: exactly that lease.
secrets?array<string>Not supported on macOS (there is no egress substitution); a non-empty
list is a 400 secrets_unsupported_on_macos.
wait?|Seconds to hold the response until the sandbox is running, capped at
DAYTONA_CREATE_WAIT_MAX (3 by default). Absent holds for the cap; 0
answers at once; a negative value answers 400. The response carries the
status when the hold ends: running if the sandbox got there in time,
as a warm Mac's claim usually does, otherwise its status then, such as
pending.
int64macOS sandbox create enqueued (or an idempotent replay); reservation_id names the admitting lease
application/json- response
Response for POST /sandboxes — the fresh create, the idempotent replay, and the
snapshot-restore paths all share this shape. Field order is alphabetical to
keep the wire bytes identical to the former serde_json::json! construction.
access_token?|The sandbox's data-plane access token, returned ONCE at create time.
Null on an idempotent replay (the original create already returned
it). While the deployment's data-plane compat window is open (the
ship default) this is the non-expiring per-VM dtnv_… token; once
the deployment flips compat off it is a full-grant sandbox JWT whose
expiry rides in access_token_expires_at (PLAN-SANDBOX-TOKEN-JWT.md).
passwordaccess_token_expires_at?|Expiry of access_token (RFC 3339). Null while the compat window has
access_token carrying the non-expiring dtnv_ credential, and null
on an idempotent replay; set once the compat flip makes
access_token a sandbox JWT — mint a fresh token via
POST /sandboxes/{id}/access-token before it lapses.
date-timecreate_ttl_expires_at?|date-timeimage?null|job_id?|Create/restore job id. Null on an idempotent replay.
uuidname*stringSandbox name (caller-provided or the generated sandbox-<short-id>).
reservation_id?|macOS only: the external id of the Mac lease whose slot admitted the sandbox — one of the organization's leases, or the one this create bought. Omitted for every other class.
status*stringInitial lifecycle status — pending, or the sandbox's current status on
an idempotent replay.
toolbox_proxy_url*stringThe sandbox's own region's toolbox proxy base URL, the same value
GET /sandboxes/{id} carries — exec/fs/preview traffic must target
this, not a global proxy.
vm_id*stringExternal sandbox id: base58-encoded UUID with a -<region> suffix
(e.g. 7fJk2mQpXv9dLc3RtY-use1); a bare UUID in single-region mode.
wait_cap*integerint640 <= valuecurl -X POST 'https://example.com/sandboxes/macos' \ -H 'Content-Type: application/json' \ -d '{ "image": "string"}'{ "access_token": "pa$$word", "access_token_expires_at": "2019-08-24T14:15:22Z", "create_ttl_expires_at": "2019-08-24T14:15:22Z", "image": null, "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f", "name": "string", "reservation_id": "string", "status": "string", "toolbox_proxy_url": "string", "vm_id": "string", "wait_cap": 0}Reads the central search index (OpenSearch), not this cell's database, so
one call spans the whole fleet. Filters compose with AND; comma lists
(status, class, region) match any member. Nothing is excluded
implicitly: deleted sandboxes are returned until retention removes the
row, exactly as GET /sandboxes behaves — narrow with status.
Consistency. The index is eventually consistent: a committed change is
searchable about 2–3 s later in steady state, longer during a cluster or
network incident (documents go stale; nothing is lost). Each item carries
updated_at so you can tell how stale a hit is. For read-your-writes use
GET /sandboxes and GET /sandboxes/{id}, which read the database. Results for a
region whose cell is still indexing (a newly enabled cell, or one that has
not heartbeated) may be incomplete: such regions are named in
partial_regions (and the x-daytona-search-partial response header)
rather than failing the request; results for the other regions are
complete.
Cursor. next_cursor (and each item's cursor) is opaque and bound to
the exact filter and sort that produced it: presenting it with a different
filter or sort is a 400 cursor does not match this query, never a silent
reset. limit may change between pages. Paging is best-effort under
concurrent mutation — a sandbox whose sort field changes between two page
fetches (status, name, mem_mib, updated_at, … are mutable) can
appear on both pages or on neither, and a sandbox created or deleted
mid-walk shifts later pages.
Errors. 501 SEARCH_NOT_CONFIGURED: search is not enabled on this
deployment — fall back to GET /sandboxes. 503 SEARCH_UNAVAILABLE: the search
cluster did not answer (transport, timeout, 5xx); retry later, or fall
back to GET /sandboxes. Both carry the code in the body's code field. A
400 is always the request's own fault — fix the parameter, do not retry.
AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: read:sandboxes
q?stringFree text over the sandbox name and image_ref. When the value is
an external sandbox id (tagged or bare UUID) it also matches that id
exactly.
name_prefix?stringname starts with this string (exact, case-sensitive).
id_prefix?stringThe id starts with this string — matched against both the
region-tagged external id and the bare UUID, so whichever id shape the
client saw works. The server-side form of the SDKs' startsWith on
id.
status?stringComma-separated lifecycle states (pending, assigned, building,
booting, running, pausing, paused, stopping, stopped,
deleting, deleted, failed, lost). Unknown => 400.
class?stringComma-separated sandbox classes: linux, windows, gpu, macos.
region?stringComma-separated region slugs. Default: every region.
image_ref?stringExact image reference.
image_ref_prefix?stringimage_ref starts with this string.
labels?stringLabel containment filter: a JSON-encoded object {"k":"v",...}; only
sandboxes whose labels contain every pair match. Same format as
GET /sandboxes?labels=. Malformed or non-object => 400.
persistent?booleanPersistent (warm-lifecycle) sandboxes only (true) or ephemeral only
(false).
spot?booleanSpot-tier sandboxes only (true) or on-demand only (false).
forked_from?stringSandboxes forked from this sandbox (external id).
min_vcpus?integerInclusive lower bound on vCPUs.
int64max_vcpus?integerInclusive upper bound on vCPUs.
int64min_mem_mib?integerInclusive lower bound on memory (MiB).
int64max_mem_mib?integerInclusive upper bound on memory (MiB).
int64min_scratch_mib?integerInclusive lower bound on scratch disk (MiB).
int64max_scratch_mib?integerInclusive upper bound on scratch disk (MiB).
int64created_after?stringCreated at or after this RFC 3339 instant.
created_before?stringCreated at or before this RFC 3339 instant.
updated_after?stringLast modified at or after this RFC 3339 instant.
updated_before?stringLast modified at or before this RFC 3339 instant.
last_active_after?stringLast activity at or after this RFC 3339 instant.
last_active_before?stringLast activity at or before this RFC 3339 instant.
sort?stringSort field: created_at (default), updated_at, last_activity_at
(sandboxes without activity sort last), name, vcpus, mem_mib,
scratch_mib. Ties break on the id.
order?stringasc or desc (default).
limit?integerPage size, clamped to [1, 200]; default 100.
int64cursor?stringOpaque continuation token from a previous page's next_cursor (or an
item's own cursor). Bound to the exact filter and sort of the
request that issued it: presenting it with a different filter or sort
is a 400. Not part of the token: limit.
Matching sandboxes in the project, sorted as requested, with total, next_cursor, and partial_regions. Header x-daytona-search-partial repeats partial_regions (comma-separated) when non-empty.
application/json- response
Response of GET /sandboxes/search (§4.2).
next_cursor?|Continuation token for the next page; null on the last page.
partial_regions*array<string>Regions whose cell has not yet reported the index the read alias points to as backfilled, or has never heartbeated: results for them may be incomplete. Empty in steady state. Filled in by the route (§6); the query itself does not know it.
total*integerMatching sandboxes. Exact while total_relation is eq; a lower
bound (the 10 000 tracking floor) when it is gte.
int640 <= valuetotal_relation*stringeq or gte.
vms*array<>curl -X GET 'https://example.com/sandboxes/search'{ "next_cursor": "string", "partial_regions": [ "string" ], "total": 0, "total_relation": "string", "vms": [ { "class": "string", "cpu": 0.1, "create_ttl_expires_at": "2019-08-24T14:15:22Z", "error": "string", "host_ip": "string", "id": "string", "image": null, "manifest_name": "string", "mem_max_mib": 0, "mem_mib": 0, "name": "string", "port_map": null, "region": "string", "runner_id": "string", "scratch_max_mib": 0, "scratch_mib": 0, "snapshot": null, "status": "string", "user": "string", "vcpus": 0, "vcpus_max": 0, "created_at": "2019-08-24T14:15:22Z", "cursor": "string", "forked_from": "string", "gpu_host_count": 0, "labels": null, "last_activity_at": "2019-08-24T14:15:22Z", "lifecycle": { "idle_timeout_at": "string", "idle_timeout_secs": 0, "last_activity_at": "string", "last_activity_source": "string", "on_idle_timeout": null, "on_timeout": null, "timeout_at": "string", "timeout_secs": 0, "wake_on_request": true }, "os_family": "string", "persistent": true, "spot": true, "spot_evicted_at": "2019-08-24T14:15:22Z", "started_at": "2019-08-24T14:15:22Z", "stopped_at": "2019-08-24T14:15:22Z", "toolbox_proxy_url": "string", "updated_at": "2019-08-24T14:15:22Z", "windows_image": "string" } ]}Create a Windows sandbox. Behind a feature flag: Windows sandboxes are experimental and available only to organizations with the windows_sandboxes feature flag enabled; other organizations get 403 FEATURE_FLAG_DISABLED.
AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
application/json- body
cpu?|doublecreate_ttl?|int64env?Sandbox-specific environment variables defined at create time. Names
must satisfy the shared guest-env rules: POSIX-ish identifiers, and
names in the platform's reserved namespaces (the daemon's own RLP
prefix followed by an underscore, and DAYTONA_ other than
DAYTONA_SANDBOX_TOKEN, DAYTONA_API_URL, DAYTONA_OTEL_ENDPOINT and
DAYTONA_DOCKER_START) fail the create with 400 naming the key.
idempotency_key?string|nullimage*stringlabels?lifecycle?null|mem_max_mib?|Per-sandbox memory limit in MiB; same semantics as vcpus_max.
int32mem_mib?|int32name?string|nullpersistent?booleanports?array<>region?string|nullscratch_max_mib?|Per-sandbox disk limit in MiB: the writable layer's size. Same semantics
as vcpus_max; a disk-snapshot restore requires it equal to the
captured disk, or absent.
int32scratch_mib?|int32secrets?array<string>spot?booleanvcpus?|int32vcpus_max?|Per-sandbox vCPU limit in whole vCPUs (PLAN-BURSTABLE-ONLY.md): the boot shape and the CPU ceiling. Absent => the system cap. Set equal to the request for a fixed shape.
int32wait?|int64Windows sandbox admitted (or an idempotent replay)
application/json- response
Response for POST /sandboxes — the fresh create, the idempotent replay, and the
snapshot-restore paths all share this shape. Field order is alphabetical to
keep the wire bytes identical to the former serde_json::json! construction.
access_token?|The sandbox's data-plane access token, returned ONCE at create time.
Null on an idempotent replay (the original create already returned
it). While the deployment's data-plane compat window is open (the
ship default) this is the non-expiring per-VM dtnv_… token; once
the deployment flips compat off it is a full-grant sandbox JWT whose
expiry rides in access_token_expires_at (PLAN-SANDBOX-TOKEN-JWT.md).
passwordaccess_token_expires_at?|Expiry of access_token (RFC 3339). Null while the compat window has
access_token carrying the non-expiring dtnv_ credential, and null
on an idempotent replay; set once the compat flip makes
access_token a sandbox JWT — mint a fresh token via
POST /sandboxes/{id}/access-token before it lapses.
date-timecreate_ttl_expires_at?|date-timeimage?null|job_id?|Create/restore job id. Null on an idempotent replay.
uuidname*stringSandbox name (caller-provided or the generated sandbox-<short-id>).
reservation_id?|macOS only: the external id of the Mac lease whose slot admitted the sandbox — one of the organization's leases, or the one this create bought. Omitted for every other class.
status*stringInitial lifecycle status — pending, or the sandbox's current status on
an idempotent replay.
toolbox_proxy_url*stringThe sandbox's own region's toolbox proxy base URL, the same value
GET /sandboxes/{id} carries — exec/fs/preview traffic must target
this, not a global proxy.
vm_id*stringExternal sandbox id: base58-encoded UUID with a -<region> suffix
(e.g. 7fJk2mQpXv9dLc3RtY-use1); a bare UUID in single-region mode.
wait_cap*integerint640 <= valuecurl -X POST 'https://example.com/sandboxes/windows' \ -H 'Content-Type: application/json' \ -d '{ "image": "string"}'{ "access_token": "pa$$word", "access_token_expires_at": "2019-08-24T14:15:22Z", "create_ttl_expires_at": "2019-08-24T14:15:22Z", "image": null, "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f", "name": "string", "reservation_id": "string", "status": "string", "toolbox_proxy_url": "string", "vm_id": "string", "wait_cap": 0}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: read:sandboxes
id*stringExternal sandbox id (base58 UUID with -<region> suffix; bare UUIDs accepted)
wait?stringIf set (e.g. running), block until the VM reaches this status (or a
terminal state) before responding. Absent = return immediately.
wait_exact?stringLike wait, but the target status must be reached exactly — a
terminal-bound state that is not the target does NOT satisfy it. Needed
for wait_exact=stopped: a VM is stopping the instant DELETE is acked,
and the loose wait= predicate treats stopping as satisfying any wait,
so wait=stopped returns immediately on the transient stopping row.
wait_exact=stopped blocks until the authoritative stopped event.
(PLAN-SUSTAINED-THROUGHPUT Item 3.) It is also the wait to use before a
start: a persistent sandbox with a volume stays stopping until its
volume execution settles, and only stopped means it can start again
(PLAN-VOLUME-STOP-READINESS). failed/lost still short-circuit so a
VM that will never reach the target does not hang until timeout.
timeout_ms?integerMax time to block, ms. Clamped to [0, 60000]. Default 30000.
int640 <= valueSandbox detail. With wait/wait_exact, returned once the predicate is met or the timeout elapses (whichever first)
application/json- response
Response shape for GET /sandboxes/{id}: the sandbox row plus the non-lifecycle
extras and per-region endpoints the handler merges in. Schema-only (the
handler assembles the JSON itself).
class*stringVM class (migration pre-deploy/20260820101429_vms_class, PLAN-VM-CLASS-SPLIT.md DP-2):
linux | windows | gpu | macos. Immutable per VM, derived at create
(vm_class), carried on the hot overlay, and serialized on the native
DTOs (list/detail/batch-wait). Unlike labels it has
NO #[sqlx(default)] — every VmRow SELECT must name it, so a missed
list fails loudly instead of silently reporting the wrong class.
cpu*numberdoublecreate_ttl_expires_at?|date-timeerror?string|nullhost_ip?string|nullid*stringInternal Uuid. Serialized as the region-tagged EXTERNAL id so all
API/DTO responses carry the routable id, while the field type stays
Uuid for the rest of the code (and back-compat: deployments without
region tagging still serialize the bare UUID string, byte-identical to
before).
image?null|manifest_name?string|nullmem_max_mib?|int32mem_mib*integerint32name*stringport_map*unknownregion*stringHome region slug (PLAN-REGIONS.md). Serialized as region.
runner_id?string|nullscratch_max_mib?|int32scratch_mib*integerint32snapshot?null|status*stringuser?|The sandbox's default OS user — the one its processes, entrypoint, SSH
sessions and git operations run as unless a request names another:
the create's user, or — when the create named
none — the USER of the image's config, recorded once the sandbox is
running. Omitted when the create named no user and none was recorded:
the sandbox then runs as root.
vcpus*integerint32vcpus_max?|Effective per-axis limits (PLAN-BURSTABLE.md), resolved at create: the
ceilings the sandbox boots at, at or above what it reserves in cpu /
mem_mib / scratch_mib. Option + #[sqlx(default)] so SELECTs that
omit the columns (e.g. the VmLite list overlay) still map — None then
simply omits them from the DTO.
int32forked_from?|External id of the fork source (PLAN-FORK.md), or null.
gpu_host_count*integerAbstract gpu_host GPU count (PLAN-GPU-BACKENDS.md §4a); >0 => GPU sandbox.
int32image_build_id?|The content-keyed image build this sandbox booted from
(PLAN-BUILD-DEDUPE.md), or null for any other image source. Two
sandboxes created from the SAME Dockerfile report the SAME id — that
is what says the second adopted the first's build instead of
rebuilding it. The regional proxy serves that build's log via
GET /sandboxes/{id}/build-logs-url discovery.
uuidimported_from?Where the sandbox was imported from (POST /migration/v1/sandboxes/{v1_id}/import, #3035): {platform: "v1", id: <v1 sandbox id>}; absent for a sandbox created on this platform.
labels*unknownSandbox labels (migration 0053): control-plane-only { "k": "v" }
metadata; {} when the sandbox has none.
lifecycle*Lifecycle policy + derived clock (PLAN-LIFECYCLE-TIMEOUTS.md): the
stored timeout/idle pairs plus timeout_at, last_activity_at and
last_activity_source. Declared here so the generated clients and the
published spec match what the handler actually returns.
mac_boot_mode?|macOS only: how the running guest came back from its last resume,
restored (from the saved memory) or cold_after_restore_failure (the
saved memory could not be restored and the Mac booted the disk). Null
when this incarnation was never resumed.
mac_checkpoint_state?|macOS only (PLAN-MACOS-LIFECYCLE.md): the sandbox's checkpoint state,
none | pending | committed | failed; null for every other class.
pending from the stop request until the checkpoint commits or fails:
start answers 409 checkpoint_pending meanwhile.
os_family?|Guest OS family (PLAN-CH-BACKEND.md phase 4): "windows" or null/"linux".
persistent*booleanPersistent write layer flag (PLAN-PERSISTENT-SANDBOXES.md) — gates the warm lifecycle actions (stop/start/pause/resume/fork).
spot*booleanSpot tier flag (PLAN-SPOT-INSTANCES.md).
spot_evicted_at?|When the platform reclaimed this spot sandbox; null if never.
date-timessh_gateway_host?|SSH gateway host for this sandbox's region (absent if unresolvable).
ssh_gateway_port?|SSH gateway port (default 2222; absent if the host is unresolvable).
int320 <= valuetoolbox_proxy_url*stringThe sandbox's own region's toolbox proxy base URL — exec/fs/preview traffic must target this, not a global proxy.
windows_image?|Golden Windows base-image name; null for Linux sandboxes.
curl -X GET 'https://example.com/sandboxes/string'{ "class": "string", "cpu": 0.1, "create_ttl_expires_at": "2019-08-24T14:15:22Z", "error": "string", "host_ip": "string", "id": "string", "image": null, "manifest_name": "string", "mem_max_mib": 0, "mem_mib": 0, "name": "string", "port_map": null, "region": "string", "runner_id": "string", "scratch_max_mib": 0, "scratch_mib": 0, "snapshot": null, "status": "string", "user": "string", "vcpus": 0, "vcpus_max": 0, "forked_from": "string", "gpu_host_count": 0, "image_build_id": "1e3d8f2d-6818-44ae-8d8a-cebebd30fb2f", "imported_from": { "id": "string", "platform": "string" }, "labels": null, "lifecycle": { "idle_timeout_at": "string", "idle_timeout_secs": 0, "last_activity_at": "string", "last_activity_source": "string", "on_idle_timeout": null, "on_timeout": null, "timeout_at": "string", "timeout_secs": 0, "wake_on_request": true }, "mac_boot_mode": "string", "mac_checkpoint_state": "string", "os_family": "string", "persistent": true, "spot": true, "spot_evicted_at": "2019-08-24T14:15:22Z", "ssh_gateway_host": "string", "ssh_gateway_port": 0, "toolbox_proxy_url": "string", "windows_image": "string"}Class-blind by design (unlike the other /sandboxes mutations): the in-guest
daemon's self-delete calls this URL for every class, and delete dispatches
per class internally. /sandboxes/windows/{id} and /sandboxes/gpu/{id} remain
equivalent class-scoped surfaces.
AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: delete:sandboxes
id*stringExternal sandbox id
Teardown initiated (status: deleting)
application/json- response
Response for the fire-and-forget lifecycle actions (delete/stop/pause): the
acted-on sandbox and the transitional status it was moved to. Field order is
alphabetical to keep the wire bytes identical to the former
serde_json::json! construction.
status*stringThe transitional status: deleting | stopping | pausing.
vm_id*stringExternal sandbox id.
curl -X DELETE 'https://example.com/sandboxes/string'{ "status": "string", "vm_id": "string"}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
id*stringExternal sandbox id (base58 UUID with -<region> suffix; bare UUIDs accepted)
application/json- body
Sandbox access token minted (stateless — nothing is stored; the token cannot be revoked before its expiry)
application/json- response
POST …/access-token response.
access_token*stringThe sandbox access token (RFC 9068 at+jwt, ES256,
aud: daytona:toolbox). Returned only here — never logged, never
stored, never on any other endpoint (secrets rule).
passwordexpires_at*stringAbsolute expiry (RFC 3339). The token cannot be refreshed — mint a fresh one through this route instead.
date-timeoperations*array<string>The granted operations, canonical order — echoes what the token's
scope claim carries.
ports?array<>|The granted ports (sorted, deduped), or null for all ports.
token_type*stringAlways Bearer.
curl -X POST 'https://example.com/sandboxes/string/access-token'{ "access_token": "pa$$word", "expires_at": "2019-08-24T14:15:22Z", "operations": [ "string" ], "ports": [ 0 ], "token_type": "string"}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: read:sandboxes
id*stringExternal sandbox ID
Absolute regional proxy URL
application/json- response
Absolute canonical regional proxy URL for once, text-follow and SSE reads.
url*stringcurl -X GET 'https://example.com/sandboxes/string/build-logs-url'{ "url": "string"}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: read:sandboxes
id*stringExternal sandbox id
Daemon entrypoint-session log (live for a running sandbox, the persisted copy otherwise)
response?stringtext/plaincurl -X GET 'https://example.com/sandboxes/string/entrypoint-logs'"string"AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
id*stringExternal sandbox id (base58 UUID with -<region> suffix; bare UUIDs accepted)
application/json- body
POST /vms/{id}/files/sign body (PLAN-SIGNED-FILE-URLS.md §1).
expires*integerAbsolute expiry, Unix seconds. Must lie in the future and at most the
deployment's signed-URL ceiling ahead (7 days by default); 0
(never) is refused — a pre-signed link always expires.
int64method*stringGET signs a download link (/files/download), POST an upload link
(/files/upload) — the two operations the proxy accepts a signature
for.
path*stringGuest path the link addresses, verbatim (the canonical and the URL's
path query parameter carry the same string).
The pre-signed URL and its parts
application/json- response
POST /vms/{id}/files/sign response: the link, plus its parts so a client
with its own toolbox base (a direct toolbox_url) can recompose it.
expires*integerThe expiry that was signed (Unix seconds).
int64method*stringGET or POST, as signed.
path*stringThe guest path, as signed.
signature*stringv1_ + base64url(HMAC-SHA256(signing key, canonical)), no padding.
url*stringThe full pre-signed URL against the sandbox region's toolbox proxy.
curl -X POST 'https://example.com/sandboxes/string/files/sign' \ -H 'Content-Type: application/json' \ -d '{ "expires": 0, "method": "string", "path": "string"}'{ "expires": 0, "method": "string", "path": "string", "signature": "string", "url": "string"}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
id*stringExternal sandbox id of the (running, paused or stopped persistent) source
Optional body; omit it entirely for a memory fork with the default name
application/json- body
Fork enqueued (a memory fork lands paused, a disk-only fork stopped; a fork of a running source is then started automatically)
application/json- response
Response for POST /sandboxes/{id}/fork. Field order is alphabetical to keep the
wire bytes identical to the former serde_json::json! construction.
forked_from*stringExternal id of the source sandbox.
status*stringAlways pending. A memory fork lands paused, a disk-only fork lands
stopped; a fork of a RUNNING source is then brought up automatically.
toolbox_proxy_url*stringThe fork's own region's toolbox proxy base URL (a fork lands in its
source's region), the same value GET /sandboxes/{id} carries.
vm_id*stringExternal id of the NEW fork.
curl -X POST 'https://example.com/sandboxes/string/fork'{ "forked_from": "string", "status": "string", "toolbox_proxy_url": "string", "vm_id": "string"}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
id*stringExternal sandbox id
application/json- body
Request body for PUT /sandboxes/{id}/labels: the full replacement label set.
labels?The new label set (REPLACES the current one; {} clears all labels).
{}Labels replaced
application/json- response
Response for PUT /sandboxes/{id}/labels.
labels*unknownThe stored label set.
vm_id*stringExternal sandbox id.
curl -X PUT 'https://example.com/sandboxes/string/labels' \ -H 'Content-Type: application/json' \ -d '{}'{ "labels": null, "vm_id": "string"}PROJECT-KEY ONLY, unlike delete/stop/pause: the wall-clock deadline is a
safety knob the sandbox itself must not be able to disable, so a per-VM
dtnv_ token has no route here (same reasoning that keeps start/resume off
the self-service plane).
A body that sets on_timeout or on_idle_timeout to delete — or
touches any field of a pair whose stored or resulting action is delete,
clearing and switching away included — additionally requires
delete:sandboxes: scheduling, re-anchoring, or disarming the destruction
of an existing sandbox delegates the delete capability (issue #651,
PLAN-LIFECYCLE-TIMEOUTS.md Decision 9).
AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
id*stringExternal sandbox id
application/json- body
The lifecycle object as it arrives on the wire — at create (nested under
lifecycle) and as the whole body of the per-class lifecycle PATCH.
deny_unknown_fields matches the create bodies' posture: a misspelled knob
— or an old SDK's stop_after_idle_secs — is a loud 400 naming the field,
never a silently ignored safety policy.
idle_timeout_secs?|Idle seconds after which on_idle_timeout fires. Opt-in: omitted =
disabled at create, unchanged at PATCH; -1 clears the stored pair.
A value below 60 is raised to 60 and stored raised; 0 is rejected.
int64-1 <= value <= 2147483647nullon_idle_timeout?|nullon_timeout?|nulltimeout_secs?|Wall-clock seconds after which on_timeout fires. Re-arms with the
full budget on every accepted transition to running (start, resume,
wake); a PATCH that supplies it re-anchors the deadline from now.
1..= the effective max (org max_timeout_secs, else the global
86400 default); -1/0 are rejected — the timeout cannot be
disabled. Omitted at create: the platform default (300 s) when the
default gate is on, no timeout otherwise.
int641 <= value <= 2147483647nullwake_on_request?|Resume a parked sandbox on inbound authenticated traffic. Linux persistent only.
nullLifecycle policy updated
application/json- response
Response for PATCH /sandboxes/{id}/lifecycle and
POST /sandboxes/{id}/reset-idle-timer (class-blind: one route for every
class) — one echo shape for every lifecycle mutation.
lifecycle*The stored policy after the update, plus the derived read-only facts.
vm_id*stringExternal sandbox id.
curl -X PATCH 'https://example.com/sandboxes/string/lifecycle' \ -H 'Content-Type: application/json' \ -d '{}'{ "lifecycle": { "idle_timeout_at": "string", "idle_timeout_secs": 0, "last_activity_at": "string", "last_activity_source": "string", "on_idle_timeout": null, "on_timeout": null, "timeout_at": "string", "timeout_secs": 0, "wake_on_request": true }, "vm_id": "string"}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: read:sandboxes
id*stringExternal sandbox id
Serial console log (live for a running sandbox, the persisted terminal log otherwise)
response?stringtext/plaincurl -X GET 'https://example.com/sandboxes/string/logs'"string"AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: read:sandboxes
id*stringExternal sandbox id
Desired vs applied network policy state
application/json- response
applied?null|applied_incarnation?string|nullapplied_revision?|int64desired?null|desired_revision*integerint64failure_reason?string|nullstate?string|nullcurl -X GET 'https://example.com/sandboxes/string/network-policy'{ "applied": null, "applied_incarnation": "string", "applied_revision": 0, "desired": null, "desired_revision": 0, "failure_reason": "string", "state": "string"}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
id*stringExternal sandbox id
Full replacement. Send a JSON object to set policy, or literal null to reset to open while preserving revision history. Empty body is invalid. With a non-null allow_domains, explicit block_all=false is rejected as network_policy_domains_require_block_all and an omitted/null block_all normalizes to true.
application/json- body
Desired policy stored with durable dispatch intent
application/json- response
applied?null|applied_incarnation?string|nullapplied_revision?|int64desired?null|desired_revision*integerint64failure_reason?string|nullstate?string|nullcurl -X PUT 'https://example.com/sandboxes/string/network-policy'{ "applied": null, "applied_incarnation": "string", "applied_revision": 0, "desired": null, "desired_revision": 0, "failure_reason": "string", "state": "string"}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
id*stringExternal sandbox id
Pause initiated (status: pausing)
application/json- response
Response for the fire-and-forget lifecycle actions (delete/stop/pause): the
acted-on sandbox and the transitional status it was moved to. Field order is
alphabetical to keep the wire bytes identical to the former
serde_json::json! construction.
status*stringThe transitional status: deleting | stopping | pausing.
vm_id*stringExternal sandbox id.
curl -X POST 'https://example.com/sandboxes/string/pause'{ "status": "string", "vm_id": "string"}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
id*stringExternal sandbox id
Idle timer reset (advance-only; the echoed lifecycle is the post-reset state, with idle_timeout_at re-anchored and timeout_at unchanged)
application/json- response
Response for PATCH /sandboxes/{id}/lifecycle and
POST /sandboxes/{id}/reset-idle-timer (class-blind: one route for every
class) — one echo shape for every lifecycle mutation.
lifecycle*The stored policy after the update, plus the derived read-only facts.
vm_id*stringExternal sandbox id.
curl -X POST 'https://example.com/sandboxes/string/reset-idle-timer'{ "lifecycle": { "idle_timeout_at": "string", "idle_timeout_secs": 0, "last_activity_at": "string", "last_activity_source": "string", "on_idle_timeout": null, "on_timeout": null, "timeout_at": "string", "timeout_secs": 0, "wake_on_request": true }, "vm_id": "string"}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
id*stringExternal sandbox id
Resume enqueued (status: assigned)
application/json- response
Response for the job-backed lifecycle actions (start/resume). Field order is
alphabetical to keep the wire bytes identical to the former
serde_json::json! construction.
job_id*stringThe enqueued start/resume job id.
uuidstatus*stringvm_id*stringExternal sandbox id.
curl -X POST 'https://example.com/sandboxes/string/resume'{ "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f", "status": "string", "vm_id": "string"}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
id*stringExternal sandbox id (base58 UUID with -<region> suffix; bare UUIDs accepted)
The signing key was rotated; outstanding links stop verifying within the proxies' key-cache TTL
application/json- response
POST /vms/{id}/signing-key/rotate answer: the rotation happened. The new
key is never returned (PLAN-SIGNED-FILE-URLS.md §3) — the next
POST …/files/sign signs with it.
rotated*booleanAlways true on success; the request fails otherwise.
curl -X POST 'https://example.com/sandboxes/string/signing-key/rotate'{ "rotated": true}AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
id*stringExternal sandbox id
Warm start enqueued
application/json- response
Response for the job-backed lifecycle actions (start/resume). Field order is
alphabetical to keep the wire bytes identical to the former
serde_json::json! construction.
job_id*stringThe enqueued start/resume job id.
uuidstatus*stringvm_id*stringExternal sandbox id.
curl -X POST 'https://example.com/sandboxes/string/start'{ "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f", "status": "string", "vm_id": "string"}Class-blind like DELETE (the daemon self-stop path is hardcoded to this URL): stop dispatches per class internally — a Windows row warm-stops via ACPI, a non-persistent row of any class 409s exactly as before the split.
AuthorizationBearer <token>Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).
Scope: write:sandboxes
id*stringExternal sandbox id
Warm stop initiated (status: stopping)
application/json- response
Response for the fire-and-forget lifecycle actions (delete/stop/pause): the
acted-on sandbox and the transitional status it was moved to. Field order is
alphabetical to keep the wire bytes identical to the former
serde_json::json! construction.
status*stringThe transitional status: deleting | stopping | pausing.
vm_id*stringExternal sandbox id.
curl -X POST 'https://example.com/sandboxes/string/stop'{ "status": "string", "vm_id": "string"}