API Reference
API Reference
Complete HTTP API reference for all Banata browser session, sandbox, billing, and health endpoints.
Base URL: https://api.boxes.banata.dev
All endpoints require a Bearer token in the Authorization header unless noted otherwise:
Authorization: Bearer br_live_...Browser Sessions
POST /v1/browsers
Create a new browser session.
Request body:
| Field | Type | Default | Description |
|---|---|---|---|
weight | "light" | "medium" | "heavy" | "light" | Memory allocation tier |
isolation | "shared" | "dedicated" | "shared" | Machine sharing mode |
egressProfile | "shared-dc" | "dedicated-dc" | "rotating-residential" | "static-residential" | "byo-proxy" | Auto | Outbound IP profile |
stealth | boolean | false | Enable anti-detection (Builder+) |
recording | boolean | false | Enable MP4 session recording (Pro+) |
captcha | boolean | false | Enable auto CAPTCHA solving |
maxDurationMs | number | Plan limit | Per-session time limit (ms) |
proxy | object | — | Your own proxy server |
profileKey | string | — | Saved browser profile key |
region | string | — | Preferred region (3-letter code) |
Proxy object:
| Field | Type | Required |
|---|---|---|
protocol | "http" | "https" | "socks5" | Yes |
host | string | Yes |
port | number | Yes |
username | string | No |
password | string | No |
Response (201):
{
"id": "j57f40gk2nm535kdj49n8e051s81wt6y",
"status": "queued",
"cdpUrl": null,
"weight": "light",
"isolation": "shared",
"egressProfile": "shared-dc"
}Permission: browser_sessions:create
Rate limit: 60/min (burst: 20)
GET /v1/browsers
Get session status or list active sessions.
With id — single session:
GET /v1/browsers?id=SESSION_ID{
"id": "...",
"status": "ready",
"cdpUrl": "wss://...",
"weight": "light",
"isolation": "shared",
"egressProfile": "shared-dc",
"artifacts": { "screenshots": [], "har": null, "recording": null },
"duration": null,
"createdAt": 1772078705353
}Without id — list active sessions:
GET /v1/browsers
GET /v1/browsers?limit=50{
"data": [
{
"id": "...",
"status": "ready",
"cdpUrl": "wss://...",
"weight": "light",
"egressProfile": "shared-dc",
"createdAt": 1772078705353,
"startedAt": 1772078708000
}
]
}limit range: 1–100, default: 25.
Session statuses: queued → assigning → ready → active → ending → ended | failed
Permission: browser_sessions:read
Rate limit: 600/min (burst: 100)
DELETE /v1/browsers?id={sessionId}
End a session and trigger cleanup.
Response (200): { "ok": true }
Permission: browser_sessions:delete
Rate limit: 120/min (burst: 30)
Sandbox Sessions
POST /v1/sandboxes
Create a new sandbox session.
Request body:
| Field | Type | Default | Description |
|---|---|---|---|
runtime | "bun" | "python" | "base" | "bun" | Runtime environment |
size | "standard" | "standard" | Standard 2 shared vCPU / 4 GB sandbox shape. |
env | Record<string, string> | — | Environment variables |
ephemeral | boolean | true | Ephemeral workspace |
maxDurationMs | number | Plan limit | Max duration (ms, max 7,200,000) |
region | string | — | Preferred region (3-letter code) |
capabilities | object | — | Advanced features (see below) |
Capabilities object:
{
"opencode": { "enabled": true, "defaultAgent": "build", "allowPromptApi": true },
"browser": { "mode": "paired-banata-browser", "recording": true, "persistentProfile": true, "streamPreview": true, "humanInLoop": true },
"documents": { "libreofficeHeadless": true },
"storage": { "workspace": "checkpointed", "artifactPrefix": "prefix/" }
}Response (201):
{
"id": "k82g51hl...",
"status": "queued",
"runtime": "bun",
"size": "standard",
"capabilities": null
}Permission: sandbox_sessions:create
Rate limit: 60/min (burst: 20)
GET /v1/sandboxes
Get sandbox status or list all sandboxes.
With id: Returns full session details including terminalUrl, capabilities, pairedBrowser, opencode, browserPreview, humanHandoff, artifacts.
If you need a standalone human-viewable browser page, use the SDK’s derived browserPreviewViewerUrl or construct a viewer URL on your app host from the preview metadata. The raw API returns preview transport metadata, not a rendered HTML page.
Without id: Returns { "items": [...] } with all sessions for your org.
Permission: sandbox_sessions:read
Rate limit: 600/min (burst: 100)
DELETE /v1/sandboxes?id={sessionId}
End a sandbox session.
Response (200): { "ok": true }
Permission: sandbox_sessions:delete
Rate limit: 120/min (burst: 30)
POST /v1/sandboxes/pause
Suspend a sandbox, preserving workspace state.
Body: { "id": "SANDBOX_ID" }
Response: { "ok": true }
Permission: sandbox_sessions:delete
POST /v1/sandboxes/resume
Resume a paused sandbox.
Body: { "id": "SANDBOX_ID" }
Response: { "ok": true }
Permission: sandbox_sessions:create
Sandbox Execution
POST /v1/sandboxes/exec
Execute a shell command. Requires ready or active state.
Body: { "id": "...", "command": "...", "args": [...], "timeout": 30000 }
Permission: sandbox_sessions:exec
Rate limit: 300/min (burst: 50)
POST /v1/sandboxes/code
Execute a code snippet. Requires ready or active state.
Body: { "id": "...", "code": "...", "timeout": 30000 }
Permission: sandbox_sessions:exec
Rate limit: 300/min (burst: 50)
GET /v1/sandboxes/terminal?id={id}
Get WebSocket URL and token for interactive terminal.
Response: { "terminalUrl": "wss://...", "token": "eyJ..." }
Permission: sandbox_sessions:exec
Rate limit: 600/min (burst: 100)
Sandbox File System
GET /v1/sandboxes/fs/read?id={id}&path={path}
Read a file from the sandbox.
Permission: sandbox_sessions:exec
Rate limit: 300/min (burst: 50)
POST /v1/sandboxes/fs/write
Write a file to the sandbox.
Body: { "id": "...", "path": "...", "content": "..." }
Permission: sandbox_sessions:exec
Rate limit: 300/min (burst: 50)
GET /v1/sandboxes/fs/list?id={id}&path={path}
List directory contents. path defaults to /workspace.
Permission: sandbox_sessions:exec
Rate limit: 300/min (burst: 50)
Sandbox Browser Preview
GET /v1/sandboxes/browser-preview?id={id}
Get browser preview metadata (requires browser capability).
This returns the raw preview transport metadata used by the dashboard and SDK. It is intended for embedding a viewer or warming the preview backend, not for directly pasting into a browser tab.
Permission: sandbox_sessions:read
POST /v1/sandboxes/browser-preview/control
Switch browser control mode.
Body: { "id": "...", "mode": "human"|"ai"|"shared", "controller": "...", "leaseMs": 300000 }
Permission: sandbox_sessions:exec
Sandbox OpenCode
GET /v1/sandboxes/opencode/state?id={id}
Get the current OpenCode state for a sandbox.
Query: ensureSession=1|true optionally creates an OpenCode session if one does not exist yet. agent=build|plan selects the default agent when ensuring a session.
Permission: sandbox_sessions:read
GET /v1/sandboxes/opencode/messages?id={id}&sessionId={sessionId}
Get the current OpenCode message history.
Permission: sandbox_sessions:read
GET /v1/sandboxes/opencode/events?id={id}&sessionId={sessionId}
Stream OpenCode events as Server-Sent Events (SSE).
This is the recommended primitive if you are building your own OpenCode chat UI. The Banata dashboard uses the same stream to render the chat timeline incrementally.
Permission: sandbox_sessions:read
POST /v1/sandboxes/opencode/prompt-async
Queue an async prompt for OpenCode.
Body: { "id": "...", "prompt": "...", "agent": "build"|"plan", "sessionId": "..." }
Permission: sandbox_sessions:exec
Rate limit: 300/min (burst: 50)
POST /v1/sandboxes/opencode/prompt
Send a prompt to the AI agent (requires opencode capability with allowPromptApi not false).
Body: { "id": "...", "prompt": "...", "agent": "build"|"plan", "sessionId": "...", "noReply": false }
Permission: sandbox_sessions:exec
Rate limit: 300/min (burst: 50)
Sandbox Human Handoff
GET /v1/sandboxes/handoff?id={id}
Get current handoff state.
Permission: sandbox_sessions:read
POST /v1/sandboxes/handoff/request
Request human intervention.
Body: { "id": "...", "reason": "mfa"|"captcha"|"approval"|"login_failed"|"ambiguous_ui"|"file_download"|"custom", "message": "...", "requestedBy": "sdk", "resumePrompt": "...", "expiresInMs": 300000 }
Permission: sandbox_sessions:exec
POST /v1/sandboxes/handoff/accept
Human accepts control.
Body: { "id": "...", "controller": "...", "leaseMs": 300000 }
Permission: sandbox_sessions:exec
POST /v1/sandboxes/handoff/complete
Human returns control.
Body: { "id": "...", "controller": "...", "note": "...", "returnControlTo": "ai"|"shared", "runResumePrompt": true }
Permission: sandbox_sessions:exec
Sandbox Artifacts
POST /v1/sandboxes/checkpoint
Persist workspace snapshot.
Body: { "id": "..." }
Permission: sandbox_sessions:exec
GET /v1/sandboxes/artifacts?id={id}
List artifact pointers.
Permission: sandbox_sessions:read
GET /v1/sandboxes/artifacts/download?id={id}&key={key}&expiresIn={seconds}
Get a signed download URL. expiresIn range: 1–86400, default: 3600.
Response: { "id": "...", "key": "...", "url": "https://signed-url...", "expiresInSeconds": 3600 }
Permission: sandbox_sessions:read
Sandbox Runtime
GET /v1/sandboxes/runtime?id={id}
Get runtime status including capabilities, OpenCode state, browser state, handoff state, and artifacts.
Permission: sandbox_sessions:read
Usage & Billing
GET /v1/usage
Current billing period usage.
{
"totalSessions": 42,
"totalBrowserHours": 12.5,
"weightBreakdown": { "light": 20, "medium": 15, "heavy": 7 },
"periodStart": 1709251200000
}Permission: org:billing
Rate limit: 30/min (burst: 10)
GET /v1/billing
Billing info for your organization.
{
"hasSubscription": true,
"plan": "pro",
"polarCustomerId": "cust_abc123",
"currentPeriod": {
"totalSessions": 42,
"totalBrowserHours": 12.5,
"weightBreakdown": { "light": 20, "medium": 15, "heavy": 7 }
}
}Permission: org:billing
Rate limit: 30/min (burst: 10)
POST /v1/billing/checkout
Create a checkout session for plan upgrade.
Body:
| Field | Type | Required | Description |
|---|---|---|---|
plan | "builder" | "pro" | "scale" | Yes | Target plan |
successUrl | string | No | HTTPS redirect URL after payment |
Response:
{
"checkoutUrl": "https://polar.sh/checkout/...",
"checkoutId": "checkout_abc123"
}Permission: org:billing
Rate limit: 5/min (burst: 2)
Health
GET /health
System health summary. No authentication required.
{
"status": "healthy",
"timestamp": 1772078705353,
"machines": { "running": 3, "total": 5 },
"sessions": { "active": 2 },
"errors": { "last5min": 0 }
}| Status | HTTP Code |
|---|---|
healthy | 200 |
degraded | 503 |
unhealthy | 503 |
Common Error Codes
| Code | Meaning |
|---|---|
PLAN_FEATURE_UNAVAILABLE | Feature requires a higher plan. Response includes requiredPlan and currentPlan. |
PLAN_LIMIT_EXCEEDED | Value exceeds your plan's limit (e.g., maxDurationMs too high). |
PERMISSION_DENIED | API key lacks the required permission. |
SCHEDULING_FAILED | No machine could be assigned. Includes a reason field. |