CrowNest
API reference

Sandboxes

Create, list, inspect, set TTLs for, and kill sandboxes — isolated live execution environments.

A sandbox is an isolated live execution environment. You create one from a template, run commands and work with files inside it, and it's destroyed when its TTL expires or when you kill it.

The Sandbox object

FieldTypeDescription
idstringSandbox ID, prefixed sbx_
orgIdstringOwning organization, prefixed org_
projectIdstringOwning project, prefixed prj_
statusstringcreating, starting, ready, running, idle, expiring, destroyed, or failed
templateIdstringTemplate ID, prefixed tpl_
templateSlugstringTemplate slug, such as python-node
templateVersionstringResolved template version
templateVersionIdstringTemplateVersion ID, prefixed tplv_
ttlMsintegerRequested lifetime in milliseconds
expiresAtstringISO 8601 timestamp when the sandbox expires
metadataobjectString labels set at creation
networkPolicyobjectNormalized create-time outbound access policy
createdAtstringISO 8601 creation timestamp, when available
destroyedAtstringISO 8601 destruction timestamp, once destroyed
destroyedReasonstringidle_expired, platform_cleanup, ttl_expired, or user_killed

Create a sandbox

POST /v1/sandboxes — requires scope sandbox:create. Accepts an Idempotency-Key header.

Creates a sandbox from a template and returns it once provisioning starts. All body fields are optional:

FieldTypeRequiredDefaultConstraints
projectIdstringNoDefault projectA prj_ ID your key can access
templatestringNopython-nodepython-node or node; discover the current catalogue through Templates
templateVersionIdstringNoA tplv_ ID; pins an exact immutable environment
ttlMsintegerNo3600000Positive integer, max 3600000 (1 hour). Use the TTL endpoint later.
metadataobjectNoString map; max 16 keys, keys ≤ 64 chars, values ≤ 512 chars, ≤ 4 KB total
networkPolicyobjectNounrestrictedCreate-time outbound mode and, for list modes, up to 64 reviewed hosts
Terminal
curl -X POST https://api.crownest.dev/v1/sandboxes \
  -H "Authorization: Bearer $CROWNEST_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7f3d9c2a-create-01" \
  -d '{
    "template": "python-node",
    "ttlMs": 1800000,
    "metadata": { "run": "nightly-eval" }
  }'

Returns 201 with the created sandbox:

{
  "sandbox": {
    "id": "sbx_abc123",
    "orgId": "org_abc123",
    "projectId": "prj_abc123",
    "status": "creating",
    "templateId": "tpl_abc123",
    "templateSlug": "python-node",
    "templateVersion": "2026-06-17",
    "templateVersionId": "tplv_python_node_2026_06_17",
    "ttlMs": 1800000,
    "expiresAt": "2026-06-11T13:30:00.000Z",
    "metadata": { "run": "nightly-eval" },
    "networkPolicy": { "mode": "deny-all" },
    "createdAt": "2026-06-11T13:00:00.000Z"
  }
}

Control outbound access

networkPolicy is immutable for the lifetime of a Sandbox. Use one of these provider-neutral forms:

{ "mode": "unrestricted" }
{ "mode": "deny-all" }
{ "mode": "allowlist", "hosts": ["api.example.com", "*.example.org"] }
{ "mode": "denylist", "hosts": ["telemetry.example.com"] }

deny-all blocks internet traffic except Cloudflare's documented container DNS path. An allowlist denies internet by default and permits matching HTTP or HTTPS request hosts. A denylist keeps default internet access but blocks matching HTTP or HTTPS request hosts. Redirect destinations are checked again.

Hosts are lowercase ASCII names, exact IPv4 literals, or a leftmost *. suffix pattern. The suffix matches nested subdomains but not the apex. URLs, ports, CIDR ranges, IPv6 literals, Unicode names, and other glob forms are rejected. This surface doesn't claim post-resolution CIDR filtering or universal DNS-rebinding protection.

Restrictive configuration completes before the Sandbox becomes ready. If the runtime can't install it, creation fails instead of returning an unrestricted Sandbox. HTTPS interception uses the curated image's trust configuration; certificate-pinned or private-trust-store clients can fail.

Terminal
crownest sandboxes create \
  --network-policy allowlist \
  --network-hosts api.example.com,github.com

Errors: invalid_request, forbidden, not_found, quota_exceeded, sandbox_ttl_exceeded.

List sandboxes

GET /v1/sandboxes — requires scope sandbox:read.

Returns a list of live sandboxes, newest first, in the standard { data, hasMore } envelope. Destroyed and failed sandboxes are excluded unless you ask for them:

ParameterTypeDescription
projectIdstringFilter to one project
statusstringFilter by sandbox status
includestringhistorical to include destroyed and failed sandboxes
metadata.<key>stringFilter by an exact metadata label, for example metadata.run=nightly-eval
Terminal
curl "https://api.crownest.dev/v1/sandboxes?include=historical" \
  -H "Authorization: Bearer $CROWNEST_API_KEY"
{
  "data": [
    {
      "id": "sbx_abc123",
      "status": "ready",
      "templateSlug": "python-node",
      "expiresAt": "2026-06-11T13:30:00.000Z"
    }
  ],
  "hasMore": false
}

Get a sandbox

GET /v1/sandboxes/{sandboxId} — requires scope sandbox:read.

Returns one sandbox by ID. Poll this endpoint to watch status move from creating to ready.

Terminal
curl https://api.crownest.dev/v1/sandboxes/sbx_abc123 \
  -H "Authorization: Bearer $CROWNEST_API_KEY"

Returns 200 with { "sandbox": { ... } }. Errors: forbidden, not_found.

Set a sandbox TTL

POST /v1/sandboxes/{sandboxId}/ttl — requires scope sandbox:extend. Requires an Idempotency-Key header.

This endpoint resets a live sandbox's TTL countdown from the time of the request. The requested ttlMs must move expiresAt later than its current value. A sandbox's total session is capped at 24 hours from creation.

FieldTypeRequiredDescription
ttlMsintegerYesNew lifetime in milliseconds. Max 86400000 (24 hours), counted from creation.
Terminal
curl -X POST https://api.crownest.dev/v1/sandboxes/sbx_abc123/ttl \
  -H "Authorization: Bearer $CROWNEST_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7f3d9c2a-extend-01" \
  -d '{ "ttlMs": 3600000 }'

Returns 200 with { "sandbox": { ... } }, including the refreshed expiresAt.

Errors: invalid_request, forbidden, not_found, sandbox_destroyed, sandbox_ttl_exceeded.

Deprecated alias

POST /v1/sandboxes/{sandboxId}/extend remains available until July 10, 2027. Its responses include Deprecation, Sunset, and Link headers that identify POST /v1/sandboxes/{sandboxId}/ttl as the canonical endpoint.

Kill a sandbox

DELETE /v1/sandboxes/{sandboxId} — requires scope sandbox:kill.

Destroys the sandbox immediately. The workspace filesystem is lost; only artifacts you exported survive. The operation is idempotent by state — deleting an already-destroyed sandbox returns the destroyed record rather than an error.

Terminal
curl -X DELETE https://api.crownest.dev/v1/sandboxes/sbx_abc123 \
  -H "Authorization: Bearer $CROWNEST_API_KEY"
{
  "sandbox": {
    "id": "sbx_abc123",
    "status": "destroyed",
    "destroyedAt": "2026-06-11T13:05:00.000Z",
    "destroyedReason": "user_killed"
  }
}

Errors: forbidden, not_found.

Next steps

  • Run processes in Commands, or interpreter snippets in Code.
  • Move data in and out in Files.
  • Keep outputs after destruction in Artifacts.

On this page