Skip to main content

HTTP API

Every route needs the session token (cookie, ?token= on the first page load, or Authorization: Bearer) and a localhost Host header. Writes and WebSockets also need an allowed Origin, except /mcp called by a local program with a Bearer token.

RoutePurpose
GET /healthz{"ok":true}; the only route without the token
GET /api/metaname, version, protocol version, data mode
GET /ws/statelive city stream (WebSocket, protocol v3)
GET /ws/terminal/:hostIdinteractive shell (WebSocket)
GET /ws/agentapprovals and the agent panel (WebSocket)
GET/POST/DELETE /mcpMCP endpoint for AI apps
POST /api/hosts, POST /api/hosts/testadd a server, or test a draft
PATCH/DELETE /api/hosts/:idedit or remove a server
POST /api/hosts/import-ssh-configimport from ~/.ssh/config
POST /api/connect/probe, /trust, /installthe Connect a server steps
GET/POST /api/ssh/keys, POST /api/ssh/keys/importlist, create, upload keys
POST /api/resources/testone real poll of a draft; adds a Doctor report when it fails
POST /api/resources{ resource, secrets }: secrets to the vault, the entry to resources.yaml
PATCH/DELETE /api/resources/:idedit (name, district, tags, new credentials) or remove
GET /api/resources/:id/credentialswhich credentials are saved (true/false), never values
GET /api/doctormachine checks and everything in trouble
POST /api/doctor/resource/:idfull Doctor report for a resource
POST /api/doctor/resource/:id/apply{ patch }: re-prove, then save allow-listed settings
POST /api/doctor/host/:idfull Doctor report for a server
GET /api/replay?at=<ms>the city at a past moment
GET /api/history?target=&days=incidents and chart points
GET/PUT /api/settingsretention and thresholds
GET /api/alertsalert channels (secrets never returned) and Web Push devices
POST /api/alerts/channels, PUT/DELETE …/:idadd, edit (empty secrets keep the saved ones) or remove a channel
POST /api/alerts/test{ id } or { input, id? }: test a saved channel or an unsaved form
POST /api/alerts/push, DELETE …/push/:idsubscribe or remove a browser for Web Push
GET /api/threatsattack and exposure findings, worst first, and what each check could read
GET /api/threats/timeline?since=&until=findings active in a time range (time travel)
POST /api/threats/:id/acknowledgemark a finding as expected (a new account, port or login is learned)
POST /api/threats/checkrun every check now (security, expiry, disks, backups, packages, containers)
GET /api/threats/:id/fixes, POST …/:id/fixthe fixes a finding offers; { fixId } applies one (audited)
GET/POST /api/backups, DELETE …/:idbackup checks: list, add or edit, remove
GET /api/containers/:idlatest containers (CPU, memory, restarts) and pods on a server
GET /api/incident?at=&minutes=&target=everything recorded around a moment
POST /api/logs/search{ query, since, regex, sources, hostIds }: search logs on servers
GET/PUT /api/costscloud costs per AWS account; { enabled } turns tracking on or off
POST /api/alerts/push/:id/testsend a test push to one browser
GET /api/runbooks, POST /api/runbooks/runlist runbooks; run one (or a command) on chosen servers
GET /api/audit?limit=audit log, newest first
GET /api/agent/mcp-setupthe Claude Code command and JSON config

The WebSocket protocol is defined with zod in packages/shared/src/protocol.ts.