One FastAPI server (cairn-server, default port 9090) exposes the whole
control plane. Interactive docs ship with it at /docs (OpenAPI at
/openapi.json).
- Auth — enabled iff
OBS_JWT_SECRET is set: POST /token (OAuth2
password form) returns a bearer JWT; a global middleware then guards every
route outside a small public list (/healthz, /token, /auth/status,
API docs, /console assets, signature-verified webhook ingress). Admin
routes additionally need an owner/admin role.
- Workspaces — every route can be addressed per-workspace as
/workspaces/{id}/<path> (or the X-Cairn-Workspace header). Cross-
workspace access to a run 404s.
- Streaming —
GET /runs/{id}/stream is Server-Sent Events (resume with
?after_seq=N); POST /v1/chat/completions streams when stream: true.
| Method | Path | Purpose |
|---|
| GET | /runs | list runs (lane, status, limit) |
| GET | /runs/{id} | full run record incl. provenance + live progress |
| GET | /runs/{id}/events | event-log snapshot (after_seq) |
| GET | /runs/{id}/stream | SSE live event stream |
| GET | /runs/{id}/artifacts · /artifacts/download · /report | what a run produced (file streams; S3 → presigned redirect) |
| POST | /runs/{id}/cancel | cancel |
| GET | /runs/{id}/pilot · POST /runs/{id}/pilot/review | per-run pilot report; record a reviewer scorecard |
| POST | /runs/{id}/evaluate | score stored output against the pack’s eval recipe |
| GET | /runs/{id}/diagnosis | failure labels + eval verdicts + cost drill-down |
| Method | Path | Purpose |
|---|
| GET | /runs/{id}/pending-approval | what a paused run is asking to approve |
| POST | /runs/{id}/resume | {decision, approver, note} — missing decision = 422, not awaiting = 409 |
| POST | /runs/{id}/expire · /approvals/dismiss | dismiss one / bulk-dismiss stale gates |
| GET | /triggers/approve/{workflow_id} | Slack/email magic-link approval callback (action saga) |
| Method | Path | Purpose |
|---|
| POST | /pipelines/run | {bundle_path, pipeline_name, inputs, environment} → {pipeline_id} |
| GET | /pipelines · /pipelines/{id} · /{id}/config | list / detail / composed step config |
| POST | /pipelines/{id}/steps/{step}/advance · /approve · /pipelines/{id}/cancel | drive gated steps; cancel |
| Method | Path | Purpose |
|---|
| GET | /packs | registered templates |
| GET | /packs/{pack}/{tpl}/contract | the UI contract: schemas, plan, steps, integrations |
| POST | /packs/{pack}/{tpl}/run | run a template (profile, config_preset, sandbox) |
| POST | /packs/{pack}/{tpl}/validate · /preflight | validate form values; the side-effect-free ready/blocked verdict |
| GET | /packs/{pack}/{tpl}/graph · /eligibility · /metric-contract · /slack-modal | compiled graph (Mermaid + JSON); Playground eligibility; metric contract; Slack modal view |
| Method | Path | Purpose |
|---|
| POST | /triggers/alert · /pattern · /manual | webhook ingress (manual supports wait) |
| GET/POST | /triggers/scheduled | list / create cron schedules (validated; can pin a config_preset) |
| PATCH/DELETE | /triggers/scheduled/{id} | pause/resume / delete |
| GET/POST | /triggers/inbox · /inbox/replay | durable trigger inbox (opt-in OBS_TRIGGER_DURABLE) |
| (dynamic) | pack-declared ingress paths | signature-verified per-pack webhook receivers |
| Method | Path | Purpose |
|---|
| POST | /ask | the read-only ReAct agent — {query, thread_id?} → grounded answer + optional run-form action |
| GET | /ask/thread/{id} | load a prior (account-scoped) conversation |
GET /insights/{failures,cost,health,summary,workflow,workflow/runs,workflow/report,workflow/clusters} — dashboard aggregates over the run store and eval ledger.
GET /suggestions, GET /suggestions/{id}, POST /suggestions/{id}/{accept|reject} — the governed improvement queue.
POST /playground/{upload,profile,materialize,adopt-threshold}, GET /playground/{metric-history,upload/{id}} — sandbox dataset upload/profiling and gate what-if.
GET /registry/catalog · installed-workflows · installs; POST /registry/{install,uninstall,enable,disable,sync-workflows} — pack distribution and per-workspace enablement.
GET/POST /workspaces, PATCH/DELETE /workspaces/{id} — tenancy lifecycle (archive is soft, default protected).
POST /admin/users, POST /admin/users/{id}/password, GET /admin/users — admin-invite user management (no public signup).
GET /healthz · /auth/status · /auth/me, POST /token — health and auth.
The console’s data plane lives under two prefixes:
/console/api/* — operators, per-workflow config surface and values
(PUT rejects governance knobs), config presets and input presets
(CRUD, set-default, rename), model registry, policies, gateway summary,
audit log (X-Total-Count paging), remote jobs, and the single-shot plan
resolver POST /console/api/ask. Responses served from stub data carry an
X-Cairn-Stub: true header.
/ui/api/* — profiles/environments (list, edit, form-based editing,
policy/knowledge attach-lists, backends), knowledge corpora (register,
index, query), model roles + catalog, console-authored triggers and
policies (YAML CRUD), and account-scoped connections (create, update,
test-before-save health probe, MCP tool discovery, OAuth start).
GET /oauth/callback completes broker-based OAuth connections.
POST /v1/chat/completions — OpenAI-compatible (+ SSE streaming); GET /v1/models.
/mcp — an opt-in (OBS_OPS_MCP=1), reads-first MCP mount that
auto-derives tools from the API’s read routes; every mutation, stream, and
download is excluded fail-closed. Off by default.