Docs / api / execution

Execution API

Code execution REST API — run commands inside sandboxes with streaming, exit codes, environment variables, working directory, and timeout options

Run shell commands and scripts inside sandboxes via the Execution API. Execute any process, stream output in real time, and capture exit codes.

Endpoint

MethodPathDescription
POST/v1/sandboxes/:id/executeExecute a command inside a sandbox

POST /v1/sandboxes/:id/execute

Run a command or script inside a running sandbox. The sandbox must be in the running state.

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

{
  "stdout": "Hello from sandbox\nv22.12.0\n",
  "stderr": "",
  "exitCode": 0,
  "durationMs": 245,
  "signal": null
}

Request Body

FieldTypeRequiredDefaultDescription
commandstringYesShell command to execute (bash)
cwdstringNo/workspaceWorking directory for the command
envobjectNo{}Additional environment variables (merged with sandbox env)
timeoutMsintegerNo60000Command timeout in ms (max 300000 = 5 min)
stdinstringNoText to pipe to the command's stdin

Response Fields

FieldTypeDescription
stdoutstringStandard output from the command
stderrstringStandard error from the command
exitCodeintegerProcess exit code. 0 = success, non-zero = error
durationMsintegerWall-clock execution time in milliseconds
signalstring | nullSignal that killed the process, or null if exited normally

Advanced Usage

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

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

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"
}

stdin

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

For long-running commands, stream stdout and stderr in real time using Server-Sent Events (SSE).

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

event: stdout
data: Line 1

event: stdout
data: Line 2

event: stdout
data: Line 3

event: done
data: {"exitCode":0,"durationMs":3012,"signal":null}

Event Types

EventPayloadDescription
stdoutstringA line of stdout output
stderrstringA line of stderr output
doneJSON objectCommand finished (includes exitCode, durationMs, signal)
errorJSON objectExecution error

SDK Usage

TypeScript

import { Runra } from "@runra/sandbox";

const client = new Runra();

const sandbox = await client.sandboxes.create({ image: "node:22" });

// Simple execution
const result = await sandbox.exec("npm install && npm run build");
console.log(result.exitCode); // 0
console.log(result.stdout);

// With options
const result = await sandbox.exec("npm test", {
  cwd: "/workspace/packages/core",
  env: { CI: "true" },
  timeoutMs: 120_000,
});

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

Exit CodeMeaning
0Success
1127Application-specific error
137Killed by SIGKILL (timeout or OOM)
143Killed by SIGTERM
nullProcess 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

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 sandbox
const [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

StatusCodeDescription
400INVALID_REQUESTMissing command field
400COMMAND_TOO_LONGCommand exceeds 64KB limit
404SANDBOX_NOT_FOUNDSandbox doesn't exist
408EXECUTION_TIMEOUTCommand exceeded timeoutMs
409INVALID_STATESandbox is not in running state
429RATE_LIMITEDToo many concurrent executions
502EXECUTION_ERRORInternal sandbox error

Next Steps