Skip to content

HTTP API reference

Last reviewed: 4 days ago

This page documents every route exposed by the sandbox bridge.

Authentication

All routes under /v1/sandbox/* and /v1/openapi.* require a Bearer token:

Authorization: Bearer <SANDBOX_API_KEY>

When SANDBOX_API_KEY is not configured, authentication is skipped for local development convenience. Always set the secret before deploying to production.

OpenAPI schema

The bridge serves its own API documentation:

MethodRouteDescription
GET/v1/openapi.jsonMachine-readable OpenAPI 3.1 schema.
GET/v1/openapiInteractive HTML documentation.

Both routes accept authentication via Bearer header or ?token= query parameter.

When running locally with npm run dev, open http://localhost:8787/v1/openapi in your browser to explore every endpoint interactively.

Sandbox lifecycle

MethodRouteDescription
POST/v1/sandboxCreate a new sandbox. Returns {"id": "<sandbox-id>"}.
DELETE/v1/sandbox/:idDestroy the sandbox container. Returns 204.
GET/v1/sandbox/:id/runningCheck container liveness. Returns {"running": true|false}.

Command execution

MethodRouteDescription
POST/v1/sandbox/:id/execRun a command. Response is an SSE stream (see below).

The /exec endpoint accepts a JSON body:

{
"argv": ["sh", "-lc", "echo hello"],
"timeout_ms": 10000,
"cwd": "/workspace"
}

Argv escaping

Each element of the argv array is escaped using ANSI-C $'...' quoting before being joined into a shell command. Tokens that contain only safe characters (A-Za-z0-9@%+=:,./-) are passed through unchanged. All other tokens are wrapped in $'...' with backslashes, single quotes, newlines, carriage returns, and tabs escaped. This prevents shell injection while preserving arguments that contain spaces, quotes, or special characters.

SSE response format

The response is a text/event-stream with the following event types:

EventDataDescription
stdoutBase64-encoded chunkStandard output from the command.
stderrBase64-encoded chunkStandard error from the command.
exit{"exit_code": N}Command completed. Terminal event.
error{"error": "…", "code": "…"}Command failed. Terminal event.

File operations

MethodRouteDescription
GET/v1/sandbox/:id/file/*Read a file. Returns raw bytes (application/octet-stream).
PUT/v1/sandbox/:id/file/*Write a file. Request body is raw bytes. Returns {"ok": true}. Max 32 MiB.

The file path is encoded in the URL after /file/. All paths must resolve within /workspace. Path traversal attempts (for example, ../../etc/passwd) are rejected.

Workspace persistence

MethodRouteDescription
POST/v1/sandbox/:id/persistSerialize /workspace to a tar archive. Returns raw tar bytes.
POST/v1/sandbox/:id/hydratePopulate /workspace from a tar archive sent as the request body.

The /persist endpoint accepts an optional excludes query parameter — a comma-separated list of relative paths to exclude from the archive.

The /hydrate endpoint accepts a raw tar payload up to 32 MiB.

Bucket mounts

MethodRouteDescription
POST/v1/sandbox/:id/mountMount an S3-compatible bucket as a local directory.
POST/v1/sandbox/:id/unmountUnmount a previously mounted bucket.

The /mount endpoint accepts a JSON body:

{
"bucket": "my-bucket",
"mountPath": "/mnt/data",
"options": {
"endpoint": "https://ACCOUNT_ID.r2.cloudflarestorage.com",
"readOnly": false,
"prefix": "subdir/",
"credentials": {
"accessKeyId": "...",
"secretAccessKey": "..."
}
}
}

Credentials are optional — the bridge auto-detects from Worker secrets (R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY or AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY) when omitted.

Sessions

MethodRouteDescription
POST/v1/sandbox/:id/sessionCreate a session. Returns {"id": "<session-id>"}.
DELETE/v1/sandbox/:id/session/:sidDelete a session. Returns 204.

Sessions isolate working directory, environment variables, and command execution state within a sandbox. Pass the Session-Id header on /exec, /file/*, and /pty requests to scope them to a session.

When no Session-Id header is provided, requests use the sandbox default session.

Terminal (PTY)

MethodRouteDescription
GET/v1/sandbox/:id/ptyUpgrade to a WebSocket PTY session.

Query parameters:

ParameterTypeDefaultDescription
colsnumber80Terminal width in columns.
rowsnumber24Terminal height in rows.
shellstringShell binary (for example, /bin/bash).
sessionstringSession ID for session-scoped PTY.

The WebSocket carries binary frames for terminal I/O and JSON text frames for control messages:

DirectionFrame typeContent
Client to serverBinaryUTF-8 encoded keystrokes.
Server to clientBinaryTerminal output including ANSI escape sequences.
Client to serverText (JSON)Control messages (for example, {"type": "resize", "cols": 120, "rows": 30}).
Server to clientText (JSON)Status messages (ready, exit, error).

Warm pool

MethodRouteDescription
GET/v1/pool/statsCurrent pool statistics.
POST/v1/pool/primeStart the warm pool alarm loop.
POST/v1/pool/shutdown-prewarmedStop all idle warm containers.

The warm pool pre-starts sandbox containers so new sessions boot instantly. Configure it with environment variables in wrangler.jsonc:

JSONC
{
"$schema": "./node_modules/wrangler/config-schema.json",
"vars": {
"WARM_POOL_TARGET": "3",
"WARM_POOL_REFRESH_INTERVAL": "10000"
}
}

A cron trigger (* * * * *) primes the pool automatically after deployment. Set WARM_POOL_TARGET to "0" (the default) to disable the pool and avoid unexpected costs.

Health check

MethodRouteDescription
GET/healthUnauthenticated liveness probe. Returns {"ok": true}.