Skip to content
LogoLogo

Sandboxes

Core CRUD and lookup for sandbox microVMs.

At a glance

  • Base URL: https://api.sb.createos.sh
  • Auth: X-Api-Key: <token> header. Get a token
  • Response envelope: JSend, {"status": "...", "data": ...}

Sandbox status lifecycle

A sandbox moves through these statuses:

StatusDescription
creatingSpawn in progress
runningActive; can exec and transfer files
pausingSnapshot in progress
pausedSnapshotted to storage; host freed
resumingRestoring from snapshot
forkingBundle copy in progress (source stays paused)
errorResume/fork exhausted retries; POST /resume to retry
destroyingDelete in progress
destroyedPermanently gone
failedTerminal failure

POST /v1/sandboxes

Create a new sandbox. Time to the first command depends on the image, available capacity, and host load.

Auth required: Yes

Request body

FieldTypeRequiredDescription
shapestringYesVM shape. See GET /v1/shapes for the catalog. Example: s-1vcpu-256mb
rootfsstringNoRootfs catalog name. Omit for host default. See GET /v1/rootfs. Disabled names are rejected with 400.
namestringNoUser-facing VM name, unique per user among non-terminal sandboxes. Auto-generated (<adjective>-<animal>) if omitted. Used as hostname and in-network DNS name.
disk_mibintegerNoDisk size in MiB. 0 = shape default (10 GiB).
ssh_pubkeysstring[]NoOpenSSH public keys for SSH access. Default CLI shell and tunnel commands use API-key authentication and do not require SSH keys.
envsobjectNoEnvironment variables exported into every exec. Keys must match ^[A-Za-z_][A-Za-z0-9_]*$. Up to 64 entries, 4 KiB per value, 64 KiB total. Values are never returned by GET, only key names.
ingress_enabledbooleanNoWhen true, sandbox is reachable at <ulid>-<port>.<domain>. Off by default.
networksobject[]NoPrivate networks to join at create time. Each entry: {"id": "<name|net-ulid>"}.
disksobject[]NoS3 disks to mount. Each entry: {"disk_id": "<name|id>", "mount_path": "/mnt/data", "sub_path": "optional/prefix"}. Disk must be pre-registered via POST /v1/disks.
egressstring[]NoOutbound allowlist. Each entry is host[:port], ip[:port], cidr[:port], or *. Omit / empty / ["*"] = allow all.
auto_pause_after_secondsintegerNoPause after this many seconds of inactivity (no exec, file transfer, or tunnel). Range: 60-86400. Null/omitted = never auto-pause.
host_idstringNoPin to a specific host. 503 if the host can't fit the VM.
regionstringNoPlacement region. Omit to use the receiving API's default region. Requests for another configured region are forwarded there. An unavailable region returns 503; an unreachable regional service returns 502.

Note: bandwidth_quota_bytes is not settable at create time. Each sandbox starts with a deployment-configured allowance; the software default is 5 GiB. Read /bandwidth for your sandbox's actual quota and use POST /v1/sandboxes/{id}/bandwidth/recharge to increase it once the sandbox is running.

Example request

curl -X POST https://api.sb.createos.sh/v1/sandboxes \
  -H "X-Api-Key: $CREATEOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "shape": "s-1vcpu-1gb",
    "rootfs": "devbox:1",
    "name": "my-sandbox",
    "ingress_enabled": true,
    "auto_pause_after_seconds": 600,
    "ssh_pubkeys": ["ssh-ed25519 AAAA..."],
    "envs": { "ANTHROPIC_API_KEY": "sk-ant-..." },
    "egress": ["pypi.org", "1.1.1.1:53"]
  }'

Example response

{
  "status": "success",
  "data": {
    "id": "sb-01K...",
    "name": "my-sandbox",
    "ip": "192.168.0.12",
    "shape": "s-1vcpu-1gb",
    "rootfs": "devbox:1",
    "vcpu": 1,
    "mem_mib": 1024,
    "disk_mib": 10240,
    "spawn_ms": 87.4,
    "egress": ["pypi.org", "1.1.1.1:53"],
    "bandwidth_quota_bytes": 5368709120
  }
}

Notable errors: 400 invalid body or disabled rootfs, 503 no host capacity.

GET /v1/sandboxes

List sandboxes owned by the caller (paginated).

Auth required: Yes

Query parameters

ParameterTypeDefaultDescription
limitinteger50Max results per page (maximum 500)
offsetinteger0Pagination offset
statusstringFilter by a sandbox lifecycle status, including paused, pausing, resuming, forking, and error. Omit to list all statuses.

Example request

curl "https://api.sb.createos.sh/v1/sandboxes?status=running&limit=10" \
  -H "X-Api-Key: $CREATEOS_API_KEY"

Example response

{
  "status": "success",
  "data": {
    "data": [
      {
        "id": "sb-01K...",
        "name": "my-sandbox",
        "status": "running",
        "ip": "192.168.0.12",
        "vcpu": 1,
        "mem_mib": 1024,
        "disk_mib": 10240,
        "shape": "s-1vcpu-1gb",
        "rootfs": "devbox:1",
        "region": "eu",
        "ingress_enabled": true,
        "auto_pause_after_seconds": 600,
        "created_at": "2026-06-17T08:00:00Z"
      }
    ],
    "pagination": {
      "total": 1,
      "limit": 10,
      "offset": 0,
      "count": 1
    }
  }
}

GET /v1/sandboxes/{id}

Get details for a single sandbox.

Auth required: Yes

Path parameters

ParameterDescription
idSandbox id (sb-<ulid>)

Example request

curl https://api.sb.createos.sh/v1/sandboxes/sb-01K... \
  -H "X-Api-Key: $CREATEOS_API_KEY"

Example response

{
  "status": "success",
  "data": {
    "id": "sb-01K...",
    "name": "my-sandbox",
    "status": "running",
    "ip": "192.168.0.12",
    "vcpu": 1,
    "mem_mib": 1024,
    "disk_mib": 10240,
    "shape": "s-1vcpu-1gb",
    "rootfs": "devbox:1",
    "region": "eu",
    "ingress_enabled": true,
    "bandwidth_ingress_bytes": 1048576,
    "auto_pause_after_seconds": 600,
    "envs": ["ANTHROPIC_API_KEY"],
    "ssh_pubkeys": ["ssh-ed25519 AAAA..."],
    "egress": ["pypi.org"],
    "created_at": "2026-06-17T08:00:00Z",
    "running_at": "2026-06-17T08:00:01Z"
  }
}

Notable errors: 404 sandbox not found.

envs returns only the key names; values are never exposed via the API.

Lifecycle fields such as paused_at, last_resumed_at, and forked_from are omitted when unset.

PATCH /v1/sandboxes/{id}

Partially update a sandbox. Only fields you include are changed.

Auth required: Yes

Path parameters

ParameterDescription
idSandbox id

Request body

FieldTypeRequiredDescription
ingress_enabledbooleanNoToggle public ingress on or off
auto_pause_after_secondsintegerNoNew idle-pause timeout. Range: 60-86400. Omit to leave unchanged.
disable_auto_pausebooleanNoSet true to turn off auto-pause entirely. Takes precedence over auto_pause_after_seconds when both are sent.

Example request

curl -X PATCH https://api.sb.createos.sh/v1/sandboxes/sb-01K... \
  -H "X-Api-Key: $CREATEOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ingress_enabled": false, "auto_pause_after_seconds": 1800}'

Example response

Returns the full updated SandboxView object (same shape as GET).

Notable errors: 400 invalid values, 404 not found.

DELETE /v1/sandboxes/{id}

Destroy a sandbox permanently.

Auth required: Yes

Path parameters

ParameterDescription
idSandbox id

Example request

curl -X DELETE https://api.sb.createos.sh/v1/sandboxes/sb-01K... \
  -H "X-Api-Key: $CREATEOS_API_KEY"

Example response

{
  "status": "success",
  "data": {
    "id": "sb-01K...",
    "status": "destroying"
  }
}

Idempotent: deleting an already-destroyed sandbox returns the same shape with status: "destroyed". A fresh delete returns "destroying" and completes within a few seconds.

Notable errors: 404 not found.

GET /v1/sandboxes/by-ip/{ip}

Look up a sandbox by its VM IP address.

Auth required: Yes

Path parameters

ParameterDescription
ipVM IP address (e.g. 192.168.0.12)

Example request

curl https://api.sb.createos.sh/v1/sandboxes/by-ip/192.168.0.12 \
  -H "X-Api-Key: $CREATEOS_API_KEY"

Example response

Returns a SandboxView object (same shape as GET /v1/sandboxes/{id}).

Notable errors: 404 no sandbox found with that IP.