API
The browser API is private: it exists for the bundled web application and for the single administrator. The reference is generated by the running server:
GET /api/v1/openapi.json (authenticated; OpenAPI 3.1)That document is assembled from the live route table and the zod schemas attached to each route
(apps/server/src/modules/openapi.ts), so it cannot drift from what is registered. Each operation carries
x-auth (public | preauth | restricted | full) and x-websocket. The human-readable endpoint
table is in CONTRACT.md ("Browser API"); request and response types are in
packages/shared/src/dto.ts and wire.ts.
This page only states the conventions.
Conventions
| Topic | Rule |
|---|---|
| Base path | /api/v1; JSON in and out; timestamps are ISO-8601 strings |
| Authentication | session cookie __Host-cr_sid (HttpOnly, Secure, SameSite=Strict). See authentication.md |
Mutations (POST, PUT, PATCH, DELETE) |
header X-CSRF-Token (from GET /auth/status) and Origin equal to the public origin |
| WebSocket upgrades | cookie + completed second factor + matching Origin; a refused upgrade is a plain HTTP error (401, 403, 404, 410), never a socket |
| Errors | {"error": {"code": string, "message": string, "details"?: any}} with a meaningful HTTP status |
| Validation | every body, query and path parameter is zod-validated; failure = 400 invalid_request with details: [{path, message}] |
| Caching | every /api/ response is Cache-Control: no-store |
| Paths | file paths are relative to the project root ("" = root); absolute host paths are never exposed, .. is refused |
| Limits | JSON body 6 MiB; file read 2 MiB (text only); file write 5 MiB; upload 200 MiB (raw body); WebSocket frame 1 MiB |
| Rate limits | per minute: credential endpoints 20 per IP; anonymous GET /auth/status 240 per IP; GET /health 600 per IP; everything else 600 per session. Excess = 429 rate_limited |
Common error codes: unauthenticated (401), second_factor_required, bad_origin, bad_csrf (403),
not_found (404), conflict, exists, invalid_state (409), payload_too_large (413), binary (415),
locked, rate_limited, too_many_sessions (429), not_implemented (501), runtime_error (502),
runtime_unavailable (503).
Areas
| Area | Paths | Notes |
|---|---|---|
| Health | GET /health |
the only public route; returns {ok, version} |
| Auth | /auth/* |
setup, login, TOTP, passkeys, devices, password, logout |
| Projects | /projects, /projects/:id, /workspace/roots |
DELETE unregisters only; files are never deleted |
| Sessions | /sessions, /sessions/:id, …/terminate, …/reconnect, …/snapshot, /projects/:id/conversations |
Claude arguments are derived from resumeConversationId / continueLast only |
| Files | /projects/:id/files, …/file, …/fs, …/upload, …/download, …/search, …/git/status, …/git/diff |
write uses baseSha256 for optimistic concurrency (409 conflict with the on-disk sha256) |
| Tasks | /tasks, /tasks/:id, …/cancel, …/retry, …/log, …/artifacts/:artifactId |
host = local or an allow-listed alias; retry only when idempotent |
| Cluster | /cluster/nodes, /cluster/nodes/:id, /cluster/metrics, /cluster/models, /cluster/models/:id/test |
read-only telemetry |
| Skills / MCP | /skills, /skills/op, /skills/registry/search, /mcp, /mcp/:name, /mcp/:name/test |
MCP env and header values are write-only |
| System | /system/status, /system/audit |
component health with per-check timestamps; audit paginated with before |
| Misc | /notifications, /notifications/read, /settings, /openapi.json |
WebSockets
| Path | Frames |
|---|---|
/sessions/:id/stream?cols=&rows= |
binary = raw PTY bytes both ways; text = JSON control messages (resize, ping from the client; ready, pong, exit, error from the server) |
/tasks/:id/log/stream |
binary log bytes, server to client only; closes when the task has ended and the log is drained |
/events |
text JSON ServerEvent: hello, session.updated, session.removed, task.updated, notification, auth.expired |
Application close codes: 4401 unauthorized, 4403 forbidden, 4404 not found, 4410 session ended, 4429 backpressure, 4503 runtime unavailable.
Runtime IPC (internal)
The runtime's HTTP/WebSocket interface on the unix socket is not a public API. It is specified in
CONTRACT.md ("Runtime IPC") and typed in packages/shared/src/wire.ts. Only
apps/server holds its token.
Limitations / not verified
- There is no API token or service-account mechanism: the API can only be used with a browser session cookie. It is not designed for third-party clients.
- The OpenAPI document describes request and response schemas only for routes that declare them; streaming endpoints (upload, download, logs) and WebSockets are listed without body schemas.
- No versioning policy beyond the
/api/v1prefix; the shared package is at version 0.1.0. apps/web/dev/mock-server.mjsis a test double for the Playwright suite; it is not a reference implementation of this API.