Documentation

Execute Python code in secure sandboxes with streaming output, file operations, and pip package support.

LLM-optimized documentation (llms.txt) - Machine-readable quick reference

Quick Start

Sign up with your email to get a trial API key. Email verification required - you must click the link in your email to get your API key.

# 1. Sign up with your email (sends verification email)
curl -X POST https://api.cerver.ai/auth/signup \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com"}'
# Returns: {"message": "Verification email sent!", ...}

# 2. Check your email and click the verification link
# You'll receive your API key (sk_trial_xxx) after verification

# 3. Create sandbox
curl -X POST https://api.cerver.ai/sandbox \
  -H "Authorization: Bearer sk_trial_xxx"
# Returns: {"sandbox_id": "abc-123", ...}

# 4. Run code
curl -X POST https://api.cerver.ai/sandbox/abc-123/run \
  -H "Authorization: Bearer sk_trial_xxx" \
  -H "Content-Type: application/json" \
  -d '{"code": "print(2 ** 100)"}'
# Returns: {"output": "1267650600228229401496703205376", "exit_code": 0}

Trial keys have limited usage (100 requests/day). Upgrade for higher limits.

API Reference

Base URL: https://api.cerver.ai

Endpoint Description
POST /auth/signup Sign up with email (sends verification link)
GET /auth/verify-signup?token= Verify email and get API key
POST /auth/login Request magic link for dashboard access
POST /sandbox Create sandbox (with envs, timeout, metadata)
GET /sandbox/:id Get sandbox info
GET /sandboxes List all active sandboxes
DELETE /sandbox/:id Terminate sandbox
POST /sandbox/:id/timeout Extend sandbox timeout
GET /sandbox/:id/host?port=N Get external URL for port
POST /sandbox/:id/run Run code (with envs override)
POST /sandbox/:id/run/stream Run code with SSE streaming
POST /sandbox/:id/install Install pip packages
POST /sandbox/:id/files Write file
GET /sandbox/:id/files List files
GET /sandbox/:id/files?path=x Read file

Create Sandbox

Create a sandbox with optional configuration:

POST /sandbox
Authorization: Bearer sk_trial_xxx
Content-Type: application/json

{
  "engine": "containers",
  "envs": {"API_KEY": "secret123", "DEBUG": "true"},
  "timeout_ms": 600000,
  "metadata": {"project": "my-app", "user_id": "123"}
}

# Response
{
  "sandbox_id": "abc-123",
  "engine": "containers",
  "status": "ready",
  "timeout_ms": 600000,
  "expires_at": 1706000000,
  "envs": ["API_KEY", "DEBUG"],
  "metadata": {"project": "my-app", "user_id": "123"}
}

Options

Parameter Type Description
engine string "workers" (default, fast) or "containers" (full pip)
envs object Environment variables available to code
timeout_ms number Sandbox lifetime in ms (default: 300000)
metadata object Custom key-value pairs for tracking

Environment Variables

Set environment variables at sandbox creation, override per execution:

# Set at sandbox creation
POST /sandbox
{"envs": {"API_KEY": "secret", "DEBUG": "true"}}

# Override for specific execution
POST /sandbox/abc-123/run
{
  "code": "import os\nprint(os.environ.get('API_KEY'))",
  "envs": {"API_KEY": "override_value"}
}
# Output: override_value

Default variables injected automatically:

Timeout Management

Sandboxes have a configurable lifetime. Extend before expiry to keep them alive:

# Create with custom timeout (10 minutes)
POST /sandbox
{"timeout_ms": 600000}

# Check time remaining
GET /sandbox/abc-123
# Returns: {"time_remaining_ms": 180000, ...}

# Extend timeout
POST /sandbox/abc-123/timeout
{"timeout_ms": 300000}
# Returns: {"expires_at": 1706000300, "time_remaining_ms": 299500}

Timeout Limits by Plan

Plan Max Timeout Default
Trial 5 minutes 5 minutes
Free 1 hour 5 minutes
Pro 24 hours 5 minutes

Port Exposure

Run web servers in your sandbox and get external URLs (containers engine only):

# Run a web server in your sandbox
POST /sandbox/abc-123/run
{"code": "from http.server import HTTPServer, SimpleHTTPRequestHandler\nserver = HTTPServer(('0.0.0.0', 8080), SimpleHTTPRequestHandler)\nserver.serve_forever()"}

# Get external URL for the port
GET /sandbox/abc-123/host?port=8080

# Response
{
  "sandbox_id": "abc-123",
  "port": 8080,
  "url": "https://abc12345-8080.sandbox.cerver.ai",
  "host": "abc12345-8080.sandbox.cerver.ai"
}

Run Code

POST /sandbox/abc-123/run
Authorization: Bearer sk_trial_xxx
Content-Type: application/json

{
  "code": "x = 5\nprint(x * 10)",
  "envs": {"DEBUG": "true"},
  "timeout": 30
}

# Response
{
  "output": "50",
  "error": "",
  "exit_code": 0,
  "duration": 2
}

Streaming Output

Get real-time output via Server-Sent Events:

POST /sandbox/abc-123/run/stream
Authorization: Bearer sk_trial_xxx
Content-Type: application/json

{"code": "import time\nfor i in range(3):\n    print(i)\n    time.sleep(1)"}

# Response (SSE stream)
data: {"type": "stdout", "data": "0\n"}
data: {"type": "stdout", "data": "1\n"}
data: {"type": "stdout", "data": "2\n"}
data: {"type": "exit", "code": 0}

Install Packages

Install pip packages. Auto-upgrades to containers engine if needed:

POST /sandbox/abc-123/install
Authorization: Bearer sk_trial_xxx
Content-Type: application/json

{"packages": "pandas numpy"}

# Response
{"success": true, "upgraded": true}

File Operations

# Write file
POST /sandbox/abc-123/files
{"path": "data.txt", "content": "hello world"}
# Response: {"success": true, "path": "data.txt", "size": 11}

# Read file
GET /sandbox/abc-123/files?path=data.txt
# Response: {"path": "data.txt", "content": "hello world", "size": 11}

# List files
GET /sandbox/abc-123/files
# Response: {"files": [{"path": "data.txt", "size": 11}]}

Access files from code using __sandbox_dir__:

result = sandbox.run("""
with open(__sandbox_dir__ + '/data.txt') as f:
    print(f.read())
""")

Engines

Engine Startup Packages Use Case
workers ~50ms Python stdlib only Fast scripts, simple calculations
containers ~500ms Full pip support pandas, numpy, ML, web servers

Python SDK

pip install cerver

Basic Usage

from cerver import Sandbox

with Sandbox(api_key="sk_trial_xxx") as sandbox:
    result = sandbox.run("print('Hello!')")
    print(result.output)  # Hello!

With Environment Variables

with Sandbox(
    api_key="sk_trial_xxx",
    envs={"API_KEY": "secret"}
) as sandbox:
    result = sandbox.run("""
import os
print(os.environ.get('API_KEY'))
""")
    print(result.output)  # secret

Using Containers

with Sandbox(engine="containers") as sandbox:
    sandbox.install("pandas")
    result = sandbox.run("""
import pandas as pd
df = pd.DataFrame({'a': [1, 2, 3]})
print(df.sum())
""")

AI Agent Integration

Tool Definition

{
  "name": "execute_python",
  "description": "Execute Python code in a secure sandbox",
  "parameters": {
    "type": "object",
    "properties": {
      "code": {"type": "string", "description": "Python code to execute"},
      "envs": {"type": "object", "description": "Environment variables"}
    },
    "required": ["code"]
  }
}

OpenAI Function Calling

from cerver import Sandbox
from openai import OpenAI

client = OpenAI()
sandbox = Sandbox()

tools = [{
    "type": "function",
    "function": {
        "name": "execute_code",
        "description": "Execute Python code in a sandbox",
        "parameters": {
            "type": "object",
            "properties": {
                "code": {"type": "string"}
            }
        }
    }
}]

response = client.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "Calculate factorial of 10"}],
    tools=tools
)

if response.choices[0].message.tool_calls:
    code = response.choices[0].message.tool_calls[0].function.arguments
    result = sandbox.run(code)
    print(result.output)

Anthropic Claude

from cerver import Sandbox
from anthropic import Anthropic

client = Anthropic()
sandbox = Sandbox()

tools = [{
    "name": "execute_code",
    "description": "Execute Python code in a sandbox",
    "input_schema": {
        "type": "object",
        "properties": {
            "code": {"type": "string"}
        }
    }
}]

response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    tools=tools,
    messages=[{"role": "user", "content": "Calculate 2^100"}]
)

for block in response.content:
    if block.type == "tool_use":
        result = sandbox.run(block.input["code"])
        print(result.output)

Rate Limits

Plan Requests/day Sandboxes Port Exposure
Trial (sk_trial_) 100 1 No
Free (sk_live_) 1,000 5 Yes
Pro 100,000 100 Yes

Upgrade your plan for higher limits.

Error Handling

from cerver import Sandbox, CerverError, TimeoutError

try:
    with Sandbox() as sandbox:
        result = sandbox.run("import nonexistent")
        if result.exit_code != 0:
            print(f"Error: {result.error}")
except TimeoutError:
    print("Execution timed out")
except CerverError as e:
    print(f"Cerver error: {e}")

Security

Cerver is built on Cloudflare's infrastructure for security and speed:

Data flow:

User Request
     ↓
API (validates API key)
     ↓
D1 Database (stores users, keys, usage)
     ↓
Sandbox (isolated code execution)

No one can access the database directly. All requests go through the API which validates your API key first. Your code runs in isolated sandboxes that cannot access other users' data.