Base URL is this site. Authenticate with Authorization: Bearer csk_…. JSON in, JSON out.
| Method | Path | What it does |
|---|---|---|
| GET | /v1/templates | Templates you can use |
| POST | /v1/sandboxes | Create. Body {template, ttlSeconds, idleTimeoutSeconds, metadata}. Returns once running. Send Idempotency-Key to make retries safe. |
| GET | /v1/sandboxes, /v1/sandboxes/{id} | List live sandboxes, or one |
| DELETE | /v1/sandboxes/{id} | Destroy now |
| POST | /v1/sandboxes/{id}/exec | {cmd, args, shell, cwd, env, timeoutSeconds, stdin} → {exitCode, stdout, stderr, durationMs, timedOut, generation} |
| PUT | /v1/sandboxes/{id}/files?path=/work/x | Upload the request body |
| GET | /v1/sandboxes/{id}/files?path=/work/x | Download; add &list=1 to list a directory |
| GET | /v1/usage | Sandbox-seconds and concurrency against your limits |
| GET | /v1/audit | Your audit trail |
429 with the limit named.generation increases if the sandbox was replaced underneath you; files in /work are gone when it does./work or /tmp. Network egress from a sandbox is closed in the trial.import os, requests
API = "https://caisson.rajendrag.com"; H = {"Authorization": f"Bearer {os.environ['CAISSON_API_KEY']}"}
sb = requests.post(f"{API}/v1/sandboxes", json={"ttlSeconds": 600}, headers=H).json()
r = requests.post(f"{API}/v1/sandboxes/{sb['id']}/exec", headers=H,
json={"cmd": "python3", "args": ["-c", "import pandas; print(pandas.__version__)"]}).json()
print(r["exitCode"], r["stdout"])
requests.delete(f"{API}/v1/sandboxes/{sb['id']}", headers=H)