SPB Git

Repository Public

api.md 5.2 KB

# 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:

text
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/v1 prefix; the shared package is at version 0.1.0.
  • apps/web/dev/mock-server.mjs is a test double for the Playwright suite; it is not a reference implementation of this API.
Files main
Menu

Theme