Skip to main content

StacyVM REST API Reference

This document is the source of truth for the StacyVM HTTP API. The Python and TypeScript SDKs are thin wrappers over these endpoints — anything they do, you can do with curl.
  • Base URL: http://localhost:7423/api/v1
  • Content type: application/json (request and response, except where noted)
  • OpenAPI spec: swagger.yaml / swagger.json

Table of contents


Authentication

Optional headers:
CORS is permissive by default for local development (server.cors_allowed_origins: ["*"]). Public deployments should set exact origins, for example:
stacyvm config lint --production fails when CORS is left wildcard or empty. X-User-ID is trimmed when present. It must be 128 characters or fewer and cannot contain whitespace, control characters, or path separators.

Rate limiting

API rate limiting is optional and disabled by default. When rate_limit.enabled is true, StacyVM applies an in-memory token bucket to API routes.
The default owner mode uses X-User-ID when present, then falls back to X-API-Key, then client IP. Limited requests return 429 Too Many Requests with Retry-After, X-RateLimit-Limit, and X-RateLimit-Remaining headers. Rate-limit buckets store hashed identity keys internally; raw owner IDs, API keys, and IP addresses are not exposed in diagnostics or metrics.

Conventions

  • IDs. Sandbox IDs look like sb-a1b2c3d4. Templates are addressed by name.
  • Durations. All ttl and timeout fields use Go duration strings: 30s, 5m, 1h30m.
  • Timestamps. ISO 8601 UTC, e.g. 2026-05-04T10:30:00Z.
  • File modes. Octal strings, e.g. "755", "644".
  • Streaming. POST /sandboxes/{id}/exec switches to NDJSON (application/x-ndjson) when stream: true.

Errors

Errors return a JSON body with HTTP status reflecting the failure class:

Admin API

StacyVM supports an optional separate admin API key:
Use X-Admin-API-Key for admin requests. X-API-Key is still accepted when it matches the admin key. If auth.admin_api_key is empty, admin routes fall back to auth.api_key for backwards compatibility unless auth.admin_fallback_enabled is set to false. For dashboard setup, quota workflows, diagnostics, audit history, CSV export, and storage notes, see admin-control-plane. Admin route aliases: The existing non-admin paths remain available for compatibility in this phase.

Sandboxes

Spawn a sandbox

Request body (all fields optional, server defaults apply):
Response 201 Created:

Evaluate spawn admission

Preflight a spawn request against current quota and scheduler limits without creating a sandbox. X-User-ID overrides owner_id, matching the spawn endpoint. Request body: same shape as POST /api/v1/sandboxes. Response 200 OK:
queueable reflects the configured spawn overflow mode. Capacity denials are queueable only when defaults.spawn_overflow is queue; TTL denials are never queueable.

List sandboxes

Response 200 OK: array of sandbox objects.

Get a sandbox

Response 200 OK or 404 Not Found.

Destroy a sandbox

Response 200 OK:

Prune expired sandboxes

Response 200 OK:

Extend TTL

Request body:
Response 200 OK: full sandbox object with updated expires_at.

Execute a command

Request body:
Response 200 OK (non-streaming):
Response 200 OK (streaming, stream: true): application/x-ndjson — one JSON object per line:

Console logs

lines defaults to 100. Response 200 OK:

Files

All file paths are absolute inside the sandbox. The endpoints below are scoped under /sandboxes/{id}/files.

Write a file

Response 200 OK: { "status": "written" }.

Read a file

Response 200 OK: raw file contents (binary safe). The SDKs decode as UTF-8.

Delete a file or directory

recursive defaults to false. Response 200 OK: { "status": "deleted" }.

List a directory

path defaults to /. Response 200 OK:

Move / rename

Response 200 OK: { "status": "moved" }.

Change permissions

Response 200 OK: { "status": "chmod applied" }.

Stat

Response 200 OK: a single FileInfo object (same shape as list).

Glob

Response 200 OK:

Templates

Create a template

Response 201 Created: the template object. 409 Conflict if name is taken.

List templates

Response 200 OK: array of templates.

Get a template

Response 200 OK or 404 Not Found.

Update a template

Same body as create (without name). Response 200 OK or 404.

Delete a template

Response 200 OK: { "status": "deleted" }.

Spawn from a template

Optional override body:
Response 201 Created: full sandbox object.

Quotas

Owner quotas are persisted overrides for per-owner sandbox and runtime limits. They apply when requests include an owner via X-User-ID or owner_id. Owner IDs are trimmed and must be 128 characters or fewer. They cannot contain whitespace, control characters, or path separators. Quota durations must use whole-second Go duration strings; use 0s or omit a duration to inherit the global default.

List owner quotas

Response 200 OK:

Get quota summary

Returns redacted policy coverage counts without exposing owner IDs. Response 200 OK:

Save owner quota

Request:
Response 200 OK: full owner quota object. Invalid owner IDs, negative sandbox counts, malformed durations, sub-second durations, and fractional-second durations return 400 Bad Request.

Get owner usage

Response 200 OK:

Delete owner quota

Response 200 OK: { "status": "deleted" }.

Providers

List providers

Response 200 OK:

Get a provider

Response 200 OK:

Health-check all providers

Response 200 OK:

Workers

Worker registry endpoints expose the control-plane view of StacyVM workers. In single-node mode the API server registers itself as the local worker at startup. Remote workers heartbeat through /api/v1/worker/* using worker credentials. Admins can still manage registry records under /api/v1/admin/workers/*.

List workers

Response 200 OK:

Get a worker

Response 200 OK: one worker object.

Heartbeat a worker

Required headers:
Request:
Response 200 OK: updated worker object. Admin heartbeat aliases remain available at /api/v1/admin/workers/{workerID}/heartbeat for controlled registry repair and test setup.

Renew a worker lease

Required headers:
auth.worker_token is the shared staging token. For production-aligned worker identity, configure auth.worker_signing_key for short-lived signed worker tokens or auth.worker_tokens.<workerID> for individually rotatable static credentials during migration. Request:
Response 200 OK:

Delete a worker

Response 200 OK:

Snapshots

List Firecracker snapshots

Response 200 OK: array of snapshot summaries (image name, kernel, size, created_at).

Pool

Pool status

Response 200 OK (pool enabled):
Response 200 OK (pool disabled):

System

Health

Response 200 OK:

Liveness

Response 200 OK:
Use this endpoint for process liveness checks. It only confirms that the API process is responding.

Readiness

Response 200 OK:
Response 503 Service Unavailable when no configured provider is healthy.

Diagnostics

Response 200 OK:
Diagnostics are read-only and intentionally redacted. Use this endpoint for support bundles, incident debugging, and deployment sanity checks. The remediation object points operators to the first public document to use when a diagnostics area needs follow-up.

Metrics

Response 200 OK:

Prometheus metrics

Response 200 OK:
Use this endpoint for Prometheus-compatible scraping of runtime, provider, worker, sandbox, event, and operation metrics.

Events stream

Response 200 OK with Content-Type: text/event-stream. The server emits orchestrator events as Server-Sent Events:
Common event types include:
  • sandbox.created, sandbox.running, sandbox.destroyed, sandbox.error
  • exec.started, exec.completed, exec.failed, exec.timeout
  • file.written, file.read
  • operation.failed, resource.limit, provider.failed, reconcile.action
  • spawn.queued, spawn.dequeued, spawn.queue_timeout
  • quota.saved, quota.deleted
Use any SSE client (EventSource in browsers, httpx-sse in Python, etc.) to consume.

WebSocket exec

Upgrades the connection to a WebSocket for interactive command execution. Useful for terminals, REPLs, and any case where you need bi-directional I/O. Client → server messages:
Server → client messages:
The web dashboard uses this endpoint to power its live terminal — a concrete reference is at web/src/.

SDK mapping

If you’d rather write Python or TypeScript than curl, every endpoint above maps 1:1 to an SDK method: Full SDK docs: Python · TypeScript.