REST
The REST endpoints on api.parallelsandbox.com and log.parallelsandbox.com, for apps, scripts and what agents have no tool for, such as fresh URLs for a box's screenshots and recordings.
For the web and desktop apps, for anything that is not an agent, and for what agents have no MCP tool for, such as fresh URLs for a box's screenshots and recordings (GET /v1/boxes/{id}/media). Same credential, Authorization: Bearer <token>, where the token is an account's psbx_ API key or a connected client's OAuth access token (one hour; where keys come from), on https://api.parallelsandbox.com unless noted.
| Endpoint | Purpose |
|---|---|
/v1/auth/github |
GitHub login |
/v1/keys |
create, list and revoke API keys; from the app's signed-in session only (an API key or OAuth token cannot manage keys); POST makes a key for tools without OAuth, and keys made by OAuth sign-in are not listed |
/v1/boxes |
list (newest started first, 200 at most; ?all=1 adds stopped boxes), start (goal is optional here), inspect and stop boxes; the list carries sceneUrl, webUrl, each web service's url, goal, agent, screenInUse, screenActive and posterUrl (Which conversation is using a box). A stopped box still carries its newest posterUrl but no review: stopping a box closes its card, and the card's picture can no longer be had |
PUT /v1/boxes/{id}/orientation |
set this ready box's AI screen to portrait or landscape; requires a box image with screen-orientation and returns its new orientation |
POST /v1/boxes/{id}/review/done |
mark the box's waiting sandbox_review card done, as the app does; GET /v1/boxes shows the waiting card as review |
POST /v1/boxes/{id}/wake |
wake a frozen box (counts as use; 402 when the account has no credits); returns the box's status |
GET /v1/boxes/{id}/media |
the box's steps taken in the last 7 days that have pictures (recorded with sandbox_exec, taken or recorded with sandbox_shot), the newest 200 at most, oldest first, for a stopped box too: {"keepDays": 7, "steps": [...]}. Each step has the fields of sandbox_status steps[] (at, kind, summary and ok, and target, note, actor, detail, ms, exitCode, signal, timedOut and error when they apply), plus media[], each with kind (video or image), url and bytes, and durationSec for a video; the URLs are signed again on each call and valid for at least an hour |
DELETE /v1/boxes/{id}/media |
deletes the box's stored screenshots, recordings (including the ones recorded with each step), frozen poster and review card picture; works on running and stopped boxes. Returns {"ok":true,"deleted":N,"bytes":B}; the activity record stays, and GET /v1/boxes/{id}/media then returns empty steps. Another account's box gets 404; if deleting fails partway it returns 502, and calling again deletes the rest |
DELETE /v1/boxes/{id}/events |
deletes the box's activity record: the steps on its timeline in the app (with the notes and commands a person can see there), steps[] in sandbox_status, and the screenshots and recordings taken with those steps. Use it before handing a box to someone who should not see how you got there, such as a reviewer who reads another language. Returns {"ok":true,"deleted":N,"mediaDeleted":M}; steps from later calls are recorded as usual. Only the account can call it, not a review link; another account's box gets 404 |
DELETE /v1/build-cache |
deletes the account's whole sandbox_build cache and returns {"ok":true,"deleted":N,"bytes":B}; the next sandbox_build with the same fingerprint builds again (reused: false). If deleting fails partway it returns 502; call again |
POST /v1/agents/{id}/heartbeat |
the conversation {id} (its X-Psbx-Agent) is still open; body {"client": "<MCP client name>"}, every 60 seconds; returns {"ok":true} |
POST /v1/agents/{id}/leave |
the conversation {id} has closed: the boxes it used last show as AI stopped unless they wait for the person; returns {"ok":true} |
POST /v1/boxes/{id}/exec |
run a command as the person, what the app's command box uses: {"cmd", "cwd", "env", "timeoutSec", "background", "note"}, returning sandbox_exec's fields and "actor": "human". It runs even while the box is taken over, is not recorded (no screenshot or video), and its step in steps[] and the app has actor: human. It is not how an AI's step is made: to test what an agent's call records, call sandbox_exec over MCP |
GET /v1/files/{token} |
the download links that sandbox_get, sandbox_shot and sandbox_exec's outputUrl return: no key needed (the link itself is the permission, valid 1 hour), it redirects (302) to a storage URL valid a few minutes |
/v1/boxes/{id}/sync |
upload a tar.gz into a box (what the adapter's sandbox_sync uses) |
/v1/boxes/{id}/screencast |
live screen, WebSocket |
/v1/boxes/{id}/input |
mouse and keyboard input |
/v1/takeovers |
pending takeover requests, each with takeoverUrl, its token and appLink (parallelsandbox://box/<id>?t=<token>) |
/v1/takeovers/{id}/return |
hand a box back with a note |
GET, PUT /v1/box-access |
the IP allowlist for box URLs: { "allowedIps": [...] }, [] turns it off (other facts) |
GET /v1/secrets, PUT /v1/secrets/{name}, DELETE /v1/secrets/{name} |
manage secrets; a person can also add, replace and delete them at app.parallelsandbox.com under Settings → Secrets |
/v1/versions |
published versions. DELETE /v1/versions/{id} removes a version record, and also deletes its image from the registry when no other version of the account uses the same image tag: {"ok":true,"imageDeleted":true}; when the image stays, imageDeleted is false with a reason (for example image is still used by 1 other version(s): billing/v2). If the registry cannot delete it, it returns 502 and keeps the version record, so you can retry |
/v1/environments |
environments, connections (connector tokens), private addresses, service settings (uploaded .env or imported from AWS ECS); every endpoint is in Environments |
/v1/aws |
the read-only AWS role used for imports; /v1/aws/ecs/services lists ECS services |
/v1/connector |
WebSocket the connector connects to, with its connection token |
GET /v1/usage, GET /v1/usage/events |
usage totals by kind, and usage events (since, until, box_id, limit) |
GET /v1/credits |
balance, buckets, plan, and during the 24 hours after credits ran out boxesKeptUntil |
GET /v1/billing/catalog |
plans and credit packs (no key needed) |
/v1/billing/checkout, /v1/billing/portal |
Stripe Checkout and customer portal |
/v1/billing/webhook |
Stripe webhook |
POST /v1/projects (log.parallelsandbox.com) |
create a log project; returns its write key once |
GET, PATCH, DELETE /v1/projects/{id} (log.parallelsandbox.com) |
inspect a log project, change its allowed origins, delete it |
POST /v1/projects/{id}/write-key (log.parallelsandbox.com) |
replace the write key; the old one stops working at once |
/v1/projects/{id}/sourcemaps (log.parallelsandbox.com) |
upload and list source maps |
Every tool and topic is listed in the tool reference.
API keys
Tools without OAuth can use a psbx_ API key. The AI creates one with a name using POST /v1/keys and the app’s signed-in session; the key is shown only once. GET /v1/keys lists keys and DELETE /v1/keys/{id} revokes one. API keys and OAuth access tokens cannot manage keys. Normal installation uses the OAuth adapter and needs no manually created key.