Skip to content
LogoLogo

Pause, Resume & Fork

Snapshot a sandbox to free its host, restore it later, or clone it into a new independent identity.

At a glance

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

State preserved on pause

Pausing snapshots the full VM state to object storage:

  • Disk: filesystem contents
  • Memory: full RAM image (processes, open files, network connections)
  • CPU state: exact register values and execution context

Pause releases live compute while preserving the snapshot. Resume can use the same host or another compatible host. A cached snapshot can resume faster than one that must be fetched from storage; timing depends on snapshot size, cache state, and load. Applications should reconnect external network connections after resume.

POST /v1/sandboxes/{id}/pause

Pause a running sandbox, preserving disk and memory state.

Auth required: Yes

Path parameters

ParameterDescription
idSandbox id (must be running)

Returns 202 Accepted with the sandbox in pausing status. Poll GET /v1/sandboxes/{id} until status flips to paused. Completion time depends on snapshot size and storage performance. Calling pause on an already paused sandbox returns 409; check its status before retrying.

The response header X-Poll-After carries the suggested number of seconds to wait before the first poll.

Example request

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

Example response (202)

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

Notable errors: 409 sandbox is not running.

A sandbox can also pause itself from the inside with no API key, see Self-Signal.

POST /v1/sandboxes/{id}/resume

Resume a paused sandbox.

Auth required: Yes

Path parameters

ParameterDescription
idSandbox id (must be paused or error)

Returns 202 Accepted with the sandbox in resuming status. Poll GET /v1/sandboxes/{id} until status flips to running. The server retries on different hosts if the first attempt fails. If all retry attempts are exhausted the row goes to error. POST /resume again to try with a fresh budget.

Calling resume on an already running sandbox returns 409; check its status before retrying.

Resume checks your sandbox quota, excluding the sandbox being resumed from that count. Other non-terminal sandboxes, including paused ones, count toward the cap. If they fill the cap, resume returns 429. Destroy an unneeded sandbox to free a slot.

Example request

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

Example response (202)

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

Notable errors: 409 sandbox is not paused or in error, 429 sandbox quota reached, 402 insufficient credit, 503 no host with capacity.

POST /v1/sandboxes/{id}/fork

Clone a paused sandbox into a new, independent sandbox identity.

Auth required: Yes

Path parameters

ParameterDescription
idSource sandbox id, must be paused

Fork copies the snapshot into a new sandbox with:

  • Separate sandbox id and IP address
  • Separate bandwidth ledger
  • Separate placement (may land on a different host)

By default the new sandbox auto-resumes to running. Pass start_paused: true to keep it in paused.

Request body (optional)

FieldTypeRequiredDescription
start_pausedbooleanNoKeep the new sandbox paused after the bundle copy completes. Default false (auto-resumes to running).
ssh_pubkeysstring[]NoSSH public keys to authorize on the new sandbox.
egressstring[]NoOutbound allowlist for the new sandbox.
ingress_enabledbooleanNoEnable public ingress on the new sandbox.
envsobjectNoA nonempty map replaces the inherited environment map. Omit or send an empty map to inherit the source environment.

The child starts with the deployment's default bandwidth allowance. Supplying bandwidth_quota_bytes returns 400, including when its value is zero. Recharge after the child reaches running to increase its quota.

S3 disk attachments do not carry over. Fork has no disks request field: wait for the child to run, then attach the registered disks it needs.

Example request

curl -X POST https://api.sb.createos.sh/v1/sandboxes/sb-01K.../fork \
  -H "X-Api-Key: $CREATEOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"start_paused": true}'

Example response (202)

{
  "status": "success",
  "data": {
    "id": "sb-01KNEW...",
    "name": "brave-otter",
    "status": "forking",
    "shape": "s-1vcpu-1gb",
    "vcpu": 1,
    "mem_mib": 1024,
    "disk_mib": 10240,
    "forked_from": "sb-01K..."
  }
}

The response carries the new sandbox id under data. Use X-Poll-After to choose when to start polling that id. Wait for paused when start_paused is true, or running otherwise. The initial response does not include an allocated IP.

Notable errors: 400 unsupported bandwidth override, 409 source sandbox is not paused, 402 insufficient credit, 429 sandbox quota reached, 503 fork unavailable.

Polling pattern

All three lifecycle operations are asynchronous. Use this pattern to wait for completion:

ID="sb-01K..."
 
# Trigger the operation (e.g. resume)
curl -X POST "https://api.sb.createos.sh/v1/sandboxes/$ID/resume" \
  -H "X-Api-Key: $CREATEOS_API_KEY"
 
# Poll until running
while true; do
  STATUS=$(curl -s "https://api.sb.createos.sh/v1/sandboxes/$ID" \
    -H "X-Api-Key: $CREATEOS_API_KEY" | jq -r '.data.status')
  echo "status: $STATUS"
  [ "$STATUS" = "running" ] && break
  [ "$STATUS" = "error" ]   && { echo "resume failed"; exit 1; }
  sleep 2
done