API reference

The documented, standardized API — every named route in api_routes with its method, declared params and a response shape derived from its SQL, plus the generic ?api=<table> CRUD layer and the admin denylist. Rendered through the <<<ApiReference>>> tag.

The data-driven API surface — 62 named routes, each a row in api_routes. Call one as ?route=<name>: it runs that row's parameterized SQL with your declared :params bound. A SELECT route replies {"route":…,"rows":[…]}; a write route replies {"route":…,"affected":n,"rowid":id}. auth is public for reads, token/admin for writes.

Tickets

routemethodauthparamsresponse shapemeta
binding.listGETpublic{"ticket_id":"int"}{"route":"binding.list","rows":["clause_seq", "guarantee_label"]}list a ticket's declared guarantee-label -> clause bindings
binding.recordPOSTtoken{"ticket_id":"int","clause_seq":"int","guarantee_label":"str","digest":"str"}{"route":"binding.record","affected":<n>,"rowid":<id>}declare that a shadow guarantee label satisfies a mandate clause (applied by crankd at harvest)
guarantee.heldGETpublic{"component":"str"}{"route":"guarantee.held","rows":["guarantee"]}every guarantee label a component has recorded — the contract crankd will not let a crank erode
guarantee.listGETpublic{"ticket_id":"int"}{"route":"guarantee.list","rows":["version", "shadow", "guarantee", "clause_seq"]}list a ticket's harvested guarantees and the clauses they bind to
guarantee.recordPOSTtoken{"ticket_id":"int","version":"str","shadow":"str","guarantee":"str","clause_seq":"int","digest":"str"}{"route":"guarantee.record","affected":<n>,"rowid":<id>}record one harvested shadow guarantee, attributed to a ticket and bound to a mandate clause
mandate.listGETpublic{"ticket_id":"int"}{"route":"mandate.list","rows":["seq", "clause", "digest"]}list a ticket's mandate clauses in order
mandate.recordPOSTtoken{"ticket_id":"int","seq":"int","clause":"str","digest":"str"}{"route":"mandate.record","affected":<n>,"rowid":<id>}record one falsifiable clause of a ticket's mandate
ticket.approvalGETpublic{"component":"str"}{"route":"ticket.approval","rows":["id", "component", "title", "body", "patch", "status", "approval_sig"]}the latest ticket for a component (content + patch + approval_sig) for crankd to verify + apply
ticket.approvePOSTtoken{"id":"int","approval_sig":"str"}{"route":"ticket.approve","affected":<n>,"rowid":<id>}attach a wallet signature over the ticket content digest -- the external approval the agent cannot forge
ticket.assignPOSTtoken{"ticket_id":"int","agent_id":"str","role":"str"}{"route":"ticket.assign","affected":<n>,"rowid":<id>}authorize a REGISTERED agent on a ticket in a role (idempotent: re-assign is a no-op, never an error)
ticket.createPOSTtoken{"component":"str","title":"str","severity":"str","body":"str","patch":"str"}{"route":"ticket.create","affected":<n>,"rowid":<id>}file a crank ticket with its change (patch); status REQUESTED, approval is a separate wallet signature
ticket.crewGETpublic{"ticket_id":"int"}{"route":"ticket.crew","rows":["ts", "agent_id", "role", "status"]}the agents authorized on a ticket, with roles
ticket.journalGETpublic{"ticket_id":"int"}{"route":"ticket.journal","rows":["ts", "agent_id", "event", "status", "note", "steps_remaining"]}the full append-only journal for a ticket (status changes + progress reports)
ticket.kindPOSTtoken{"kind":"str","id":"int"}{"route":"ticket.kind","affected":<n>,"rowid":<id>}classify a ticket (set-once: the identity trigger refuses re-kinding; must exist in ticket_kinds)
ticket.lessonPOSTtoken{"ticket_id":"int","agent_id":"str","note":"str"}{"route":"ticket.lesson","affected":<n>,"rowid":<id>}harvest a settled ticket: append the distilled lesson (attributed; append-only like all events)
ticket.manifestGETpublic{"ticket_id":"int"}{"route":"ticket.manifest","rows":["uid", "ts", "kind", "ref", "note"]}the ticket as a descriptive manifest: every UID'd item it authorized
ticket.progressPOSTtoken{"ticket_id":"int","agent_id":"str","note":"str","steps_remaining":"int"}{"route":"ticket.progress","affected":<n>,"rowid":<id>}append an attributed progress report (+ steps until the goal); the journal never edits
ticket.queueGETpublic{}{"route":"ticket.queue","rows":["id", "kind", "status", "component", "title", "body"]}the dispatch queue: open/requested tickets, oldest first (brake state checked per-ticket via ticket.stops)
ticket.stopsGETpublic{"ticket_id":"int"}{"route":"ticket.stops","rows":["active_stops"]}active (unreleased) stop tickets aimed at this ticket or any ancestor — >0 means HALT

Provenance

routemethodauthparamsresponse shapemeta
agent.promptGETpublic{"agent_id":"str"}{"route":"agent.prompt","rows":["agent_id", "parent", "tools", "status", "ts", "prompt"]}one agent's full birth prompt + registration record
agent.registerPOSTtoken{"agent_id":"str","parent":"str","prompt":"str","tools":"str"}{"route":"agent.register","affected":<n>,"rowid":<id>}record an agent spawn: id + parent + prompt() + tools()
agent.rosterGETpublic{"n":"int"}{"route":"agent.roster","rows":["agent_id", "parent", "status", "ts", "prompt"]}registered agents, newest first (LIMIT :n; omit n for all)
agent.trailGETpublic{"agent_id":"str"}{"route":"agent.trail","rows":["ts", "tool", "intent", "note"]}the propagation trail for an agent id (tool + intent events, in order)
artifact.listGETpublic{"ticket_id":"int"}{"route":"artifact.list","rows":["name", "version", "forge_sha", "kind"]}list the forge artifacts a ticket produced
artifact.recordPOSTtoken{"ticket_id":"int","name":"str","version":"str","forge_sha":"str","kind":"str"}{"route":"artifact.record","affected":<n>,"rowid":<id>}reference a forge artifact (name:version + sha) a crank produced, against its ticket
children.listGETpublic{"parent_id":"int"}{"route":"children.list","rows":["child_id", "kind", "title", "status", "component"]}list a ticket's child tickets (the owned tree)
edge.recordPOSTtoken{"parent_id":"int","child_id":"int","kind":"str"}{"route":"edge.record","affected":<n>,"rowid":<id>}record a parent->child ticket edge (the owned tree)
journey.listGETpublic{"ticket_id":"int"}{"route":"journey.list","rows":["kind", "text", "ts"]}list a ticket's journey (blunders and successes, in order)
journey.recordPOSTtoken{"ticket_id":"int","kind":"str","text":"str"}{"route":"journey.record","affected":<n>,"rowid":<id>}append a journey event (success/blunder/pivot/note) to a ticket's history
policy.activeGETpublic{"component":"str"}{"route":"policy.active","rows":["id", "component", "max_version", "expires", "sig"]}the newest standing policy for a component (for crankd to verify + apply bounds)
policy.createPOSTtoken{"component":"str","max_version":"str","expires":"int","sig":"str"}{"route":"policy.create","affected":<n>,"rowid":<id>}file a wallet-signed standing crank policy for a component (scope: max_version, expiry)
run.getGETpublic{"digest":"str"}{"route":"run.get","rows":["id", "ts", "component", "version", "ticket_id", "authorized_by", "ok", "shadow_output", "digest"]}fetch crank run(s) by the content address of their shadow output
run.recentGETpublic{"component":"str","n":"int"}{"route":"run.recent","rows":["id", "ts", "version", "ticket_id", "authorized_by", "ok", "digest"]}list a component's recent crank runs (metadata; use run.get for the full output)
run.recordPOSTtoken{"component":"str","version":"str","ticket_id":"int","authorized_by":"str","ok":"int","shadow_output":"str","digest":"str"}{"route":"run.record","affected":<n>,"rowid":<id>}persist a crank run with its full shadow output (content-addressed by sha256(shadow_output))

Repos & Docs

routemethodauthparamsresponse shapemeta
doc.listGETpublic{"repo":"str"}{"route":"doc.list","rows":["path", "kind"]}list a repo's documentation files
doc.readGETpublic{"repo":"str","path":"str"}{"route":"doc.read","rows":["body", "kind"]}read one repo documentation file body
doc.recordPOSTtoken{"repo":"str","path":"str","kind":"str","body":"str"}{"route":"doc.record","affected":<n>,"rowid":<id>}ingest a repo documentation file
doc.reposGETpublic{}{"route":"doc.repos","rows":["repo"]}list repos that have ingested documentation
repo.listGETpublic{}{"route":"repo.list","rows":["name", "forge_remote", "head_commit"]}list the registered repos
source.commitsGETpublic{"repo":"str"}{"route":"source.commits","rows":["commit_sha", "ts", "is_current", "forge_remote"]}list a repo's source commits, newest first
source.recordPOSTtoken{"repo":"str","commit_sha":"str","is_current":"int","forge_remote":"str"}{"route":"source.record","affected":<n>,"rowid":<id>}record a source commit for a repo

Process / Other

routemethodauthparamsresponse shapemeta
authorize_processPOSTtoken{"name":"str","body":"str","meta":"str"}{"route":"authorize_process","affected":<n>,"rowid":<id>}
bug.listGETpublic{"source":"str","severity":"str"}{"route":"bug.list","rows":["*"]}list bugs, optionally scoped by source and/or severity, ordered by severity
bug.recordPOSTtoken{"bug_id":"str","source":"str","title":"str","severity":"str","location":"str","repro":"str","success":"str","fanout":"int","repos":"int","status":"str","pattern":"str","meta":"str"}{"route":"bug.record","affected":<n>,"rowid":<id>}upsert one bug (congruency curated repro or corpus consistent-bug pattern), keyed (source, bug_id)
bug.statsGETpublic{}{"route":"bug.stats","rows":["facet", "value", "n"]}bug counts grouped by severity and by source
error.recentGETpublic{}{"route":"error.recent","rows":["id", "ts", "type", "message", "file", "line", "route", "sig"]}recent fatal-monitor error_log rows, newest first
error.statsGETpublic{}{"route":"error.stats","rows":["sig", "n", "last_ts", "message"]}fatal counts grouped by signature
job.getGETpublic{"hash":"str"}{"route":"job.get","rows":["hash", "ts", "spec"]}fetch a content-addressed crank job by hash
job.putPOSTtoken{"hash":"str","spec":"str"}{"route":"job.put","affected":<n>,"rowid":<id>}store a content-addressed crank job (hash = sha256 of the canonical spec)
kind.rosterGETpublic{}{"route":"kind.roster","rows":["kind", "pattern", "worker_role", "adversary_role", "purpose"]}the ticket kinds: pair (adversarial network) vs solo, with role names
lessons.recentGETpublic{"n":"int"}{"route":"lessons.recent","rows":["ticket_id", "ts", "agent_id", "note"]}harvested lessons across all tickets, newest first (LIMIT :n; omit n for all) — playbook input
lifecycle.stepsGETpublic{"kind":"str","version":"int"}{"route":"lifecycle.steps","rows":["seq", "step"]}the enumerable lifecycle steps for a kind (versioned; steps-remaining counts down these)
process_statusPOSTtoken{"status":"str","id":"int"}{"route":"process_status","affected":<n>,"rowid":<id>}
processes.runningGETpublic{}{"route":"processes.running","rows":["id", "component", "status", "updated"]}
search.facetsGETpublic{}{"route":"search.facets","rows":["facet", "value"]}distinct repo + kind facet values for the multi-axis search form
search.recordPOSTtoken{"repo":"str","path":"str","chunk_seq":"int","section":"str","text":"str","dim":"int","model":"str","vector":"str"}{"route":"search.record","affected":<n>,"rowid":<id>}ingest one L2-normalized doc-chunk embedding into the vector store
search.statsGETpublic{}{"route":"search.stats","rows":["model", "chunks", "docs"]}vector-store coverage: chunk + doc counts per embedding model
search.textGETpublic{"q":"str","repo":"str"}{"route":"search.text","rows":["repo", "path", "snippet"]}keyword (full-text) search over the documentation corpus, optionally repo-scoped
telemetry.recentGETpublic{}{"route":"telemetry.recent","rows":["id", "ts", "kind", "route", "detail", "ua", "sig"]}recent front-end telemetry beacons (page views / events / client errors), newest first
telemetry.recordPOSTpublic{"kind":"str","route":"str","message":"str","detail":"str"}{"route":"telemetry.record","affected":<n>,"rowid":<id>}front-end telemetry beacon: page views / interaction events land a front_telemetry row; client JS errors also log to error_log + auto-file a de-duped front-end bug (boot/monitor.php)
tickets.recentGETpublic{"status":"str","n":"int"}{"route":"tickets.recent","rows":["id", "title", "severity", "status"]}
work.recordPOSTtoken{"ticket_id":"int","kind":"str","ref":"str","note":"str"}{"route":"work.record","affected":<n>,"rowid":<id>}mint a PERMANENT work UID into a ticket's manifest (returns nothing; read ticket.manifest)

Generic ?api=<table> CRUD

Beyond the named routes, every non-denylisted table is reachable through a generic CRUD layer (the fast internal path). Table and column names are validated against the schema; reads are public, writes need a token / admin session:

calldoes
GET ?api=tableslist the reachable tables
GET ?api=<table>[&<col>=<v>&order=<c>.<dir>&limit=&p=&per=]filtered / paginated rows
GET ?api=<table>&id=<pk>a single row by primary key
POST ?api=<table>create a row from the JSON body (real columns only)
PUT|PATCH ?api=<table>&id=<pk>update a row by primary key
DELETE ?api=<table>&id=<pk>delete a single row by primary key

Admin denylist — not in REST

These tables — the self-hosting archive plus the auth / key tables — are admin-only and never reachable through ?api= or generic writes: