SandboxAPI — Code Execution API for AI Agents
12 languages. gVisor isolation. Stateful sessions. Package install. Streaming, async, webhooks, multi-file. MCP-native.
Quick Start #
Synchronous execution #
curl -X POST https://sandboxapi.p.rapidapi.com/v1/execute \
-H "Content-Type: application/json" \
-H "X-RapidAPI-Key: YOUR_API_KEY" \
-H "X-RapidAPI-Host: sandboxapi.p.rapidapi.com" \
-d '{"language":"python3","code":"print(\"Hello, World!\")"}'
Response:
{
"id": "exec_abc123",
"status": "completed",
"language": "python3",
"stdout": "Hello, World!\n",
"stderr": "",
"exit_code": 0,
"exit_signal": 0,
"execution_time_ms": 42,
"wall_time_ms": 58,
"memory_used_kb": 8192
}
Stateful session 3.2.0 #
Sessions hold a sandbox open between calls. Variables, files, and installed packages persist for the session's idle TTL (max 30 minutes).
# 1. Create a session
curl -X POST https://sandboxapi.p.rapidapi.com/v1/sessions \
-H "X-RapidAPI-Key: YOUR_API_KEY" \
-d '{"language":"python3","idle_ttl":300}'
# → {"id":"sess_abc","language":"python3","expires_at":"..."}
# 2. Execute — sets a variable
curl -X POST https://sandboxapi.p.rapidapi.com/v1/sessions/sess_abc/execute \
-H "X-RapidAPI-Key: YOUR_API_KEY" \
-d '{"code":"x = 42"}'
# 3. Execute again — variable persists
curl -X POST https://sandboxapi.p.rapidapi.com/v1/sessions/sess_abc/execute \
-H "X-RapidAPI-Key: YOUR_API_KEY" \
-d '{"code":"print(x * 2)"}'
# → stdout: "84\n"
Package installation in a session 3.3.0 #
curl -X POST https://sandboxapi.p.rapidapi.com/v1/sessions/sess_abc/install \
-H "X-RapidAPI-Key: YOUR_API_KEY" \
-d '{"manager":"pip","packages":["pandas","numpy"]}'
Supported managers: pip, npm, gem, cargo. Top-1k packages per language are cached for sub-3s installs.
Streaming output 3.1.0 #
curl -N -X POST https://sandboxapi.p.rapidapi.com/v1/execute/stream \
-H "X-RapidAPI-Key: YOUR_API_KEY" \
-d '{"language":"python3","code":"for i in range(5):\n print(i); import time; time.sleep(1)"}'
# → SSE events: stdout, stdout, ..., result
Events use the standard SSE format. The terminal event has event: result with a JSON payload that includes exit_code, execution_time_ms, and memory_used_kb.
Async + webhook 3.1.0 #
curl -X POST "https://sandboxapi.p.rapidapi.com/v1/execute?async=true" \
-H "X-RapidAPI-Key: YOUR_API_KEY" \
-d '{"language":"python3","code":"...","callback_url":"https://your.app/hook"}'
# → {"token":"job_xyz","status":"queued"}
# Either poll:
curl https://sandboxapi.p.rapidapi.com/v1/executions/job_xyz \
-H "X-RapidAPI-Key: YOUR_API_KEY"
# Or wait for the signed PUT to your callback_url.
# Verify the X-SandboxAPI-Signature: sha256=... header.
Multi-file programs 3.0.0 #
# Base64-encode a ZIP of source files, optionally with a compile script and run script.
curl -X POST https://sandboxapi.p.rapidapi.com/v1/execute \
-H "X-RapidAPI-Key: YOUR_API_KEY" \
-d '{
"language":"cpp",
"additional_files":"<base64 zip>",
"compile_script":"g++ -O2 *.cpp -o main",
"run_script":"./main"
}'
Output verification 3.0.0 #
curl -X POST https://sandboxapi.p.rapidapi.com/v1/execute \
-H "X-RapidAPI-Key: YOUR_API_KEY" \
-d '{
"language":"python3",
"code":"print(2+2)",
"expected_output":"5\n"
}'
# → status: "wrong_answer"
Supported Languages #
| Language | Version | ID |
|---|---|---|
| Python | 3.12 | python3 |
| JavaScript | Node 22 | javascript |
| TypeScript | 5.4 | typescript |
| Go | 1.22 | go |
| Java | 21 | java |
| C++ | GCC 14 | cpp |
| C | GCC 14 | c |
| Bash | 5.2 | bash |
| Rust | 1.85 | rust |
| Ruby | 3.3 | ruby |
| PHP | 8.4 | php |
| C# | .NET 9 | csharp |
Request Parameters #
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
language | string | Yes | — | Language ID |
code | string | Yes (single-file) | — | Source code (max 1MB) |
additional_files | string | Yes (multi-file) | — | Base64-encoded ZIP (max 10MB decompressed) |
compile_script | string | No | language default | Bash script to compile (max 4KB) |
run_script | string | No | language default | Bash script to run (max 4KB) |
timeout | integer | No | 10 | CPU seconds (capped by plan) |
wall_time_limit | float | No | =timeout | Wall-clock seconds |
stdin | string | No | "" | Standard input |
expected_output | string | No | — | If set, compared to stdout for wrong_answer status |
compiler_options | string | No | — | Extra flags to compile step (max 512 chars, allowlisted) |
command_line_arguments | string | No | — | Argv for the program (max 512 chars) |
redirect_stderr_to_stdout | bool | No | false | Merge streams |
base64_encoded | bool | No | false | Encode binary stdin/stdout |
callback_url | string | No | — | Webhook URL (async only) |
Response Fields #
| Field | Type | Description |
|---|---|---|
id | string | Execution ID |
status | string | completed / wrong_answer / timeout / compilation_error / runtime_error / memory_limit / internal_error |
stdout | string | Standard output (max 1MB, may be truncated) |
stderr | string | Standard error (max 1MB) |
compile_output | string | Compiler output (compiled languages only) |
exit_code | integer | Process exit code |
exit_signal | integer | Termination signal (e.g., 9 for SIGKILL) |
execution_time_ms | integer | CPU time |
wall_time_ms | integer | Wall-clock time |
memory_used_kb | integer | Peak memory |
Error Handling #
SandboxAPI distinguishes between API errors (HTTP 4xx/5xx) and execution errors (HTTP 200 with a status field). Treat any HTTP 200 response as a successful API call — the status tells you whether the user's code ran cleanly.
| HTTP | Meaning | What to do |
|---|---|---|
200 | Execution returned a result | Inspect status |
400 | Bad request (missing language, oversize body, etc.) | Fix the payload |
401 / 403 | Missing/invalid API key | Check your RapidAPI subscription |
408 | Wall-clock or queue timeout | Raise wall_time_limit or use async |
413 | Payload too large | Use multi-file with ZIP, or trim code |
429 | Rate limit exceeded | Back off or upgrade tier |
500 / 503 | Internal error | Retry with exponential backoff; report if persistent |
Pricing & Rate Limits #
| Plan | Price | Executions/mo | Timeout | Batch | Sessions | Packages | Async | Streaming |
|---|---|---|---|---|---|---|---|---|
| Basic | Free | 500 | 30s | 10 | — | — | — | ✓ |
| Pro | $19/mo | 10,000 | 60s | 50 | 5 concurrent | top-1k cache | ✓ | ✓ |
| Ultra | $49/mo | 50,000 | 300s | 100 | 20 concurrent | full allowlist | ✓ | ✓ |
| Mega | $149/mo | 200,000 | 600s | 200 | 50 concurrent | full + custom | ✓ | ✓ |
All plans include gVisor isolation, 12 languages, stdin, multi-file, output verification, and webhooks where the mode supports it. See pricing for full details.
Security #
Every execution runs inside an OCI container backed by gVisor (runsc) — a user-space kernel that intercepts syscalls before they reach the host. Combined with strict resource limits, no network egress (default), no persistent storage, and per-request cleanup, this gives you a strictly stronger isolation boundary than container-only sandboxes like raw Docker or Kubernetes.
- gVisor (runsc) wraps every container; user-space syscall filter blocks risky calls before the host kernel sees them.
- Resource limits (CPU, memory, PIDs, file descriptors, disk) are enforced by cgroups and seccomp.
- Network egress is disabled by default and gated by a per-request allowlist proxy in sessions.
- Webhook callbacks are signed with HMAC-SHA256 using a secret derived from your API key. Verify the
X-SandboxAPI-Signatureheader. - Synchronous executions retain no data. Async results live for 24h. Session state expires at the idle TTL (max 30 min).
MCP Server #
SandboxAPI is available as an MCP server at https://mcp.sandboxapi.dev/mcp with 11 tools: execute_code, execute_batch, list_languages, create_session, session_execute, session_close, session_install_packages, execute_async, get_execution, execute_with_expected, get_capabilities.
Add to Claude Desktop / Cursor / VS Code:
{
"mcpServers": {
"sandboxapi": {
"url": "https://mcp.sandboxapi.dev/mcp",
"headers": { "Authorization": "Bearer YOUR_API_KEY" }
}
}
}
Full integration guide on the MCP page.
Code Examples #
Python (requests)
import requests
resp = requests.post(
"https://sandboxapi.p.rapidapi.com/v1/execute",
headers={
"X-RapidAPI-Key": "YOUR_API_KEY",
"X-RapidAPI-Host": "sandboxapi.p.rapidapi.com",
},
json={"language": "python3", "code": "print(2 + 2)"},
)
data = resp.json()
print(data["stdout"]) # → "4\n"
JavaScript (fetch)
const resp = await fetch("https://sandboxapi.p.rapidapi.com/v1/execute", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-RapidAPI-Key": "YOUR_API_KEY",
"X-RapidAPI-Host": "sandboxapi.p.rapidapi.com",
},
body: JSON.stringify({ language: "javascript", code: "console.log(2 + 2)" }),
});
const data = await resp.json();
console.log(data.stdout); // → "4\n"
Go
req, _ := http.NewRequest("POST", "https://sandboxapi.p.rapidapi.com/v1/execute",
strings.NewReader(`{"language":"go","code":"package main\nimport \"fmt\"\nfunc main(){fmt.Println(2+2)}"}`))
req.Header.Set("X-RapidAPI-Key", "YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
Changelog #
| Version | Highlights |
|---|---|
| 3.4.0 | Direct API channel (api.sandboxapi.dev), Stripe self-serve, new Mega tier (200K exec/mo) |
| 3.3.0 | Package installation in sessions (pip/npm/gem/cargo) with offline cache |
| 3.2.0 | Stateful sessions — REPL-like execution with persistent variables, files, packages |
| 3.1.0 | SSE streaming output; async execution with signed webhook callbacks |
| 3.0.0 | 4 new languages (Rust, Ruby, PHP, C#); multi-file programs; expected_output + status taxonomy; MCP server expanded to 11 tools |
| 2.0.0 | Ultra tier (50K exec/mo), gVisor isolation, batch up to 100, 300s timeout, playground |
| 1.2.0 | Pre-warmed sandbox pools, sub-100ms cold starts, memory reporting |
| 1.1.0 | Batch execution endpoint (/execute/batch) |
| 1.0.0 | Stable release — Pro tier, rate limit headers, /health endpoint, full error codes |
| 0.3.0 | All 8 languages, stdin support, /languages endpoint |
| 0.2.0 | Added TypeScript, Go, Bash |
| 0.1.0 | Alpha — Python and JavaScript |