Skip to content
sistemo.io beta

API reference

Private beta

Signups are invite-only. Request an invite. The SDKs are on PyPI and npm; you still need a dashboard API key to call this API.

The REST API is the actual product — the SDKs are thin wrappers over it. Use it directly from any language.

Base URL

https://api.sistemo.io

The SDKs default to this base URL; SISTEMO_BASE_URL overrides it.

Authentication

Send your API key as a Bearer token on every request:

curl https://api.sistemo.io/v1/machines \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx"

See Authentication for scopes (read vs full) and how to create keys.

Send a real User-Agent, or the WAF answers before we do

Cloud sits behind a WAF that refuses some default client user-agents — notably Python's stdlib Python-urllib/x.y. It never reaches the API, so you get a 403 that is not one of ours: content-type: text/plain, the body error code: 1010, and a cf-ray header. Our own 403 is JSON with a code.

Both SDKs already send one (sistemo-python/<version>, @sistemo/sdk), so this only affects hand-rolled clients. Name yours:

req = urllib.request.Request(url)
req.add_header("User-Agent", "my-app/1.0")   # anything specific to you

⚠ A generic UA is also worth avoiding for your own sake — it is what you would be throttled with if we ever rate-limit by client.

Conventions

  • JSON request and response bodies (Content-Type: application/json).
  • Timestamps are RFC 3339 / ISO 8601 UTC (2026-06-23T17:30:43Z).
  • IDs are UUIDs.
  • Errors use HTTP status codes + a JSON body { "detail": "...", "code": "..." }. See Errors.
  • Idempotency — pass an Idempotency-Key header on POST /v1/machines to safely retry creates.

Endpoints at a glance

Group Endpoints
Machines GET/POST /v1/machines, GET /v1/machines/{id}, POST …/stop, …/start, DELETE …
Exec POST/GET/DELETE /v1/machines/{id}/execs
Volumes GET/POST /v1/volumes, POST …/attach, …/detach, DELETE …
Snapshots POST/GET …/snapshots, GET /v1/snapshots, POST …/restore, DELETE …
Images GET /v1/images
Activity GET /v1/activity, GET /v1/machines/{id}/activity
Quotas GET /v1/quotas
Billing & usage GET /v1/billing/{balance,rates,usage,usage/by-resource,usage/series}
API keys GET/POST/DELETE /v1/api-keys (dashboard session only)

Rate limits

Mutating routes are rate-limited per account; exec has its own limit. On 429, back off and retry (see Errors).

Known limits

Stated up front so you can design around them rather than discover them:

Command duration Default 120 s, max 24 h. Enforced in the machine
Command output 32 MiB per stream, truncated if cut — files
File transfer No file API. Use exec, or let the sandbox fetch over the network
Streaming / reconnect sb.start() / GET …/execs/{id} — long-running

More in the FAQ.