HTTP API reference
Authenticated broker routes under /v1/*. Interface version: 2026-07-23 (CURRENT_INTERFACE_VERSION / TypeScript INTERFACE_VERSION).
Unauthenticated: GET /healthz → { "ok": true }.
There is no /runtime route. Use GET /v1/runtime.
Shared headers for every /v1/* call: Authentication.
Routes
| Method | Path | Purpose | Required capability |
|---|---|---|---|
| GET | /v1/runtime | Runtime info | session:read |
| GET | /v1/sessions | List sessions | session:read |
| POST | /v1/sessions | Create session | session:write |
| POST | /v1/pages | Open page | page:write |
| POST | /v1/commands | Submit command envelope | browser:mutate (+ nested caps for upload / download / JS / intents) |
| POST | /v1/checkpoints | Persist workflow checkpoint | recovery:write |
| POST | /v1/recovery/{workflow} | Recover workflow | recovery:write |
| GET | /v1/events | Read events (after, limit query) | session:read |
| GET | /v1/artifacts/{id} | Read artifact bytes | artifact:read |
| POST | /v1/principals | Issue scoped bearer | authority:admin |
| DELETE | /v1/principals/{principal} | Revoke principal | authority:admin |
MCP streamable HTTP is also mounted at POST /v1/mcp — see MCP over HTTP and MCP tools.
Request bodies (high level)
Shapes use camelCase JSON. Do not invent fields; follow the TypeScript SDK validators / Rust types.
- POST `/v1/sessions` —
{ profile, proxy, executionPolicy? }where
executionPolicy defaults to { javascriptEvaluation: false, visionAssist: false }
- POST `/v1/pages` —
{ session_id }(snake_case on this request; session/page state also usesid/session_id/page_ids) - POST `/v1/commands` —
CommandEnvelope(schemaVersion: 2, ids,deadline,
command where command is { kind: "primitive"|"intent", input: … })
- POST `/v1/checkpoints` — checkpoint request with verified evidence (see SDK
CheckpointRequest) - POST `/v1/principals` —
{ principalId, capabilities, expiresAt }→201with one-timebearer - GET `/v1/events` — query
after(cursor) andlimit(bounded; SDK max 256)
Nested command kinds include primitives (navigate, click, …) and { kind: "intent", input: … }. Intents additionally need intent:execute.
Status and errors
Successful JSON responses are typically 200. Principal issuance returns 201. Revocation returns 204.
Failures return JSON { "error": { … } } where error is an InterfaceError:
code (camelCase) | Typical HTTP |
|---|---|
authenticationFailed / tokenExpired | 401 |
missingCapability / malformedScope | 403 |
artifactDenied / notFound | 404 |
deadlineExceeded | 408 |
idempotencyConflict / reconciliation | 409 |
resourceExhausted | 429 |
invalidRequest | 422 (or 413 when oversized) |
unsupportedInterfaceVersion | 422 |
internal | 500 |
Command outcomes may map to 200 / 403 / 409 / 429 / 503 depending on CommandOutcome.status — the TypeScript client checks status against the body.
Clients
- Typed client: TypeScript SDK
- Tutorial: First browser session
- Headers and mint curl: Authentication