Sign Up

Sandboxes

GET /events/{edge}

GET
/events/{edge}

Path Parameters

edge*string

Region tag of the sandboxes the socket will carry, or _. Routing only.

Response Body

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'
Empty
POST
/events/{edge}/ticket

Authorization

headerAuthorizationBearer <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

Path Parameters

edge*string

Region 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.

Response Body

A single-use ticket for one GET /events/{edge} upgrade

application/json
  1. response

POST /events/{edge}/ticket response.

expires_in_ms*integer

Milliseconds until the ticket expires unused.

Formatint64
Range0 <= value
subprotocol*string

The subprotocol to negotiate alongside the ticket.

ticket*string

Opaque, 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"}

GET /sandboxes

GET
/sandboxes

Authorization

headerAuthorizationBearer <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

Query Parameters

limit?integer

Page size (list mode). Clamped server-side; ignored with ids.

Formatint64
cursor?string

Opaque continuation token from a previous page's next_cursor (or a row's own cursor). Ignored with ids.

ids?string

Comma-separated external sandbox ids (max 200) — switches to batch-wait mode. Malformed/unowned ids are silently omitted from the result.

wait?string

Batch-wait mode: block until at least one id reaches this status (or a terminal state).

wait_exact?string

Like wait, but the status must be reached exactly (terminal-bound states other than the target do not satisfy it). Takes precedence.

timeout_ms?integer

Max time to block in batch-wait mode, ms. Clamped to [0, 60000]; default 30000.

Formatint64
Range0 <= value
labels?string

Label 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.

Response Body

Sandboxes in the project (keyset-paginated, newest first) — or, with ids=, a snapshot of the requested set after the optional wait

application/json
  1. 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|null
vms*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"    }  ]}
POST
/sandboxes

Authorization

headerAuthorizationBearer <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

Request Body

application/json
  1. 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?|
Formatdouble
cpu_arch?string|null
cpu_type?string|null
create_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.

Formatint64
env?

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|null
image?|

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.

Formatint32
mem_mib?|
Formatint32
name?string|null
network_policy?null|
persistent?boolean
ports?array<>
region?string|null
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.

Formatint32
scratch_mib?|
Formatint32
secrets?array<string>
spot?boolean
user?string|null
vcpus?|
Formatint32
vcpus_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.

Formatint32
volumes?array<>
wait?|

Server-hold seconds. Omitted => DAYTONA_CREATE_WAIT_MAX (3). 0 => respond immediately. <0 => 400.

Formatint64

Response Body

Sandbox admitted (status may be queued/pending/running depending on wait), or an idempotent replay of an earlier create

application/json
  1. 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).

Formatpassword
access_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.

Formatdate-time
create_ttl_expires_at?|
Formatdate-time
image?null|
job_id?|

Create/restore job id. Null on an idempotent replay.

Formatuuid
name*string

Sandbox 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*string

Initial lifecycle status — pending, or the sandbox's current status on an idempotent replay.

toolbox_proxy_url*string

The 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*string

External sandbox id: base58-encoded UUID with a -<region> suffix (e.g. 7fJk2mQpXv9dLc3RtY-use1); a bare UUID in single-region mode.

wait_cap*integer
Formatint64
Range0 <= value
curl -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}
POST
/sandboxes/from-snapshot

Authorization

headerAuthorizationBearer <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

Request Body

application/json
  1. 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?|
Formatint64
idempotency_key?string|null
labels?
lifecycle?null|
name?string|null
ports?array<>
region?string|null
snapshot*string

Snapshot name or snap_… id. Required.

wait?|
Formatint64

Response Body

Sandbox restore admitted (or an idempotent replay)

application/json
  1. 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).

Formatpassword
access_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.

Formatdate-time
create_ttl_expires_at?|
Formatdate-time
image?null|
job_id?|

Create/restore job id. Null on an idempotent replay.

Formatuuid
name*string

Sandbox 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*string

Initial lifecycle status — pending, or the sandbox's current status on an idempotent replay.

toolbox_proxy_url*string

The 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*string

External sandbox id: base58-encoded UUID with a -<region> suffix (e.g. 7fJk2mQpXv9dLc3RtY-use1); a bare UUID in single-region mode.

wait_cap*integer
Formatint64
Range0 <= value
curl -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}

POST /sandboxes/gpu

POST
/sandboxes/gpu

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.

Authorization

headerAuthorizationBearer <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

Request Body

application/json
  1. body
cpu?|
Formatdouble
create_ttl?|
Formatint64
env?

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?integer
Formatint32
Range0 <= value
idempotency_key?string|null
image*string
labels?
lifecycle?null|
mem_max_mib?|

Per-sandbox memory limit in MiB; same semantics as vcpus_max.

Formatint32
mem_mib?|
Formatint32
name?string|null
ports?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.

Formatint32
scratch_mib?|
Formatint32
secrets?array<string>
user?string|null
vcpus?|
Formatint32
vcpus_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.

Formatint32
wait?|
Formatint64

Response Body

GPU sandbox admitted (or an idempotent replay)

application/json
  1. 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).

Formatpassword
access_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.

Formatdate-time
create_ttl_expires_at?|
Formatdate-time
image?null|
job_id?|

Create/restore job id. Null on an idempotent replay.

Formatuuid
name*string

Sandbox 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*string

Initial lifecycle status — pending, or the sandbox's current status on an idempotent replay.

toolbox_proxy_url*string

The 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*string

External sandbox id: base58-encoded UUID with a -<region> suffix (e.g. 7fJk2mQpXv9dLc3RtY-use1); a bare UUID in single-region mode.

wait_cap*integer
Formatint64
Range0 <= value
curl -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}
POST
/sandboxes/gpu/from-snapshot

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.

Authorization

headerAuthorizationBearer <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

Request Body

application/json
  1. 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?|
Formatint64
idempotency_key?string|null
labels?
lifecycle?null|
name?string|null
ports?array<>
region?string|null
snapshot*string
wait?|
Formatint64

Response Body

GPU checkpoint restore admitted (or an idempotent replay)

application/json
  1. 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).

Formatpassword
access_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.

Formatdate-time
create_ttl_expires_at?|
Formatdate-time
image?null|
job_id?|

Create/restore job id. Null on an idempotent replay.

Formatuuid
name*string

Sandbox 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*string

Initial lifecycle status — pending, or the sandbox's current status on an idempotent replay.

toolbox_proxy_url*string

The 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*string

External sandbox id: base58-encoded UUID with a -<region> suffix (e.g. 7fJk2mQpXv9dLc3RtY-use1); a bare UUID in single-region mode.

wait_cap*integer
Formatint64
Range0 <= value
curl -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}
POST
/sandboxes/macos

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.

Authorization

headerAuthorizationBearer <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

Request Body

application/json
  1. 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.

Formatint64
env?

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*string

The 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?boolean

Keep 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.

Formatint64

Response Body

macOS sandbox create enqueued (or an idempotent replay); reservation_id names the admitting lease

application/json
  1. 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).

Formatpassword
access_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.

Formatdate-time
create_ttl_expires_at?|
Formatdate-time
image?null|
job_id?|

Create/restore job id. Null on an idempotent replay.

Formatuuid
name*string

Sandbox 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*string

Initial lifecycle status — pending, or the sandbox's current status on an idempotent replay.

toolbox_proxy_url*string

The 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*string

External sandbox id: base58-encoded UUID with a -<region> suffix (e.g. 7fJk2mQpXv9dLc3RtY-use1); a bare UUID in single-region mode.

wait_cap*integer
Formatint64
Range0 <= value
curl -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}
GET
/sandboxes/search

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.

Authorization

headerAuthorizationBearer <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

Query Parameters

q?string

Free 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?string

name starts with this string (exact, case-sensitive).

id_prefix?string

The 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?string

Comma-separated lifecycle states (pending, assigned, building, booting, running, pausing, paused, stopping, stopped, deleting, deleted, failed, lost). Unknown => 400.

class?string

Comma-separated sandbox classes: linux, windows, gpu, macos.

region?string

Comma-separated region slugs. Default: every region.

image_ref?string

Exact image reference.

image_ref_prefix?string

image_ref starts with this string.

labels?string

Label 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?boolean

Persistent (warm-lifecycle) sandboxes only (true) or ephemeral only (false).

spot?boolean

Spot-tier sandboxes only (true) or on-demand only (false).

forked_from?string

Sandboxes forked from this sandbox (external id).

min_vcpus?integer

Inclusive lower bound on vCPUs.

Formatint64
max_vcpus?integer

Inclusive upper bound on vCPUs.

Formatint64
min_mem_mib?integer

Inclusive lower bound on memory (MiB).

Formatint64
max_mem_mib?integer

Inclusive upper bound on memory (MiB).

Formatint64
min_scratch_mib?integer

Inclusive lower bound on scratch disk (MiB).

Formatint64
max_scratch_mib?integer

Inclusive upper bound on scratch disk (MiB).

Formatint64
created_after?string

Created at or after this RFC 3339 instant.

created_before?string

Created at or before this RFC 3339 instant.

updated_after?string

Last modified at or after this RFC 3339 instant.

updated_before?string

Last modified at or before this RFC 3339 instant.

last_active_after?string

Last activity at or after this RFC 3339 instant.

last_active_before?string

Last activity at or before this RFC 3339 instant.

sort?string

Sort 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?string

asc or desc (default).

limit?integer

Page size, clamped to [1, 200]; default 100.

Formatint64
cursor?string

Opaque 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.

Response Body

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
  1. 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*integer

Matching sandboxes. Exact while total_relation is eq; a lower bound (the 10 000 tracking floor) when it is gte.

Formatint64
Range0 <= value
total_relation*string

eq 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"    }  ]}

POST /sandboxes/windows

POST
/sandboxes/windows

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.

Authorization

headerAuthorizationBearer <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

Request Body

application/json
  1. body
cpu?|
Formatdouble
create_ttl?|
Formatint64
env?

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|null
image*string
labels?
lifecycle?null|
mem_max_mib?|

Per-sandbox memory limit in MiB; same semantics as vcpus_max.

Formatint32
mem_mib?|
Formatint32
name?string|null
persistent?boolean
ports?array<>
region?string|null
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.

Formatint32
scratch_mib?|
Formatint32
secrets?array<string>
spot?boolean
vcpus?|
Formatint32
vcpus_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.

Formatint32
wait?|
Formatint64

Response Body

Windows sandbox admitted (or an idempotent replay)

application/json
  1. 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).

Formatpassword
access_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.

Formatdate-time
create_ttl_expires_at?|
Formatdate-time
image?null|
job_id?|

Create/restore job id. Null on an idempotent replay.

Formatuuid
name*string

Sandbox 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*string

Initial lifecycle status — pending, or the sandbox's current status on an idempotent replay.

toolbox_proxy_url*string

The 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*string

External sandbox id: base58-encoded UUID with a -<region> suffix (e.g. 7fJk2mQpXv9dLc3RtY-use1); a bare UUID in single-region mode.

wait_cap*integer
Formatint64
Range0 <= value
curl -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}

GET /sandboxes/{id}

GET
/sandboxes/{id}

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id (base58 UUID with -<region> suffix; bare UUIDs accepted)

Query Parameters

wait?string

If set (e.g. running), block until the VM reaches this status (or a terminal state) before responding. Absent = return immediately.

wait_exact?string

Like 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?integer

Max time to block, ms. Clamped to [0, 60000]. Default 30000.

Formatint64
Range0 <= value

Response Body

Sandbox detail. With wait/wait_exact, returned once the predicate is met or the timeout elapses (whichever first)

application/json
  1. 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*string

VM 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*number
Formatdouble
create_ttl_expires_at?|
Formatdate-time
error?string|null
host_ip?string|null
id*string

Internal 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|null
mem_max_mib?|
Formatint32
mem_mib*integer
Formatint32
name*string
port_map*unknown
region*string

Home region slug (PLAN-REGIONS.md). Serialized as region.

runner_id?string|null
scratch_max_mib?|
Formatint32
scratch_mib*integer
Formatint32
snapshot?null|
status*string
user?|

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*integer
Formatint32
vcpus_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.

Formatint32
forked_from?|

External id of the fork source (PLAN-FORK.md), or null.

gpu_host_count*integer

Abstract gpu_host GPU count (PLAN-GPU-BACKENDS.md §4a); >0 => GPU sandbox.

Formatint32
image_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.

Formatuuid
imported_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*unknown

Sandbox 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*boolean

Persistent write layer flag (PLAN-PERSISTENT-SANDBOXES.md) — gates the warm lifecycle actions (stop/start/pause/resume/fork).

spot*boolean

Spot tier flag (PLAN-SPOT-INSTANCES.md).

spot_evicted_at?|

When the platform reclaimed this spot sandbox; null if never.

Formatdate-time
ssh_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).

Formatint32
Range0 <= value
toolbox_proxy_url*string

The 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"}
DELETE
/sandboxes/{id}

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.

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id

Response Body

Teardown initiated (status: deleting)

application/json
  1. 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*string

The transitional status: deleting | stopping | pausing.

vm_id*string

External sandbox id.

curl -X DELETE 'https://example.com/sandboxes/string'
{  "status": "string",  "vm_id": "string"}
POST
/sandboxes/{id}/access-token

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id (base58 UUID with -<region> suffix; bare UUIDs accepted)

Request Body

application/json
  1. body

Response Body

Sandbox access token minted (stateless — nothing is stored; the token cannot be revoked before its expiry)

application/json
  1. response

POST …/access-token response.

access_token*string

The 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).

Formatpassword
expires_at*string

Absolute expiry (RFC 3339). The token cannot be refreshed — mint a fresh one through this route instead.

Formatdate-time
operations*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*string

Always 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"}
GET
/sandboxes/{id}/build-logs-url

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox ID

Response Body

Absolute regional proxy URL

application/json
  1. response

Absolute canonical regional proxy URL for once, text-follow and SSE reads.

url*string
curl -X GET 'https://example.com/sandboxes/string/build-logs-url'
{  "url": "string"}
GET
/sandboxes/{id}/entrypoint-logs

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id

Response Body

Daemon entrypoint-session log (live for a running sandbox, the persisted copy otherwise)

response?stringtext/plain
curl -X GET 'https://example.com/sandboxes/string/entrypoint-logs'
"string"
POST
/sandboxes/{id}/files/sign

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id (base58 UUID with -<region> suffix; bare UUIDs accepted)

Request Body

application/json
  1. body

POST /vms/{id}/files/sign body (PLAN-SIGNED-FILE-URLS.md §1).

expires*integer

Absolute 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.

Formatint64
method*string

GET signs a download link (/files/download), POST an upload link (/files/upload) — the two operations the proxy accepts a signature for.

path*string

Guest path the link addresses, verbatim (the canonical and the URL's path query parameter carry the same string).

Response Body

The pre-signed URL and its parts

application/json
  1. 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*integer

The expiry that was signed (Unix seconds).

Formatint64
method*string

GET or POST, as signed.

path*string

The guest path, as signed.

signature*string

v1_ + base64url(HMAC-SHA256(signing key, canonical)), no padding.

url*string

The 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"}
POST
/sandboxes/{id}/fork

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id of the (running, paused or stopped persistent) source

Request Body

Optional body; omit it entirely for a memory fork with the default name

application/json
  1. body

Response 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
  1. 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*string

External id of the source sandbox.

status*string

Always 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*string

The 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*string

External 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"}
PUT
/sandboxes/{id}/labels

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id

Request Body

application/json
  1. 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).

Default{}

Response Body

Labels replaced

application/json
  1. response

Response for PUT /sandboxes/{id}/labels.

labels*unknown

The stored label set.

vm_id*string

External sandbox id.

curl -X PUT 'https://example.com/sandboxes/string/labels' \  -H 'Content-Type: application/json' \  -d '{}'
{  "labels": null,  "vm_id": "string"}
PATCH
/sandboxes/{id}/lifecycle

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).

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id

Request Body

application/json
  1. 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.

Formatint64
Range-1 <= value <= 2147483647
Defaultnull
on_idle_timeout?|
Defaultnull
on_timeout?|
Defaultnull
timeout_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.

Formatint64
Range1 <= value <= 2147483647
Defaultnull
wake_on_request?|

Resume a parked sandbox on inbound authenticated traffic. Linux persistent only.

Defaultnull

Response Body

Lifecycle policy updated

application/json
  1. 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*string

External 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"}
GET
/sandboxes/{id}/logs

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id

Response Body

Serial console log (live for a running sandbox, the persisted terminal log otherwise)

response?stringtext/plain
curl -X GET 'https://example.com/sandboxes/string/logs'
"string"
GET
/sandboxes/{id}/network-policy

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id

Response Body

Desired vs applied network policy state

application/json
  1. response
applied?null|
applied_incarnation?string|null
applied_revision?|
Formatint64
desired?null|
desired_revision*integer
Formatint64
failure_reason?string|null
state?string|null
curl -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"}
PUT
/sandboxes/{id}/network-policy

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id

Request Body

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
  1. body

Response Body

Desired policy stored with durable dispatch intent

application/json
  1. response
applied?null|
applied_incarnation?string|null
applied_revision?|
Formatint64
desired?null|
desired_revision*integer
Formatint64
failure_reason?string|null
state?string|null
curl -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"}
POST
/sandboxes/{id}/pause

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id

Response Body

Pause initiated (status: pausing)

application/json
  1. 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*string

The transitional status: deleting | stopping | pausing.

vm_id*string

External sandbox id.

curl -X POST 'https://example.com/sandboxes/string/pause'
{  "status": "string",  "vm_id": "string"}
POST
/sandboxes/{id}/reset-idle-timer

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id

Response Body

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
  1. 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*string

External 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"}
POST
/sandboxes/{id}/resume

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id

Response Body

Resume enqueued (status: assigned)

application/json
  1. 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*string

The enqueued start/resume job id.

Formatuuid
status*string
vm_id*string

External sandbox id.

curl -X POST 'https://example.com/sandboxes/string/resume'
{  "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",  "status": "string",  "vm_id": "string"}
POST
/sandboxes/{id}/signing-key/rotate

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id (base58 UUID with -<region> suffix; bare UUIDs accepted)

Response Body

The signing key was rotated; outstanding links stop verifying within the proxies' key-cache TTL

application/json
  1. 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*boolean

Always true on success; the request fails otherwise.

curl -X POST 'https://example.com/sandboxes/string/signing-key/rotate'
{  "rotated": true}
POST
/sandboxes/{id}/start

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id

Response Body

Warm start enqueued

application/json
  1. 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*string

The enqueued start/resume job id.

Formatuuid
status*string
vm_id*string

External sandbox id.

curl -X POST 'https://example.com/sandboxes/string/start'
{  "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",  "status": "string",  "vm_id": "string"}
POST
/sandboxes/{id}/stop

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.

Authorization

headerAuthorizationBearer <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

Path Parameters

id*string

External sandbox id

Response Body

Warm stop initiated (status: stopping)

application/json
  1. 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*string

The transitional status: deleting | stopping | pausing.

vm_id*string

External sandbox id.

curl -X POST 'https://example.com/sandboxes/string/stop'
{  "status": "string",  "vm_id": "string"}