Execution API
Run shell commands and scripts inside sandboxes via the Execution API. Execute any process, stream output in real time, and capture exit codes.
Endpoint
Section titled “Endpoint”| Method | Path | Description |
|---|---|---|
POST | /v1/sandboxes/:id/execute | Execute a command inside a sandbox |
POST /v1/sandboxes/:id/execute
Section titled “POST /v1/sandboxes/:id/execute”Run a command or script inside a running sandbox. The sandbox must be in the running state.
Basic Request
Section titled “Basic Request”curl -X POST https://api.box.runra.dev/v1/sandboxes/sb_x7k2m9p4q1w3v5b8n/execute \ -H "Authorization: Bearer $RUNRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "command": "echo Hello from sandbox && node --version" }'Response — 200 OK
Section titled “Response — 200 OK”{ "stdout": "Hello from sandbox\nv22.12.0\n", "stderr": "", "exitCode": 0, "durationMs": 245, "signal": null}Request Body
Section titled “Request Body”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
command | string | Yes | — | Shell command to execute (bash) |
cwd | string | No | /workspace | Working directory for the command |
env | object | No | {} | Additional environment variables (merged with sandbox env) |
timeoutMs | integer | No | 60000 | Command timeout in ms (max 300000 = 5 min) |
stdin | string | No | — | Text to pipe to the command’s stdin |
Response Fields
Section titled “Response Fields”| Field | Type | Description |
|---|---|---|
stdout | string | Standard output from the command |
stderr | string | Standard error from the command |
exitCode | integer | Process exit code. 0 = success, non-zero = error |
durationMs | integer | Wall-clock execution time in milliseconds |
signal | string | null | Signal that killed the process, or null if exited normally |
Advanced Usage
Section titled “Advanced Usage”Environment Variables
Section titled “Environment Variables”Pass environment variables per execution. These are merged with the sandbox-level env:
curl -X POST https://api.box.runra.dev/v1/sandboxes/sb_x7k2m9p4q1w3v5b8n/execute \ -H "Authorization: Bearer $RUNRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "command": "echo $MY_VAR && echo $CI", "env": { "MY_VAR": "custom value", "CI": "true" } }'Execution-level env vars take precedence over sandbox-level env vars with the same name.
Working Directory
Section titled “Working Directory”Specify a different working directory:
curl -X POST https://api.box.runra.dev/v1/sandboxes/sb_x7k2m9p4q1w3v5b8n/execute \ -H "Authorization: Bearer $RUNRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "command": "cat package.json", "cwd": "/workspace/my-project" }'Timeout
Section titled “Timeout”Set per-command timeouts. The default is 60 seconds, maximum is 5 minutes:
curl -X POST https://api.box.runra.dev/v1/sandboxes/sb_x7k2m9p4q1w3v5b8n/execute \ -H "Authorization: Bearer $RUNRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "command": "npm run build", "timeoutMs": 120000 }'If the command exceeds the timeout, it receives SIGKILL and the response returns:
{ "stdout": "Starting build...\n", "stderr": "", "exitCode": null, "durationMs": 120001, "signal": "SIGKILL"}Pipe input to a command:
curl -X POST https://api.box.runra.dev/v1/sandboxes/sb_x7k2m9p4q1w3v5b8n/execute \ -H "Authorization: Bearer $RUNRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "command": "grep error", "stdin": "info: starting\ninfo: processing\nerror: something broke\ninfo: done\n" }'Response:
{ "stdout": "error: something broke\n", "stderr": "", "exitCode": 0, "durationMs": 12, "signal": null}Streaming Output
Section titled “Streaming Output”For long-running commands, stream stdout and stderr in real time using Server-Sent Events (SSE).
Request with Streaming
Section titled “Request with Streaming”curl -X POST https://api.box.runra.dev/v1/sandboxes/sb_x7k2m9p4q1w3v5b8n/execute \ -H "Authorization: Bearer $RUNRA_API_KEY" \ -H "Content-Type: application/json" \ -H "Accept: text/event-stream" \ -d '{ "command": "for i in 1 2 3; do echo Line $i; sleep 1; done" }'Streaming Response
Section titled “Streaming Response”event: stdoutdata: Line 1
event: stdoutdata: Line 2
event: stdoutdata: Line 3
event: donedata: {"exitCode":0,"durationMs":3012,"signal":null}Event Types
Section titled “Event Types”| Event | Payload | Description |
|---|---|---|
stdout | string | A line of stdout output |
stderr | string | A line of stderr output |
done | JSON object | Command finished (includes exitCode, durationMs, signal) |
error | JSON object | Execution error |
SDK Usage
Section titled “SDK Usage”TypeScript
Section titled “TypeScript”import { Runra } from "@runra/sandbox";
const client = new Runra();
const sandbox = await client.sandboxes.create({ image: "node:22" });
// Simple executionconst result = await sandbox.exec("npm install && npm run build");console.log(result.exitCode); // 0console.log(result.stdout);
// With optionsconst result = await sandbox.exec("npm test", { cwd: "/workspace/packages/core", env: { CI: "true" }, timeoutMs: 120_000,});Python
Section titled “Python”from runra import Runra
client = Runra()sandbox = client.sandboxes.create(image="node:22")
result = sandbox.exec("ls -la /workspace")print(result.stdout)print(f"Exit code: {result.exit_code}")Exit Codes
Section titled “Exit Codes”| Exit Code | Meaning |
|---|---|
0 | Success |
1–127 | Application-specific error |
137 | Killed by SIGKILL (timeout or OOM) |
143 | Killed by SIGTERM |
null | Process didn’t start or was killed before exit |
Always check exitCode rather than relying on stderr being empty. Many tools write to stderr even on success.
const result = await sandbox.exec("npm run lint");if (result.exitCode !== 0) { console.error(`Lint failed:\n${result.stderr}`);}Concurrency Limits
Section titled “Concurrency Limits”A single sandbox can handle multiple concurrent executions. The API queues them internally and allows up to 3 concurrent executions per sandbox by default.
// These run concurrently inside the same sandboxconst [result1, result2, result3] = await Promise.all([ sandbox.exec("echo task1 && sleep 2"), sandbox.exec("echo task2 && sleep 2"), sandbox.exec("echo task3 && sleep 2"),]);If you exceed the concurrency limit, requests return 429 Too Many Requests.
Common Errors
Section titled “Common Errors”| Status | Code | Description |
|---|---|---|
400 | INVALID_REQUEST | Missing command field |
400 | COMMAND_TOO_LONG | Command exceeds 64KB limit |
404 | SANDBOX_NOT_FOUND | Sandbox doesn’t exist |
408 | EXECUTION_TIMEOUT | Command exceeded timeoutMs |
409 | INVALID_STATE | Sandbox is not in running state |
429 | RATE_LIMITED | Too many concurrent executions |
502 | EXECUTION_ERROR | Internal sandbox error |
Next Steps
Section titled “Next Steps”- Sandboxes API — manage sandbox lifecycle
- Running Code Guide — execution patterns and best practices
- CLI Reference — run commands via CLI