SDK & API
SDK Reference
Complete reference for the @banata-boxes/sdk TypeScript SDK — browser sessions, code sandboxes, webhooks, and billing.
The @banata-boxes/sdk package is the official TypeScript SDK for Banata Boxes. It provides two main classes: BrowserCloud for browser sessions and BanataSandbox for code sandboxes.
Installation
npm install @banata-boxes/sdk
# or
bun add @banata-boxes/sdk
# or
yarn add @banata-boxes/sdkBrowserCloud
Manages headless browser sessions with CDP access.
Constructor
import \{ BrowserCloud \} from "@banata-boxes/sdk";
const cloud = new BrowserCloud(\{
apiKey: "br_live_...", // Required
baseUrl: "https://...", // Default: "https://api.boxes.banata.dev"
appUrl: "https://boxes.banata.dev", // Optional public app host for viewer URLs
retry: \{
maxRetries: 3, // Default: 3
baseDelayMs: 500, // Default: 500
maxDelayMs: 10000, // Default: 10,000
\},
\});cloud.launch(config)
Creates a session, waits for it to become ready, and returns the CDP URL. This is the recommended way to use the SDK.
const \{ cdpUrl, sessionId, previewViewerUrl, close \} = await cloud.launch(\{
weight: "light",
stealth: true,
recording: true,
timeout: 30000,
\});
// Use cdpUrl with Puppeteer, Playwright, or any CDP client
const browser = await puppeteer.connect(\{ browserWSEndpoint: cdpUrl \});
// Or hand a human the standalone viewer URL
console.log(previewViewerUrl);
// Clean up when done
await browser.disconnect();
await close();Config options:
| Field | Type | Default | Description |
|---|---|---|---|
weight | "light" | "medium" | "heavy" | "light" | Browser session tier |
isolation | "shared" | "dedicated" | "shared" | Machine isolation (Pro+) |
egressProfile | string | Auto | Outbound IP profile |
stealth | boolean | false | Anti-detection (Builder+) |
recording | boolean | false | MP4 recording (Pro+) |
captcha | boolean | false | Auto CAPTCHA solving |
maxDurationMs | number | Plan limit | Session TTL in ms |
proxy | object | — | BYO proxy {protocol, host, port, username?, password?} |
profileKey | string | — | Saved browser profile key |
region | string | — | Preferred region (e.g. "iad", "lhr") |
timeout | number | 30,000 | Max wait for ready (ms) |
Returns: \{ cdpUrl: string, sessionId: string, previewViewerUrl: string \| null, getPreviewViewerUrl: () => Promise<string \| null>, close: () => Promise<void> \}
cloud.createBrowser(config)
Creates a session and returns immediately without waiting for ready.
const session = await cloud.createBrowser(\{ weight: "medium" \});
// session.id, session.status === "queued"cloud.getBrowser(sessionId)
Gets the current status of a session.
const session = await cloud.getBrowser("session-id");
// session.status, session.cdpUrl, session.artifactscloud.closeBrowser(sessionId)
Ends a session and triggers cleanup.
await cloud.closeBrowser("session-id");cloud.waitForReady(sessionId, timeoutMs)
Polls until the session is ready and returns the CDP URL.
const cdpUrl = await cloud.waitForReady("session-id", 30000);BanataSandbox
Manages code sandbox sessions with execution, filesystem, AI agent, and human handoff capabilities.
Constructor
import \{ BanataSandbox \} from "@banata-boxes/sdk";
const sandbox = new BanataSandbox(\{
apiKey: "br_live_...", // Required
baseUrl: "https://...", // Default: "https://api.boxes.banata.dev"
appUrl: "https://boxes.banata.dev", // Optional public app host for standalone viewers
retry: \{
maxRetries: 3,
baseDelayMs: 500,
maxDelayMs: 10000,
\},
\});sandbox.launch(config)
Creates a sandbox, waits for it to become ready, and returns a rich session object with bound methods. This is the recommended way to use sandboxes.
const session = await sandbox.launch(\{
runtime: "bun",
size: "standard",
capabilities: \{
opencode: \{ enabled: true, defaultAgent: "build", allowPromptApi: true \},
browser: \{
mode: "local-chromium",
streamPreview: true,
humanInLoop: true,
viewport: \{ width: 1280, height: 800 \},
\},
\},
\});
// Execute commands
const result = await session.exec("echo", ["Hello from sandbox!"]);
console.log(result.stdout); // "Hello from sandbox!"
// Run code
const code = await session.runCode("console.log(1 + 1)");
console.log(code.stdout); // "2"
// Read/write files
await session.fs.write("/workspace/hello.txt", "Hello!");
const content = await session.fs.read("/workspace/hello.txt");
const files = await session.fs.list("/workspace");
// AI agent prompt (requires opencode capability)
const response = await session.prompt("Create a simple web server");
// Start or resize the live browser preview if needed
await session.startPreview();
await session.resizePreview(\{ width: 1100, height: 720 \});
console.log(session.browserPreviewViewerUrl);
// Read OpenCode state or stream events
const state = await session.getOpencodeState(\{ ensureSession: true \});
// Create a checkpoint (snapshot)
const checkpoint = await session.checkpoint();
// Clean up
await session.kill();Config options:
| Field | Type | Default | Description |
|---|---|---|---|
runtime | "bun" | "python" | "base" | "bun" | Runtime environment |
size | "standard" | "standard" | Standard sandbox worker shape (2 shared vCPUs / 4 GB RAM). |
env | Record<string, string> | — | Environment variables |
ephemeral | boolean | true | Destroy on kill |
maxDurationMs | number | Plan limit | Session TTL in ms |
region | string | — | Preferred region |
capabilities | object | — | OpenCode, browser, docs, storage |
timeout | number | 30,000 | Max wait for ready (ms) |
Returns: LaunchedSandbox — an object with these bound methods:
| Method | Description |
|---|---|
exec(command, args?) | Run a shell command |
runCode(code) | Run code in the sandbox runtime |
prompt(text, options?) | Send an AI agent prompt (OpenCode) |
promptAsync(text, options?) | Queue an async OpenCode prompt |
getOpencodeState(options?) | Get current OpenCode session state |
listOpencodeMessages(options?) | Read OpenCode message history |
streamOpencodeEvents(options?) | Stream OpenCode SSE events |
checkpoint() | Snapshot the sandbox state |
fs.read(path) | Read a file |
fs.write(path, content) | Write a file |
fs.list(path?) | List directory contents |
getRuntime() | Get full runtime state |
getPreview() | Get browser preview state |
getPreviewViewerUrl() | Get a standalone public viewer URL for the browser |
getPreviewConnection() | Get preview WS/start/navigate/resize URLs |
startPreview() | Warm and attach the preview backend |
navigatePreview(url) | Navigate the preview/browser from the SDK |
resizePreview(size) | Resize the preview/browser viewport |
getHandoff() | Get human handoff state |
setControl(mode, options?) | Set browser control mode |
takeControl(options?) | Take human control of browser |
returnControl(options?) | Return control to AI |
requestHumanHandoff(options) | Request a human operator |
acceptHumanHandoff(options) | Accept a handoff request |
completeHumanHandoff(options?) | Complete handoff, return to AI |
kill() | Destroy the sandbox |
sandbox.create(config)
Creates a sandbox and returns immediately without waiting for ready.
const session = await sandbox.create(\{ runtime: "python", size: "standard" \});
// session.id, session.status === "queued"sandbox.get(id)
Gets the current status of a sandbox session.
const session = await sandbox.get("sandbox-id");
// session.status, session.terminalUrl, session.opencode, session.browserPreviewViewerUrl, etc.sandbox.list()
Lists all sandbox sessions for your organization.
const sessions = await sandbox.list();sandbox.kill(id)
Destroys a sandbox session.
await sandbox.kill("sandbox-id");sandbox.exec(id, command, args?)
Executes a shell command in the sandbox.
const result = await sandbox.exec("sandbox-id", "ls", ["-la", "/workspace"]);
// result.stdout, result.stderr, result.exitCode, result.durationMssandbox.runCode(id, code)
Runs code using the sandbox's configured runtime (bun/python/base).
const result = await sandbox.runCode("sandbox-id", "print('Hello from Python!')");sandbox.pause(id) / sandbox.resume(id)
Pause a sandbox to stop billing while preserving state. Resume when ready.
await sandbox.pause("sandbox-id");
// ... later ...
await sandbox.resume("sandbox-id");sandbox.fs
File system operations.
// Read a file
const content = await sandbox.fs.read("sandbox-id", "/workspace/app.ts");
// Write a file
await sandbox.fs.write("sandbox-id", "/workspace/app.ts", "console.log('hello')");
// List directory
const entries = await sandbox.fs.list("sandbox-id", "/workspace");
// entries: [\{ name: "app.ts", type: "file", size: 22, mtime: ... \}]sandbox.terminal(id)
Gets the WebSocket terminal URL for interactive access.
const \{ terminalUrl, token \} = await sandbox.terminal("sandbox-id");
// Connect via WebSocket: new WebSocket(terminalUrl)sandbox.prompt(id, prompt, options?)
Sends a prompt to the OpenCode AI agent running in the sandbox.
const response = await sandbox.prompt("sandbox-id", "Create a REST API with Express", \{
agent: "build", // "build" or "plan"
noReply: false, // Set true for fire-and-forget
\});sandbox.promptAsync(id, prompt, options?)
Queue a prompt without waiting on the synchronous response path. Useful when paired with streamOpencodeEvents().
await sandbox.promptAsync("sandbox-id", "Open example.com and summarize the page", \{
agent: "build",
\});sandbox.getOpencodeState / sandbox.listOpencodeMessages / sandbox.streamOpencodeEvents
Use these to build your own OpenCode UI or to monitor work from your own app:
const state = await sandbox.getOpencodeState("sandbox-id", \{
ensureSession: true,
agent: "build",
\});
const messages = await sandbox.listOpencodeMessages("sandbox-id");
for await (const event of sandbox.streamOpencodeEvents("sandbox-id")) \{
console.log(event.type, event.data);
if (event.type === "session.idle") break;
\}sandbox.checkpoint(id)
Creates a checkpoint (snapshot) of the sandbox state.
const result = await sandbox.checkpoint("sandbox-id");
// result.ok, result.artifactssandbox.getArtifacts(id) / sandbox.getArtifactDownloadUrl(id, key)
Access sandbox artifacts (logs, outputs, checkpoints).
const \{ artifacts \} = await sandbox.getArtifacts("sandbox-id");
const download = await sandbox.getArtifactDownloadUrl("sandbox-id", artifacts.outputLogKey);
// download.url — presigned download URLHuman Handoff
For sandboxes with browser capabilities, you can request a human operator to take control when the AI encounters MFA, CAPTCHA, or ambiguous UI.
// Request human assistance
const handoff = await sandbox.requestHumanHandoff("sandbox-id", \{
reason: "mfa",
message: "MFA code required for login",
resumePrompt: "Continue after MFA is completed",
expiresInMs: 300000, // 5 minutes
\});
// Human accepts and takes control
const accepted = await sandbox.acceptHumanHandoff("sandbox-id", \{
controller: "operator@example.com",
leaseMs: 120000,
\});
// Human completes the task
const completed = await sandbox.completeHumanHandoff("sandbox-id", \{
note: "MFA code entered successfully",
returnControlTo: "ai",
runResumePrompt: true, // Runs the resumePrompt from the request
\});Handoff reasons: "mfa", "captcha", "approval", "login_failed", "ambiguous_ui", "file_download", "custom"
Browser Control
For sandboxes with browser capabilities, control who operates the browser.
// Set browser to human control
await sandbox.setControl("sandbox-id", "human", \{
controller: "user@example.com",
leaseMs: 60000,
\});
// Return to AI control
await sandbox.setControl("sandbox-id", "ai");
// Shared mode (both AI and human can interact)
await sandbox.setControl("sandbox-id", "shared");Preview helpers
The SDK exposes two preview surfaces:
browserPreviewViewerUrl/getPreviewViewerUrl()for the standalone public viewer pagegetPreviewConnection()for the raw preview transport if you are embedding your own viewer
If you are embedding the remote browser in your own UI, use the preview helpers to derive the noVNC/websocket endpoints and warm the preview backend:
const viewerUrl = await sandbox.getPreviewViewerUrl("sandbox-id");
const preview = await sandbox.getPreviewConnection("sandbox-id");
await sandbox.startPreview("sandbox-id");
await sandbox.navigatePreview("sandbox-id", "https://example.com");
await sandbox.resizePreview("sandbox-id", \{ width: 1280, height: 800 \});
console.log(viewerUrl); // Public standalone viewer page
console.log(preview?.wsUrl);Webhooks
Manage webhook endpoints for real-time event notifications.
const cloud = new BrowserCloud(\{ apiKey: "br_live_..." \});
// Create a webhook
const webhook = await cloud.createWebhook(\{
url: "https://your-app.com/webhooks/banata",
eventTypes: ["session.ready", "session.ended", "sandbox.failed"],
\});
// webhook.signingSecret — save this to verify signatures
// List webhooks
const webhooks = await cloud.listWebhooks();
// Send a test delivery
await cloud.testWebhook(webhook.id);
// Delete a webhook
await cloud.deleteWebhook(webhook.id);Billing
const cloud = new BrowserCloud(\{ apiKey: "br_live_..." \});
// Get current usage
const usage = await cloud.getUsage();
// usage.totalSessions, usage.totalBrowserHours
// Get billing info
const billing = await cloud.getBilling();
// billing.plan, billing.currentPeriod
// Create a checkout session for plan upgrade
const \{ checkoutUrl \} = await cloud.createCheckout(\{
plan: "pro",
successUrl: "https://your-app.com/billing/success",
\});Error Handling
The SDK throws BanataError for all API errors.
import \{ BrowserCloud, BanataSandbox, BanataError \} from "@banata-boxes/sdk";
try \{
const session = await sandbox.launch(\{ runtime: "bun" \});
\} catch (error) \{
if (error instanceof BanataError) \{
console.log(error.status); // HTTP status (e.g. 403)
console.log(error.code); // "PLAN_FEATURE_UNAVAILABLE"
console.log(error.requiredPlan); // "builder"
console.log(error.currentPlan); // "free"
console.log(error.message); // Human-readable message
\}
\}| Code | Meaning |
|---|---|
PLAN_FEATURE_UNAVAILABLE | Feature requires a higher plan |
PLAN_LIMIT_EXCEEDED | Exceeds your plan's limit |
PERMISSION_DENIED | API key lacks the required permission |
SCHEDULING_FAILED | No machine could be assigned |
Retry behavior
Both BrowserCloud and BanataSandbox automatically retry on:
- 5xx server errors
- 429 rate limit errors (respects
Retry-Afterheader) - Network errors (connection refused, timeouts)
Retries use exponential backoff with jitter.
Full Examples
Browser session with Puppeteer
import puppeteer from "puppeteer-core";
import \{ BrowserCloud \} from "@banata-boxes/sdk";
const cloud = new BrowserCloud(\{ apiKey: process.env.BANATA_API_KEY! \});
const \{ cdpUrl, close \} = await cloud.launch(\{
weight: "medium",
stealth: true,
\});
const browser = await puppeteer.connect(\{ browserWSEndpoint: cdpUrl \});
const page = (await browser.pages())[0];
await page.goto("https://example.com");
console.log(await page.title());
await browser.disconnect();
await close();Code sandbox with file I/O
import \{ BanataSandbox \} from "@banata-boxes/sdk";
const sandbox = new BanataSandbox(\{ apiKey: process.env.BANATA_API_KEY! \});
const session = await sandbox.launch(\{
runtime: "python",
size: "standard",
\});
// Write a Python script
await session.fs.write("/workspace/analyze.py", `
import json
data = \{"result": [i**2 for i in range(10)]\}
print(json.dumps(data))
`);
// Run it
const result = await session.exec("python3", ["/workspace/analyze.py"]);
console.log(JSON.parse(result.stdout));
await session.kill();AI agent with human handoff
import \{ BanataSandbox \} from "@banata-boxes/sdk";
const sandbox = new BanataSandbox(\{ apiKey: process.env.BANATA_API_KEY! \});
const session = await sandbox.launch(\{
runtime: "bun",
capabilities: \{
opencode: \{ enabled: true, defaultAgent: "build" \},
browser: \{ mode: "paired-banata-browser", humanInLoop: true \},
\},
\});
// Send AI agent a task
await session.prompt("Log into dashboard.example.com and export the monthly report");
// If the AI encounters MFA, request human help
await session.requestHumanHandoff(\{
reason: "mfa",
message: "MFA code needed for dashboard.example.com",
resumePrompt: "Continue exporting the report after login",
\});
// ... human completes MFA via browser preview ...
await session.completeHumanHandoff(\{
returnControlTo: "ai",
runResumePrompt: true,
\});
await session.kill();Next Steps
- Quick Start — Get started with your first session
- Browser Sessions — All browser session options
- Sandboxes — Sandbox configuration and capabilities
- Webhooks — Real-time event notifications
- API Reference — Raw HTTP endpoint reference