Caged DOCS
Get Started
API Reference Sandboxes

Sandboxes

Create Sandbox

Base image template. See Available Templates below.

Number of vCPUs (1-8, default: 2).

Memory in MB (128-8192, default: 512).

Disk in GB (1-50, default: 5).

Network access: full, none, or allowlist.

Allowed hosts when network_mode is allowlist.

Environment variables as key-value pairs.

Git repository URL to clone (HTTPS).

PAT or OAuth token for private repositories. GitHub: ghp_..., GitLab: personal access token.

Branch to checkout (default: main/master).

Specific commit SHA to checkout (overrides repo_branch).

Monorepo subdirectory to extract into /workspace.

Maximum spend in USD.

Shell command to run after creation.

Idle timeout in seconds before auto-sleep.

Packages to pre-install (npm/pip packages).

AI agents to install: claude, aider, codex.

curl -X POST https://api.caged.dev/v1/sandboxes \
  -H "Authorization: Bearer caged_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "template": "node-20",
    "cpus": 2,
    "memory_mb": 1024,
    "repo": "https://github.com/user/project",
    "budget": 5.00,
    "init_script": "npm install"
  }'

Private Repository Example

curl -X POST https://api.caged.dev/v1/sandboxes \
  -H "Authorization: Bearer caged_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "template": "node-20",
    "repo": "https://github.com/your-org/private-repo",
    "repo_token": "ghp_xxxxxxxxxxxx",
    "repo_branch": "develop",
    "agents": ["claude"],
    "budget": 10.00
  }'

Response 201 Created

{
  "id": "cage-a1b2c3d4",
  "status": "running",
  "template": "node-20",
  "ip": "10.0.1.42",
  "cpus": 2,
  "memory_mb": 1024,
  "disk_gb": 5,
  "network_mode": "full",
  "created_at": "2026-06-08T10:00:00Z"
}

List Sandboxes

curl https://api.caged.dev/v1/sandboxes \
  -H "Authorization: Bearer caged_sk_..."

Response 200 OK

[
  {
    "id": "cage-a1b2c3d4",
    "status": "running",
    "template": "node-20",
    "cpus": 2,
    "memory_mb": 1024,
    "created_at": "2026-06-08T10:00:00Z"
  }
]

Get Sandbox

curl https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4 \
  -H "Authorization: Bearer caged_sk_..."

Execute a Command

Run a shell command inside a sandbox and get the output back. Supports pipes, redirects, and environment variables. This is how you interact with sandboxes programmatically — including prompting installed AI agents.

POST /v1/sandboxes/{id}/exec

Shell command to execute. Runs via /bin/sh -c inside the sandbox with the sandbox's environment (including any env vars set at creation).

curl -X POST https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4/exec \
  -H "Authorization: Bearer caged_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"command": "python --version"}'

Response 200 OK

{
  "output": "Python 3.12.3\n",
  "exit_code": 0
}

Prompting an agent — if the sandbox was created with "agents": ["claude"], you can prompt Claude Code non-interactively:

curl -X POST https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4/exec \
  -H "Authorization: Bearer caged_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"command": "cd /workspace && claude -p \"Summarize what this repo does\""}'

Error semantics — the three outcomes are distinguishable:

Case exit_code error Meaning
Success 0 empty Command ran and succeeded
Command failed non-zero empty Command ran; its stderr is in output
Infrastructure failure 1 set Sandbox unreachable, not running, etc.

A failed command still returns HTTP 200 — the API call succeeded; the command result is data. Exec requests can run for up to 5 minutes, so long agent prompts are fine.

For a fully interactive TTY session (e.g. the Claude Code TUI), use the terminal WebSocket instead: wss://api.caged.dev/v1/sandboxes/{id}/terminal.

Pause Sandbox

Freezes the sandbox in memory. No compute charges while paused. An auto-snapshot is created.

curl -X POST https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4/pause \
  -H "Authorization: Bearer caged_sk_..."

Resume Sandbox

Unfreezes a paused sandbox.

curl -X POST https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4/resume \
  -H "Authorization: Bearer caged_sk_..."

Destroy Sandbox

Permanently destroys a sandbox and all its data.

This action is irreversible. Create a snapshot first if you need to preserve the state.

curl -X DELETE https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4 \
  -H "Authorization: Bearer caged_sk_..."

Response 204 No Content

Available Templates

Pre-configured sandbox environments with common runtimes and tools.

JavaScript / TypeScript

Template Runtime Includes
node-22 Node.js 22.x LTS npm, yarn, pnpm, typescript
node-20 Node.js 20.x LTS npm, yarn, pnpm, typescript

Python

Template Runtime Includes
python-312 Python 3.12 pip, poetry, virtualenv, black, ruff
python-311 Python 3.11 pip, poetry, virtualenv, black, ruff

Base

Template Description
minimal Ubuntu 24.04 with SSH, git, curl, build-essential. Install any runtime yourself.

Desktop

Template Description
desktop Full virtual desktop (Xvfb, Openbox, x11vnc, Chromium). For screen-grounded agents.

Aliases: gui, computer

Using minimal? You can install any runtime manually. The sandbox persists your changes until destroyed.

Screen Endpoints (Desktop Sandboxes)

These endpoints are available for sandboxes created with the desktop template.

Screenshot

Get a screenshot of the virtual desktop.

GET /v1/sandboxes/{id}/screen/screenshot

Response format: base64 (JSON) or omit for raw PNG binary.

# Get base64 JSON
curl "https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4/screen/screenshot?format=base64" \
  -H "Authorization: Bearer caged_sk_..."

Response 200 OK

{
  "image_base64": "iVBORw0KGgo...",
  "format": "png"
}
# Get raw PNG
curl "https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4/screen/screenshot" \
  -H "Authorization: Bearer caged_sk_..." \
  -o screenshot.png

Screen WebSocket

Real-time screen interaction via WebSocket.

GET /v1/sandboxes/{id}/screen (WebSocket upgrade)

Connect:

const ws = new WebSocket(
  "wss://api.caged.dev/v1/sandboxes/cage-a1b2c3d4/screen",
  { headers: { Authorization: "Bearer caged_sk_..." } }
);

Message Types:

Type Direction Description
screenshot send/receive Request/receive screenshot
click send Click at coordinates
type send Type text
key send Press key
scroll send Scroll at coordinates
drag send Drag between coordinates
launch send Launch application
info send/receive Get screen info

Example messages:

// Request screenshot
{"type": "screenshot"}

// Click
{"type": "click", "x": 640, "y": 400, "button": "left"}

// Type text
{"type": "type", "text": "Hello, world!"}

// Press key
{"type": "key", "key": "Return"}

// Scroll down
{"type": "scroll", "x": 640, "y": 400, "direction": "down", "amount": 3}

// Launch app
{"type": "launch", "command": "chromium-browser https://example.com"}

VNC Info

Get VNC connection information for the desktop sandbox.

GET /v1/sandboxes/{id}/screen/vnc

curl "https://api.caged.dev/v1/sandboxes/cage-a1b2c3d4/screen/vnc" \
  -H "Authorization: Bearer caged_sk_..."

Response 200 OK

{
  "sandbox_id": "cage-a1b2c3d4",
  "vnc_port": 5900,
  "status": "available",
  "note": "Use port forwarding to access VNC. The VNC server runs on port 5900 inside the sandbox with no password."
}

Use with port forwarding for external VNC client access.

Was this page helpful?
Assistant
Responses are generated using AI and may contain mistakes.

Ask me anything about the documentation.

ESC