Skip to main content

Authentication

Send requests to:
Use an API key from Console → API Keys in the Authorization header. Requests operate within the key’s organization. The following example expects the key in LITHOSBOX_TOKEN and lists that organization’s sandboxes:
Send JSON request bodies with Content-Type: application/json. Fields ending in _unix_ns use Unix nanoseconds; fields ending in _unix use Unix seconds. Time-range query parameters use RFC3339 timestamps.

Sandboxes

Create a sandbox

POST /vms returns 201 and a sandbox object. Send {} to use the default environment, or choose at most one source: Optional fields are cpus, memory_mb, runtime, disable_internet, allow_egress, writable_size_bytes, dataset or datasets, timeout_s, and vm_id. See Limits for valid values. Template and snapshot restores retain their source configuration. dataset names a read-only dataset granted to your organization and mounts it at /datasets/<name>. To attach several, send "datasets": ["a", "b"] instead: up to 10 distinct names, each mounted at /datasets/<name> in the order given. Send one of dataset or datasets, not both. Send them with image or with neither source; combining them with template or snapshot_id returns 400. Datasets are fixed at creation. See Datasets.
allow_egress is a list of destinations the sandbox may still reach, with all other outbound traffic blocked: hostnames, *. wildcards, and public IPv4 addresses or CIDRs, up to 256. A non-empty list implies disable_internet. A create from a snapshot without allow_egress keeps the snapshot’s list. See Outbound network policy. timeout_s is the sandbox’s lifetime in whole seconds: the sandbox is deleted that long after its creation, whatever its state, just as DELETE /vms/{id} would. Omit it for the platform default (no lifetime); 0 asks for none. Values from 0 to 3153600000 (100 years) are accepted; anything else, including a fraction or a string, returns 400. The lifetime is fixed at creation. See Set a lifetime. Provide a UUID in vm_id and reuse it when retrying the same create request. If you lose the response, check GET /vms/{id} before issuing a new create. The Python SDK supplies and reuses an ID automatically within each create call.

Find or delete sandboxes

The sandbox object includes these fields: Common states are creating, running, slept, archived, interrupted, deleting, and failed. Transitions may also report waking, archiving, or migrating. Use the state and error response to decide which action is available; see Lifecycle actions.

Run a command

POST /vms/{id}/exec accepts an argument list:
Use stdin_b64 for base64-encoded input, with at most 4 MiB of decoded data. For shell syntax, pass args such as ["sh", "-c", "pwd && ls"]. The response includes exit_code, stdout, stderr, stdout_truncated, and stderr_truncated. Check the exit code; a successful HTTP response does not mean the command succeeded. Foreground completion does not imply every child process has exited. See Run commands for background-job patterns.

Keep a shell session

Use the same session_id for commands that need shared working-directory and environment state:
Send another command with that ID to continue in the same shell. Close it by sending {"session_id": "my-shell", "close_session": true} to the same endpoint. Sessions have the same synchronous command deadline as ordinary execution.

Lifecycle actions

The HTTP routes for archive and unarchive are /stop and /start. An archived sandbox needs an explicit /start; commands do not unarchive it. A sleeping sandbox wakes on a command or file operation, whether it was slept by /sleep or by the idle policy. Reboot returns 409 for an archived sandbox; unarchive first. Restart your application’s servers after rebooting. See Recovery for interrupted or unavailable sandboxes.

Fork a sandbox

POST /vms/{id}/branch creates an independent copy and returns 201 with a sandbox object. You may supply a UUID in child_vm_id for retrying a single fork. To request several copies from the same point, send {"count": 4}. Counts from 2 to 16 return {"vms": [...]}. Copies count toward the organization’s sandbox limit. A fork inherits its parent’s datasets; sending dataset or datasets on a fork returns 400. A fork does not inherit its parent’s lifetime: send timeout_s with the fork to give each copy one, or omit it for the platform default. Forks include files and running processes. Fork between commands, and reconnect external services independently in each copy. See Save, restore, fork.

Outbound network policy

PUT /vms/{id}/egress replaces a sandbox’s outbound policy. The body is the whole policy; nothing is merged with the previous one: It returns 200 with disable_internet, allow_egress, and applied. applied is false for an archived sandbox, which takes the policy when it is unarchived. Connections the new policy no longer allows are closed. Repeating the same request is safe. URLs, ports, paths, IPv6, a bare *, and private or reserved ranges return 400 naming the entry. DNS in the sandbox answers only listed names. See Limit outbound network access.

Public endpoints

Use public_url to access an HTTP server listening on the specified sandbox port. Leave public_port unset or zero to use the assigned port. Anyone with the URL can reach the application, so add authentication where needed. An endpoint on an archived sandbox becomes usable after unarchive. The URL is preserved, but it may briefly return 404 during reconnection. Deleting the sandbox makes the endpoint unavailable. See Expose a web service.

Snapshots and exports

Save and manage snapshots

A snapshot object includes snapshot_id, vm_id, parent_snapshot_id, state, durable, image, data_bytes, and created_unix_ns. Poll the snapshot until durable is true before relying on it for recovery or exporting it. data_bytes is the snapshot’s size in real bytes: all of its data, excluding the base image and any dataset. It is 0 until the size has been measured, shortly after the snapshot becomes durable. Storage limits and usage count this size. The original sandbox keeps running unless you request leave_paused=true (the field keeps its historical name). That option leaves it sleeping until the next command or file access, which wakes it automatically. Restore by sending {"snapshot_id": "YOUR_SNAPSHOT_ID"} to POST /vms. Restoring creates a new sandbox; deleting the original does not delete its snapshots.

Export a snapshot

An export moves from pending to ready or failed. When ready, files contains links for memory.img.zst and disk.img.zst compressed with Zstandard, plus state.json and manifest.json metadata. Each file entry includes its name, size, checksum, and download URL. expires_unix gives the export’s expiry time in Unix seconds; download the files before the links expire. Exports are for downloading and inspecting saved data. The API does not import an export to restore a sandbox; use the original snapshot ID for restoration. Deleting the source snapshot does not revoke a completed export. Delete the export separately if you want to remove its files before expiry.

Templates

POST /templates creates a reusable environment. name and image are required; version, cpus, memory_mb, runtime, and disable_internet are optional. A template has no egress allowlist: a non-empty allow_egress returns 400. Send allow_egress with each POST /vms that uses the template, or set it later with PUT /vms/{id}/egress.
Template fields include template_id, name, version, source_image, status, status_detail, runtime, base_snapshot_id, created_unix_ns, and last_used_unix_ns. Wait for status="ready" before creating from the template. If it becomes failed, read status_detail for the reason. The list can include read-only shared templates marked shared=true. You can also look up a shared template ID returned in an image-preparation error. A later create using the same image can retry preparation if a shared template failed.

Registries

POST /registries stores credentials for a registry and returns 204. For a username and token or password, use:
For an ECR role, use host, kind="ecr-assume-role", role_arn, and external_id. These credentials apply to your organization’s image pulls. See Private registries for an SDK example that reads credentials from environment variables.

Activity and metrics

Recent samples contain at_unix, interval_s, cpu_ms, mem_mb, rx_bytes, tx_bytes, and state. They cover approximately two hours at 30-second intervals. History uses minute intervals and accepts hours from 1 to 360, or start and end as RFC3339 timestamps, up to 15 days back. A point with measured=false represents a missing measurement. Events and historical metrics can be queried after sandbox deletion within their retention periods. Live logs are unavailable for archived sandboxes; reading logs from a sleeping sandbox does not wake it.

Usage

GET /usage?start=<RFC3339>&end=<RFC3339> returns organization usage, defaulting to the last 24 hours. A query window can cover up to 32 days. The response contains start, end, a states array, and storage totals. An empty states array means no usage was recorded for the window. Each states entry names a state and sums that state’s usage: Storage totals are byte-seconds, measured in the real size of your data. Divide one by the window length in seconds for the average size held: Real bytes are the only storage size. snapshot_byte_seconds and stored_byte_seconds are deprecated and scheduled for removal; do not build on them. Usage is reported in minute intervals, so short runs and state changes may be grouped within an interval. Deleted snapshots and exports stop accumulating usage. Add key=<API key ID> to /usage, /usage/series, /rated-usage, or /audit to narrow the result to one API key: usage of the sandboxes that key created, or the records of requests it made. Send key= with an empty value for activity no API key carried, such as the console. Omit key for the whole organization. Storage is never attributed to a key. GET /usage/series?hours= or start=&end= returns a time series for activity charts.

Rated usage

GET /rated-usage?start=<RFC3339>&end=<RFC3339> returns your usage priced by hour. It covers closed hourly periods whose start falls in the window, defaulting to the last 24 hours, up to 32 days. The response contains start, end, rows, rate_cards, totals, and closed_through_unix_ns, the end of the last closed hour. totals sums every returned row, corrections included. Each rate_cards entry gives a card’s version, effective_from_unix_ns, storage_model, and its rates; disk_nanos_per_gb_month prices disk above disk_free_bytes per sandbox, and reserved_cpu_nanos_per_vcpu_hour and reserved_memory_nanos_per_gib_hour are null on a card that prices no reservations. reservations lists your reservations active in the window: id, vcpus, memory_mb, starts_at_unix, and ends_at_unix (0 while open-ended). A reservation is billed every hour it is active and doesn’t reserve placement capacity. total_nanos is what your credit balance is charged for the row. GET /rated-usage/keys accepts the same window and returns totals plus a keys array of {"key_id", "totals"}, one per API key that created sandboxes. The keys’ totals sum exactly to totals. Storage and reservations appear under the empty key_id, which also holds usage that no API key carried.

Account

Audit

GET /audit?limit=200&before= returns {"records": [...], "next_before": ...}. Records include id, key_id, action, resource, outcome, request_id, and at, newest first. Use next_before as the next request’s before value to continue through older records.

Status codes

Common 409 messages include sandbox is archived (sandbox is stopped) (unarchive first), sandbox is busy (a sleep was refused because running work keeps the sandbox awake), a template that is not ready, or a snapshot with an export in progress. A checkpoint attempt on an unresponsive sandbox can also return 409 with sandbox agent unreachable. Match errors on the SDK’s typed exceptions — SandboxArchivedError for the archived refusal — rather than on message text. Message wording can change; the state names reported by the API do not. If you must inspect the text, match archived. Follow Retry-After for rate-limited requests. x-ratelimit-* headers are advisory and describe the budget observed by that response. DELETE requests are exempt from rate limits. See Request rates.