Public
No credential at all. The right first call when you are checking connectivity.
| Method | Path | Auth | What | Returns |
|---|
| GET | /api/health | public | Liveness and which channels of the runtime contract are open. | {ok, service, version, channels}. channels says which parts of the runtime contract are open. |
| GET | /api/surface | public | This surface, as JSON, the machine-readable twin of ARCHITECTURE.md. What the deployed worker actually speaks. | The whole surface as JSON: {service, version, roles, notes, tools[], http[]}. |
| GET | /llms.txt | public | Agent-readable index of the public docs (llms.txt convention). | text/markdown. The agent index of these docs. |
| POST | /api/access | public | Ask for access. Body: {email, note?} as JSON or as a plain form post. A repeat address updates the note rather than adding a row. | {ok} or {ok, already:true}. A form post redirects back to the landing with ?access=thanks or ?access=error. |
Your knowledge
Getting a company file in, and reading it back out.
| Method | Path | Auth | What | Returns |
|---|
| POST | /api/projection | bearer | Push a projection of a company file. Body: {tenant?, commit?, mode: replace|merge, nodes: [{path, content}]}. Replace mode deletes ONLY the pushing tenant's rows. | {ok, tenant, built_at, ingested, total, findings[], vectors{embedded_nodes, chunks, errors[]}}. findings reports frontmatter lines the profile does not accept rather than dropping them. |
| GET | /api/nodes | bearer | List projected nodes. Query: tenant?, kind?, limit?. Includes projection freshness and kind counts. | {tenant, projection{built_at, commit_sha, node_count, source}, kinds[{kind, n}], nodes[]}. Default limit 200, maximum 500, clamped silently. |
Runs
Opening a run before real work, keeping it alive, and closing it.
| Method | Path | Auth | What | Returns |
|---|
| GET | /api/runs | bearer | Open and recent runs. Query: tenant?. | {open[], recent[]}. Open runs carry a derived stale flag. Capped at 40 open and 12 recent, with no limit parameter and no paging. |
| POST | /api/runs | bearer | Open a run. Body: {tenant?, task, actor_label, harness?, process?, doing?, scopes?}. | {ok, run_id, started_at}. Carry the run_id through heartbeat, events and finish. |
| POST | /api/runs/:id/heartbeat | bearer | Report a run alive; update doing/scopes. | {ok, run_id, heartbeat_at}, or 404 {error} when no open run has that id. |
| POST | /api/runs/:id/finish | bearer | Close a run with a terminal status. | {ok, run_id, status} with the terminal status that was recorded. |
Events
The operational feed the whole team reads.
| Method | Path | Auth | What | Returns |
|---|
| GET | /api/events | bearer | Recent events. Query: tenant?, limit?. | {tenant, events[]}, newest first. Default limit 50, maximum 200, clamped silently. |
| POST | /api/events | bearer | Record an operational event. Body: {tenant?, type, title, detail?, amount?, needs_you?, actor?, run_id?}. | {ok, ts, type} with the timestamp the event was recorded at. |
Decisions
Raising a question, and finding out what was answered.
| Method | Path | Auth | What | Returns |
|---|
| POST | /api/asks | bearer | Create a decision link. Body: {tenant?, ask, becomes, because?, cost?, diff?, branch?, base_sha?, run_id?, pr_number?, repo?}. | {ok, key, url}. The URL is the decision page, and holding it is what confers the right to answer. |
| GET | /api/asks | bearer | Rulings given that nothing has carried out yet (the lander's poll). | {asks[]}: rulings given but not yet carried out. This is the lander's poll, a lander being a machine that holds your git credential. |
| GET | /api/asks/:key | bearer | One ask's status and ruling, what the founder answered. | {key, status, ruling, ruled_at, ask, branch}. ruling is the answer in the founder's own words. |
| POST | /api/asks/:key/done | bearer | Mark a ruling carried out (the lander merged/closed the PR). | {ok}. Marks a ruling carried out so the poll stops returning it. |
Members
Inviting people and taking access away. The founder's own surface.
| Method | Path | Auth | What | Returns |
|---|
| GET | /api/members | bearer | List members and invite codes (the Founder's own surface). | {members[]} with tenant, slug, name, role, status and invite code. |
| POST | /api/members | bearer | Invite a member. Body: {tenant?, name, role: founder|steward|observer, charter?}. | {ok, tenant, slug, name, role, invite_code}. The invite code is shown once, here. |
| POST | /api/members/:slug/revoke | bearer | Revoke a member. Stops new authorizations; never touches the repository. | {ok, slug}. Stops new authorizations. It never touches the repository. |
The mount and the ruling link
Reachable by people rather than by token.
| Method | Path | Auth | What | Returns |
|---|
| GET | /d/:key | link | The decision page: one question, evidence attached, yes or no. Holding the link is holding the right to rule. | An HTML page rather than JSON: one question, the evidence, and two buttons. |
| GET | /mcp | oauth | The MCP mount (streamable HTTP). OAuth via personal invite code; the founder's machine bearer also works. | The MCP streamable HTTP transport. Unauthenticated requests answer 401 with a WWW-Authenticate header pointing at the OAuth metadata. |
Everything else
| Method | Path | Auth | What | Returns |
|---|
| GET | /api/access | bearer | The access requests waiting on you, newest first. The founder's own surface. | {requests[]} with created_at, email, note, source and status. |
Every organization is a tenant. Every projected node, run, event, ask and member row carries a tenant slug, every read is scoped by it, and a replace-mode projection push can only ever delete its own tenant's rows. The product's own org is tenant 'hq' in the same database, tenant #2 is the vendor.