DocsAPI referenceBrowse

API reference

Every route the control plane answers, generated from the OpenAPI document it serves about itself. Two kinds of key, one scoping rule, one error shape — and every bounded reading says what it read.

the same document, from the plane
curl -s http://localhost:4319/v1/openapi.json | jq .info.title

Authentication

Tenant keys reach one log; admin keys reach every log. Webhook and signed-link secrets work only on the route that issued or configured them.

4 authentication schemesShow details

Keys and scoping. Two kinds of bearer: an admin key (configured on the plane) sees every log and every route; a tenant key (ak_…, minted by an admin) is scoped to exactly one log. Every route that names a log applies one rule — scopedLog() — and a tenant asking about any log but its own gets a flat 403 {"error":"forbidden"} that does not confirm whether that log exists. A third credential, the write-only webhook secret, is accepted only on /v1/ingest/*.

SchemeHowReaches
bearerAuthorization: Bearer <admin key or ak_… tenant key>An admin key (configured on the plane in AUDITANT_API_KEYS) reaches every log and every route. A tenant key (ak_ + 48 hex, minted by POST /v1/tenants/key) reaches exactly one log. A plane with no admin keys configured is an open local demo and treats every caller as admin.
webhookSecretheader x-auditant-webhook-secretWrite-only. Accepted on /v1/ingest/* and nowhere else; can write events and do nothing else, so leaking it costs spam, never disclosure.
vapiSecretheader x-vapi-secretThe same webhook secret under the header name Vapi sends it as.
clickTokenquery tAn HMAC-signed, expiring token from a Slack notification. Only /v1/approvals/click.

Errors and limits

Failures use one error shape. Bounded reads say which window they examined, and rate-limited routes return the headers needed to retry safely.

Error model7 responses

Errors are always {"error": string} with a status that means one thing: 400 the request is malformed (including a body over 8 MiB, or an event the schema rejects — the message names the field); 401 no usable credential; 403 the credential does not reach that (never a description of what it would have reached); 404 the route or the thing does not exist for an admin; 429 over a per-key ceiling, with Retry-After; 501 the plane is not configured for that (refusing rather than degrading — a decision without a budget store would look like enforcement and isn't); 500 "internal error", never a stack trace.

StatusMeaningBody
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.{ "error": "ts must be RFC 3339 with an explicit offset (field: ts)" }
401No usable credential.{ "error": "unauthorized" }
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.{ "error": "forbidden" }
404No such route, or no such thing — for an admin. A tenant never reaches a 404 for something outside its scope; it reaches the 403 first.{ "error": "no route for GET /v1/nope" }
429Over the per-key ceiling for this class of route. Per process; wait Retry-After seconds.
headers: Retry-After, x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-reset
{ "error": "rate limited", "scope": "decide", "limit": 12000, "windowSeconds": 60, "retryAfterSeconds": 41, "resetAt": "2026-08-20T10:01:00.000Z" }
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.{ "error": "internal error" }
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.{ "error": "policy decisions are not configured" }
Bounded readingsWindow metadata

Bounded readings. Coverage, approvals and the ledger read a capped window of the log and say so in a window object. A truncated window is a floor, not a total; narrow from/to for an exact figure.

Rate limitsRetry headers

Rate limits apply per key, per process, to ingest, decide and export. x-ratelimit-limit, x-ratelimit-remaining and x-ratelimit-reset are set on every limited response; a refusal is 429 with Retry-After.

Endpoints

Choose a group, then open only the operation you need. Request fields, response fields and examples stay collapsed until then.

Plane3 endpoints · browse

Liveness and self-description. No credential.

GET/healthLiveness, and which logs existno key · details
Auth: no keyhealth

The container health check. Lists log ids so a probe can also confirm the store is readable.

Responses
200The plane is serving from a readable store.
FieldTypeMeaning
okrequiredtrue
logsrequiredstring[]Every log id with at least one event.
200 example
{
  "ok": true,
  "logs": [
    "tenant_acme/prod"
  ]
}
GET/v1/openapi.jsonThis documentno key · details
Auth: no keyopenapi

The plane describes itself, to anyone. There is nothing here a key protects.

Responses
200The OpenAPI 3.1 document for this plane.
POST/v1/ratelimitDurable rate-limit check for a downstream that costs moneyadmin key · details
Auth: admin keyratelimit

Consumes one unit from a per-caller bucket and a shared global bucket, both persisted in the store so a restart does not hand a caller a fresh allowance. Used by the marketing site's chat. Admin only. The bounds you pass are clamped — a caller that could name its own ceiling could name a useless one.

Request body
FieldTypeMeaning
keyrequiredstringThe caller — an IP, a session id.
callerLimitSpec
caller.maxinteger
caller.windowSecondsinteger
globalLimitSpec
global.maxinteger
global.windowSecondsinteger
request
{
  "key": "203.0.113.7",
  "caller": {
    "max": 15,
    "windowSeconds": 3600
  },
  "global": {
    "max": 2000,
    "windowSeconds": 86400
  }
}
Responses
200Whether the caller may proceed.
FieldTypeMeaning
allowedrequiredboolean
remainingrequiredinteger
resetAtrequiredstring
scope"caller" | "global"Which bucket refused, when one did.
200 example
{
  "allowed": false,
  "remaining": 0,
  "resetAt": "2026-08-20T11:00:00.000Z",
  "scope": "caller"
}
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
Evidence2 endpoints · browse

Writing to the chain. Asynchronous by design: an append never blocks the agent that emitted it.

POST/v1/eventsAppend events to the chaintenant or admin key · details
Auth: tenant or admin keyRate-limited: ingest bucket, per keyappendEvents

Seals each event onto its log — assigning seq, prevHash and eventHash under the per-log write lock — and returns the new head. The whole batch is one transaction: all of it lands or none of it does. Every event names its own logId, and a tenant key may only write its own; the scope check runs before anything chains, because an append is permanent. An event the schema rejects is a 400 naming the field, and nothing in the batch is written.

Request body

At least one event.

FieldTypeMeaning
eventsrequiredAuditEventInput[]
events[].schemaVersionrequired"1.0.0"
events[].eventIdrequiredstringThe emitter's id. Deduplication is the emitter's job; the log records what it is sent.
events[].tsrequiredstringRFC 3339 with an explicit offset.
events[].logIdrequiredstring
events[].actorrequiredActor
events[].actor.kindrequired"agent" | "human" | "system"
events[].actor.idrequiredstring
events[].actor.versionstring
events[].actor.mode"interactive" | "autonomous"`interactive` — a human was present and approved. `autonomous` — no human in the loop.
events[].actor.principalstringGateway key hash, IAM principal, or OIDC subject — whatever authenticated.
events[].onBehalfOfobject
events[].onBehalfOf.humanIdstring
events[].onBehalfOf.endUserstring
events[].approvedByobject
events[].approvedBy.humanIdrequiredstring
events[].approvedBy.atrequiredstring
events[].sessionIdstringA run. The ledger's unit.
events[].traceIdstringJoins the capture planes. Without it we hold four disconnected logs rather than one account.
events[].parentEventIdstring
events[].actionTyperequired"model_call" | "tool_call" | "tool_response" | "decision" | "delegation" | "escalation" | "human_override" | "policy_decision" | "disclosure" | "lifecycle" | "error"
events[].actionrequiredstring
events[].surfacerequiredSurface
events[].surface.planerequired"model" | "action" | "edge" | "effect"Which capture plane observed this. Determines what the event can prove.
events[].surface.adapterrequiredstring`sdk`, `gateway`, `langgraph`, `vapi`, `github`…
events[].surface.modality"text" | "voice" | "code" | "infra"
events[].inputHashstringPayloads live in object storage; only hashes chain.
events[].outputHashstring
events[].outcomerequired"ok" | "error" | "blocked" | "pending_approval" | "reverted"`blocked` and `pending_approval` require a `policy` record naming what stopped it.
events[].reasonstringWhy, in the actor's own words. Required by `adverse-decision-requires-reason`.
events[].policyPolicyRecord
events[].policy.decisionrequired"allow" | "deny" | "pending_approval"
events[].policy.policyIdrequiredstring
events[].policy.policyVersionrequiredstring
events[].policy.enginerequiredstring
events[].policy.approvalIdstring
events[].policy.approverstring | null
events[].policy.reasonsstring[]
events[].policy.monitorModebooleanTrue when the rule ran in monitor mode — recorded, deliberately not enforced.
events[].costCost
events[].cost.currencyrequiredstring
events[].cost.totalrequirednumber
events[].cost.breakdownobject
events[].cost.breakdown.inputnumber
events[].cost.breakdown.outputnumber
events[].cost.breakdown.reasoningnumber
events[].cost.breakdown.cacheReadnumber
events[].cost.breakdown.cacheCreationnumber
events[].cost.breakdown.toolUsagenumber
events[].cost.unitsobject
events[].cost.units.inputTokensinteger
events[].cost.units.outputTokensinteger
events[].cost.units.cacheReadTokensinteger
events[].cost.units.cacheCreationTokensinteger
events[].cost.units.reasoningTokensinteger
events[].cost.units.secondsnumber
events[].cost.units.charactersinteger
events[].cost.modelstring
events[].cost.providerstring
events[].cost.attributionCompleterequiredbooleanFalse ⇒ the upstream priced nothing. Never render this as $0.
events[].art12objectEU AI Act Art 12(3) names these three specifically.
events[].art12.periodStartstring
events[].art12.periodEndstring
events[].art12.inputRefsstring[]
events[].art12.humansInvolvedstring[]
request
{
  "events": [
    {
      "schemaVersion": "1.0.0",
      "eventId": "evt_8f2c1a",
      "ts": "2026-08-20T10:00:00.000Z",
      "logId": "tenant_acme/prod",
      "actor": {
        "kind": "agent",
        "id": "underwriter",
        "mode": "autonomous"
      },
      "sessionId": "sess_b0f9c646",
      "traceId": "trace_41",
      "actionType": "tool_call",
      "action": "lookup_credit_file",
      "surface": {
        "plane": "action",
        "adapter": "sdk"
      },
      "inputHash": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
      "outcome": "ok"
    }
  ]
}
Responses
202Accepted and sealed. The head is the last event written.
  • x-ratelimit-limit —
  • x-ratelimit-remaining —
  • x-ratelimit-reset —
FieldTypeMeaning
acceptedrequiredinteger
logIdrequiredstringThe first event's log.
headrequiredobject
head.seqrequiredinteger
head.hashrequiredstring
202 example
{
  "accepted": 1,
  "logId": "tenant_acme/prod",
  "head": {
    "seq": 4183,
    "hash": "sha256:bb1074a2c9e1…"
  }
}
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
429Over the per-key ceiling for this class of route. Per process; wait `Retry-After` seconds.
  • Retry-After — Whole seconds until the window resets.
  • x-ratelimit-limit — The ceiling.
  • x-ratelimit-remaining — Always 0 here.
  • x-ratelimit-reset — RFC 3339.
FieldTypeMeaning
errorrequired"rate limited"
scoperequired"ingest" | "decide" | "export"
limitrequiredinteger
windowSecondsrequiredinteger
retryAfterSecondsrequiredinteger
resetAtrequiredstring
429 example
{
  "error": "rate limited",
  "scope": "decide",
  "limit": 12000,
  "windowSeconds": 60,
  "retryAfterSeconds": 41,
  "resetAt": "2026-08-20T10:01:00.000Z"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
POST/v1/ingest/{kind}/{vendor}Edge plane: a vendor's webhook, mapped onto the chainkey or webhook secret · details
Auth: key or webhook secretRate-limited: ingest bucket, per keyingestWebhook

One route per adapter kind rather than per vendor: the mapping differs, the schema does not. voice maps a finished call (lifecycle, per-turn decisions, tool calls, and a first-class disclosure event recording whether the AI disclosure was played); code maps a coding-agent session, with the commit as the effect-plane evidence; cloud maps a provider audit event (CloudTrail, GCP audit log, Kubernetes) as an effect. The vendor segment is recorded as surface.adapter and may be omitted, in which case it is the kind.

Authenticates with EITHER the bearer key OR the write-only webhook secret (x-auditant-webhook-secret, or x-vapi-secret because Vapi cannot be told otherwise). The secret can write events and do nothing else, so a vendor's webhook configuration screen never holds the key.

Parameters
FieldTypeMeaning
kindrequiredpath"voice" | "code" | "cloud"Which adapter maps the payload.
vendorrequiredpathstringRecorded as `surface.adapter` — `vapi`, `retell`, `cursor`, `aws`… Free text.
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Request body

The vendor's payload, in the shape the adapter kind expects.

Responses
202Mapped and sealed.
  • x-ratelimit-limit —
  • x-ratelimit-remaining —
  • x-ratelimit-reset —
FieldTypeMeaning
acceptedrequiredintegerEvents written.
logIdrequiredstring
adapterrequiredstringThe kind.
vendorrequiredstring
202 example
{
  "accepted": 7,
  "logId": "tenant_acme/prod",
  "adapter": "voice",
  "vendor": "vapi"
}
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
404Unknown adapter kind. Lists the ones that exist.
FieldTypeMeaning
errorrequiredstring
supportedrequiredstring[]
404 example
{
  "error": "unknown adapter \"sms\"",
  "supported": [
    "voice",
    "code",
    "cloud"
  ]
}
429Over the per-key ceiling for this class of route. Per process; wait `Retry-After` seconds.
  • Retry-After — Whole seconds until the window resets.
  • x-ratelimit-limit — The ceiling.
  • x-ratelimit-remaining — Always 0 here.
  • x-ratelimit-reset — RFC 3339.
FieldTypeMeaning
errorrequired"rate limited"
scoperequired"ingest" | "decide" | "export"
limitrequiredinteger
windowSecondsrequiredinteger
retryAfterSecondsrequiredinteger
resetAtrequiredstring
429 example
{
  "error": "rate limited",
  "scope": "decide",
  "limit": 12000,
  "windowSeconds": 60,
  "retryAfterSeconds": 41,
  "resetAt": "2026-08-20T10:01:00.000Z"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
Policy1 endpoint · browse

The one synchronous call. It is on the request path on purpose.

POST/v1/decideAsk policy before actingtenant or admin key · details
Auth: tenant or admin keyRate-limited: decide bucket, per keydecide

Synchronous, on the request path by design, and judged in microseconds. The caller states what it is trying to do — that is genuinely its own knowledge. Everything the decision is checked against (spend inside the budget window, burn rate, session iterations, the halt flag, any real human approval) is derived from the chain and stored configuration, and overwrites anything the caller sent. evaluatedAgainst echoes those derived values so a caller can see what it was judged on.

An admin key is judged against the operator's custom rules; a tenant key against the built-in rules only — one tenant's policy must never govern another's agents. Without a budget store the route returns 501 rather than deciding on caller-supplied limits.

Request body
FieldTypeMeaning
logIdrequiredstring
agentIdrequiredstring
actionrequiredstring
amountnumberThe value at stake, as the caller understands it.
modelstring
endUserstring
reasonstringThe stated justification. Its presence is checked; its truth cannot be.
sessionIdstringNeeded for a human approval to be found — an approval is matched on session AND action.
request
{
  "logId": "tenant_acme/prod",
  "agentId": "underwriter",
  "action": "wire_transfer",
  "amount": 50000,
  "sessionId": "sess_b0f9c646",
  "reason": "settling invoice #4471"
}
Responses
200The verdict, and what it was judged against.
  • x-ratelimit-limit —
  • x-ratelimit-remaining —
  • x-ratelimit-reset —
200 example
{
  "effect": "pending_approval",
  "policyId": "human-signoff-above-threshold",
  "policyVersion": "1",
  "engine": "auditant-cedar/1",
  "reasons": [
    "amount 50000 exceeds threshold 10000"
  ],
  "evaluatedAgainst": {
    "dailyTotal": 12.4,
    "burnPerMin": 0.02,
    "sessionIterations": 7,
    "tenantHalted": false,
    "approvalId": null
  }
}
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
429Over the per-key ceiling for this class of route. Per process; wait `Retry-After` seconds.
  • Retry-After — Whole seconds until the window resets.
  • x-ratelimit-limit — The ceiling.
  • x-ratelimit-remaining — Always 0 here.
  • x-ratelimit-reset — RFC 3339.
FieldTypeMeaning
errorrequired"rate limited"
scoperequired"ingest" | "decide" | "export"
limitrequiredinteger
windowSecondsrequiredinteger
retryAfterSecondsrequiredinteger
resetAtrequiredstring
429 example
{
  "error": "rate limited",
  "scope": "decide",
  "limit": 12000,
  "windowSeconds": 60,
  "retryAfterSeconds": 41,
  "resetAt": "2026-08-20T10:01:00.000Z"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
Export1 endpoint · browse

The artifact an examiner receives — self-verifying, offline.

GET/v1/exportThe evidence bundletenant or admin key · details
Auth: tenant or admin keyRate-limited: export bucket, per keyexportBundle

Everything needed to verify the record independently, in one file: the events in range, every checkpoint up to the head, the public keys, a plain README, and the standalone verifier itself as source — so checking the evidence needs Node and nothing else. Served as an attachment; it is meant to be handed to a person.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
fromquerystringInclusive, RFC 3339. Default: the beginning.
toquerystringInclusive, RFC 3339. Default: now.
Responses
200The bundle, as `Content-Disposition: attachment`.
  • Content-Disposition — `attachment; filename="auditant-<log>.json"`
  • x-ratelimit-limit —
  • x-ratelimit-remaining —
  • x-ratelimit-reset —
FieldTypeMeaning
bundleVersionrequired"1.0.0"
logIdrequiredstring
fromrequiredstring
torequiredstring
exportedAtrequiredstring
eventsrequiredAuditEvent[]
checkpointsrequiredSignedCheckpoint[]
checkpoints[].checkpointrequiredCheckpoint
checkpoints[].checkpoint.originrequiredstring`auditant.dev/<logId>` — namespaced so two deployments cannot collide.
checkpoints[].checkpoint.treeSizerequiredinteger
checkpoints[].checkpoint.headHashrequiredstring
checkpoints[].checkpoint.timestamprequiredstring
checkpoints[].bodyrequiredstringThe exact bytes that were signed.
checkpoints[].keyIdrequiredstring
checkpoints[].signaturerequiredstringbase64 ECDSA P-256 over `body`.
checkpoints[].timestampTokenstringbase64 RFC 3161 token, once an authority has countersigned.
checkpoints[].wormAnchoredbooleanOperator-side: the copy landed in write-once storage. Not part of the signed body.
publicKeysrequiredPublicKeyEntry[]
publicKeys[].keyIdrequiredstring`auditant-<12 hex of sha256(pem)>` — content-addressed.
publicKeys[].pemrequiredstringSPKI PEM.
publicKeys[].notBeforestring
publicKeys[].notAfterstring
startHeadChainHead
startHead.logIdrequiredstring
startHead.treeSizerequiredinteger
startHead.headHashrequiredstring
verifierstringThe standalone verifier as source — one dependency-free .mjs. Save it and run it with plain Node.
readmestringAdded on export: how a stranger checks this bundle.
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
429Over the per-key ceiling for this class of route. Per process; wait `Retry-After` seconds.
  • Retry-After — Whole seconds until the window resets.
  • x-ratelimit-limit — The ceiling.
  • x-ratelimit-remaining — Always 0 here.
  • x-ratelimit-reset — RFC 3339.
FieldTypeMeaning
errorrequired"rate limited"
scoperequired"ingest" | "decide" | "export"
limitrequiredinteger
windowSecondsrequiredinteger
retryAfterSecondsrequiredinteger
resetAtrequiredstring
429 example
{
  "error": "rate limited",
  "scope": "decide",
  "limit": 12000,
  "windowSeconds": 60,
  "retryAfterSeconds": 41,
  "resetAt": "2026-08-20T10:01:00.000Z"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
Reading the record6 endpoints · browse

Totals, pages, coverage and compliance, read off the same chained events.

GET/v1/eventsPage through a log by sequencetenant or admin key · details
Auth: tenant or admin keylistEvents

Events in sequence order, a page at a time. Ascending is the default for export-style walks; order=desc starts at the live head for console views. In either direction, pass a page's nextCursor back as cursor to continue without offsets, repeats, or gaps. A page can never exceed the maximum whatever is asked for, and nextCursor is null on the last page.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
cursorquerystringA previous page's `nextCursor`. Ascending pages continue strictly after it; descending pages continue strictly before it.
orderquery"asc" | "desc"Chain order. Use `desc` for a bounded view of the newest records.
limitqueryintegerPage size. Above 1000 is a 400, not a silent clamp.
sessionquerystringOnly this session.
agentquerystringOnly this actor id.
Responses
200One page.
FieldTypeMeaning
eventsrequiredAuditEvent[]
limitrequiredintegerThe page size that applied.
nextCursorrequiredstring | nullPass back as `cursor` for the next page. `null` on the last page.
orderrequired"asc" | "desc"The sequence order used for this page.
200 example
{
  "events": [
    "…"
  ],
  "limit": 200,
  "nextCursor": "4382",
  "order": "asc"
}
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/statsTotals for one logtenant or admin key · details
Auth: tenant or admin keystats

Aggregates the database computes: counts, spend, and how many model calls the upstream did not price — read from the attributionComplete flag, never inferred from a zero. Plus the head and the checkpoint count.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The totals.
FieldTypeMeaning
eventsrequiredinteger
agentsrequiredintegerDistinct actor ids.
blockedrequiredinteger
pendingApprovalrequiredinteger
costTotalrequirednumber
costIncompleterequiredintegerEvents whose cost the upstream did not price. Never shown as $0.
headrequiredobject
head.treeSizerequiredinteger
head.hashrequiredstring
checkpointsrequiredinteger
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/coverageThe completeness half of the evidence storytenant or admin key · details
Auth: tenant or admin keycoverage

A hash chain proves what is on it was never altered; it cannot prove nothing was left off. This reading makes omission visible: which capture planes are live, which agents have gone quiet, whether traces are corroborated on a second plane, how fresh the anchors are — and one blunt score a buyer can watch go up. Computed over the newest window.cap events, and says so; events is the exact total from the head.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The coverage report.
FieldTypeMeaning
logIdrequiredstring
computedAtrequiredstring
eventsrequiredintegerEvery event in the log — exact, from the head.
windowrequiredScanWindowWhat a bounded reading actually read. When `truncated` is true the figures above it are floors.
window.eventsrequiredintegerEvents read.
window.caprequiredintegerThe cap that applied.
window.truncatedrequiredbooleanMore qualifying events exist than were read.
window.fromSeqrequiredinteger | null
window.toSeqrequiredinteger | null
window.basisrequiredstringIn words — `computed over the last 10,000 of 84,211 events`.
planesLiverequired"model" | "action" | "edge" | "effect"[]
agentsrequiredAgentCoverage[]
agents[].agentIdrequiredstring
agents[].eventsrequiredintegerWithin the window.
agents[].lastSeenrequiredstring
agents[].silenceMsrequiredinteger
agents[].quietrequiredbooleanSilent for over 24h. A quiet agent and a broken emitter look identical from here.
agents[].planesrequired"model" | "action" | "edge" | "effect"[]
quietAgentsrequiredinteger
joinedTracesrequiredintegerTraces observed on two or more planes — corroborated.
totalTracesrequiredinteger
unpricedEventsrequiredinteger
pricedEventsrequiredinteger
anchoringrequiredobject
anchoring.checkpointsrequiredinteger
anchoring.latestAtrequiredstring | null
anchoring.ageMsrequiredinteger | null
anchoring.stalerequiredboolean
anchoring.unanchoredTailrequiredintegerEvents after the newest checkpoint — the current exposure.
anchoring.timestampedrequiredinteger
anchoring.wormAnchoredrequiredinteger
scorerequiredintegerplanes 35 · anchoring 25 · liveness 20 · join 10 · pricing 10. An empty log scores 0.
findingsrequiredstring[]Every deduction, named.
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/checkpointsThe seals, where they sit in the sequencetenant or admin key · details
Auth: tenant or admin keycheckpoints

The newest checkpoints on the log — up to window.cap of them, oldest first within that window, and window.total says how many there are. Each carries the tree size at signing; because event sequences are zero-based, it covers through sequence treeSize - 1. It also says when it was signed and which further assurances it has reached — an RFC 3161 countersignature and a copy in write-once storage. The signatures and tokens themselves travel in the evidence bundle.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The newest checkpoints, oldest first within the window.
FieldTypeMeaning
checkpointsrequiredobject[]
checkpoints[].treeSizerequiredintegerThe log's size when this seal was signed. It covers through zero-based event sequence `treeSize - 1`.
checkpoints[].atrequiredstringWhen it was signed, RFC 3339.
checkpoints[].countersignedrequiredbooleanAn independent RFC 3161 timestamp authority has countersigned it.
checkpoints[].wormrequiredbooleanA copy has landed in write-once storage.
windowrequiredobjectThe bound on this read, disclosed.
window.caprequiredintegerThe most this read returns.
window.returnedrequiredinteger
window.totalrequiredintegerHow many checkpoints the log holds.
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/complianceWhat each regime asks, answered from the chaintenant or admin key · details
Auth: tenant or admin keycompliance

Every regime's obligations with a status each — satisfied, open, watching (a rule armed in monitor mode: recorded, deliberately not enforced) or outside (the record cannot answer it, and says so rather than implying otherwise) — and the open ones collapsed to the distinct actions that close them.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The compliance posture across every regime.
FieldTypeMeaning
logIdrequiredstring
computedAtrequiredstring
regimesrequiredRegimeReport[]
regimes[].idrequiredstring
regimes[].namerequiredstring
regimes[].subrequiredstringJurisdiction or scope.
regimes[].obligationsrequiredObligation[]
regimes[].obligations[].idrequiredstring
regimes[].obligations[].clauserequiredstringAs the standard numbers it.
regimes[].obligations[].statementrequiredstring
regimes[].obligations[].provesrequiredstringWhat in this product answers it.
regimes[].obligations[].basisrequired"record" | "configuration" | "outside"
regimes[].obligations[].statusrequired"satisfied" | "open" | "watching" | "outside"
regimes[].obligations[].evidencerequiredinteger[]Sequence numbers that answer it.
regimes[].obligations[].detailrequiredstring
regimes[].obligations[].todostring
regimes[].evidenceablerequiredintegerObligations a record can answer at all — the denominator that means something.
regimes[].satisfiedrequiredinteger
regimes[].openrequiredinteger
regimes[].watchingrequiredinteger
regimes[].outsiderequiredinteger
regimes[].evidenceEventsrequiredinteger
evidenceablerequiredinteger
satisfiedrequiredinteger
openrequiredinteger
outsiderequiredinteger
actionsrequiredobject[]
actions[].idrequiredstring
actions[].todorequiredstring
actions[].closesrequiredstring[]
actions[].detailrequiredstring
actions[].overduerequiredboolean
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/compliance/{regime}One regime, obligation by obligationtenant or admin key · details
Auth: tenant or admin keyregime

The drill-in: one regime's obligations with the sequence numbers that answer each. Separate from the overview so a console that draws five summaries does not have to fetch every obligation of every regime to do it.

Parameters
FieldTypeMeaning
regimerequiredpathstringA regime id from the overview — `eu-ai-act`, `iso-42001`, `dpdp`, `soc2`, `nist-ai-rmf`… Unknown ids are a 404.
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The regime report.
FieldTypeMeaning
idrequiredstring
namerequiredstring
subrequiredstringJurisdiction or scope.
obligationsrequiredObligation[]
obligations[].idrequiredstring
obligations[].clauserequiredstringAs the standard numbers it.
obligations[].statementrequiredstring
obligations[].provesrequiredstringWhat in this product answers it.
obligations[].basisrequired"record" | "configuration" | "outside"
obligations[].statusrequired"satisfied" | "open" | "watching" | "outside"
obligations[].evidencerequiredinteger[]Sequence numbers that answer it.
obligations[].detailrequiredstring
obligations[].todostring
evidenceablerequiredintegerObligations a record can answer at all — the denominator that means something.
satisfiedrequiredinteger
openrequiredinteger
watchingrequiredinteger
outsiderequiredinteger
evidenceEventsrequiredinteger
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
404No such route, or no such thing — for an admin. A tenant never reaches a 404 for something outside its scope; it reaches the 403 first.
FieldTypeMeaning
errorrequiredstring
404 example
{
  "error": "no route for GET /v1/nope"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
Approvals3 endpoints · browse

The chain is the queue: a held action is a pending_approval event, and a human's answer is a human_override event in the same session.

GET/v1/approvalsOpen requeststenant or admin key · details
Auth: tenant or admin keylistApprovals

Every pending_approval event with no later human_override in the same session naming the same action. Found by two indexed queries — never a scan of the log — newest first, capped at window.cap requests and saying so.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The queue, and the bounds of the reading.
FieldTypeMeaning
pendingrequiredPendingApproval[]Newest first.
pending[].eventIdrequiredstring
pending[].tsrequiredstring
pending[].sessionIdstring
pending[].agentIdrequiredstring
pending[].actionrequiredstring
pending[].reasonsrequiredstring[]
pending[].approvalIdstring
windowrequiredobject
window.caprequiredinteger
window.requestsrequiredintegerHeld requests read.
window.answersrequiredinteger`human_override` events read, from the oldest request onward.
window.truncatedrequiredboolean
window.basisrequiredstring
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
POST/v1/approvalsA human answers a held actiontenant or admin key · details
Auth: tenant or admin keyanswerApproval

Appends a human_override event under the approver's name. Approval records outcome ok — the exact shape /v1/decide looks for, so the agent's next check walks through. Rejection records outcome blocked with a policy record naming the human, which the decision reader ignores — so the agent stays held, and the refusal is itself on the chain. An anonymous approval is exactly the record this product exists to prevent, so approver is required.

Request body
FieldTypeMeaning
logrequiredstring
sessionIdrequiredstringThe session the request was held in.
actionrequiredstringThe held action, exactly as recorded.
approverrequiredstringWho is answering. Recorded as the actor.
approverequiredboolean
reasonstring
request
{
  "log": "tenant_acme/prod",
  "sessionId": "sess_b0f9c646",
  "action": "wire_transfer",
  "approver": "augusta",
  "approve": false,
  "reason": "amount not justified by the campaign plan"
}
Responses
200Recorded.
FieldTypeMeaning
okrequiredtrue
eventIdrequiredstringThe `human_override` event written.
approvedrequiredboolean
200 example
{
  "ok": true,
  "eventId": "evt_approval_k2x9q1",
  "approved": false
}
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/approvals/clickOne-click answer from a Slack linksigned link · details
Auth: signed linkclickApproval

The one route that serves markup and sits before the bearer gate: the clicker is a human in a browser, and the signed, expiring token in t IS the credential. Records the answer exactly as POST /v1/approvals would, under the configured approver label, and renders a sentence. Everything interpolated into the page is escaped — the action name is authored by the agents this product audits. 404 when one-click links are not configured (no link secret); 403 for an invalid or expired token; 200 "Already answered" when someone got there first.

Parameters
FieldTypeMeaning
trequiredquerystringThe HMAC-signed, expiring token from the Slack message.
Responses
200Approved, Rejected, or Already answered — as a small HTML page.text/html
403Link invalid or expired.text/html
404One-click approvals are not enabled on this deployment.text/html
Ledger3 endpoints · browse

Spend, computed from the chain rather than rented from a gateway.

GET/v1/ledgerSpend analysis for one logtenant or admin key · details
Auth: tenant or admin keyledger

Cost per agent, customer, model and run, and cost per clean run — the one that completed with no block and no human. Administration (sign-ins, rule and budget changes) is in the chain and excluded from spend. Unpriced calls are counted, never folded in as $0. Computed over the newest window.cap events in range; narrow from/to when window.truncated is true.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
fromquerystring
toquerystring
Responses
200The summary.
FieldTypeMeaning
logIdrequiredstring
fromrequiredstring
torequiredstring
totalUsdrequirednumber
breakdownrequiredobject
breakdown.inputnumber
breakdown.outputnumber
breakdown.reasoningnumber
breakdown.cacheReadnumber
breakdown.cacheCreationnumber
breakdown.toolUsagenumber
runsrequiredinteger
cleanRunsrequiredinteger
costPerCleanRunrequirednumber | nullNull when there were no clean runs — never Infinity or NaN.
unpricedCallsrequiredinteger
byAgentrequiredobject[]
byAgent[].agentIdstring
byAgent[].costUsdnumber
byAgent[].runsinteger
byAgent[].blockedinteger
byCustomerrequiredobject[]
byCustomer[].customerstring
byCustomer[].costUsdnumber
byCustomer[].runsinteger
byModelrequiredobject[]
byModel[].modelstring
byModel[].costUsdnumber
byModel[].callsinteger
windowrequiredScanWindowWhat a bounded reading actually read. When `truncated` is true the figures above it are floors.
window.eventsrequiredintegerEvents read.
window.caprequiredintegerThe cap that applied.
window.truncatedrequiredbooleanMore qualifying events exist than were read.
window.fromSeqrequiredinteger | null
window.toSeqrequiredinteger | null
window.basisrequiredstringIn words — `computed over the last 10,000 of 84,211 events`.
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/ledger/runsUnit economics, per runtenant or admin key · details
Auth: tenant or admin keyledgerRuns

One row per session: calls, cost, whether policy stopped anything, whether a human had to step in. Bounded like the summary.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
fromquerystring
toquerystring
Responses
200The runs, and the bounds of the reading.
FieldTypeMeaning
runsrequiredRunCost[]
runs[].sessionIdrequiredstring
runs[].agentIdrequiredstring
runs[].customerrequiredstring | null
runs[].llmCallsrequiredinteger
runs[].toolCallsrequiredinteger
runs[].costUsdrequirednumber
runs[].costTrustworthyrequiredbooleanFalse when any model call in the run priced as unknown.
runs[].startedAtrequiredstring
runs[].endedAtrequiredstring
runs[].hitPolicyrequiredboolean
runs[].neededHumanrequiredboolean
runs[].cleanOutcomerequiredboolean
windowrequiredScanWindowWhat a bounded reading actually read. When `truncated` is true the figures above it are floors.
window.eventsrequiredintegerEvents read.
window.caprequiredintegerThe cap that applied.
window.truncatedrequiredbooleanMore qualifying events exist than were read.
window.fromSeqrequiredinteger | null
window.toSeqrequiredinteger | null
window.basisrequiredstringIn words — `computed over the last 10,000 of 84,211 events`.
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/ledger/budgetBudget state for one agenttenant or admin key · details
Auth: tenant or admin keyledgerBudget

Spend since since, burn rate, and whether it exceeded ceiling. The spend is one aggregate the database computes over an indexed column — exact whatever the log size. Note this is a calculator against a ceiling you pass; the ceilings a decision is actually judged against live in /v1/budgets.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
agentrequiredquerystring
sincequerystringWindow start. Default: 24 hours ago.
ceilingquerynumberUSD.
Responses
200The state.
FieldTypeMeaning
agentIdrequiredstring
windowStartrequiredstring
spentUsdrequirednumber
ceilingUsdrequirednumber
remainingUsdrequirednumberClamped at zero.
utilisationrequirednumber
burnRatePerMinrequirednumber
exceededrequiredboolean
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
Budgets3 endpoints · browse

Ceilings and the halt flag — configuration a caller can never assert, only an admin can set.

GET/v1/budgetsConfigured ceilings, and the halt flagtenant or admin key · details
Auth: tenant or admin keylistBudgets

An admin sees every budget scope. A tenant sees its own halt state and an empty budgets list — ceilings are the operator's configuration.

Parameters
FieldTypeMeaning
logquerystringRequired for a tenant key; optional for an admin (then `halted` is for the empty log).
Responses
200Budgets and halt state.
FieldTypeMeaning
budgetsrequiredBudget[]
budgets[].scoperequiredstringAn agent id, or `*` for the fleet default.
budgets[].ceilingUsdrequirednumber
budgets[].windowHoursrequiredinteger
budgets[].updatedAtrequiredstring
budgets[].updatedByrequiredstring
haltedrequiredboolean
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
PUT/v1/budgetsSet a ceilingadmin key · details
Auth: admin keysetBudget

Upserts the budget for a scope — an agent id, or * for the fleet default — and records the change on the chain under author. "Who raised the ceiling the day before the overspend" is a question that gets asked.

Request body
FieldTypeMeaning
scopestringAn agent id, or `*`.
ceilingUsdrequirednumber
windowHoursinteger
authorrequiredstring
logstringThe log this belongs to and is chained on. Defaults to the operator's own log; a tenant key may name only its own.
request
{
  "scope": "underwriter",
  "ceilingUsd": 250,
  "windowHours": 24,
  "author": "augusta"
}
Responses
200The budget as stored.
FieldTypeMeaning
budgetrequiredBudget
budget.scoperequiredstringAn agent id, or `*` for the fleet default.
budget.ceilingUsdrequirednumber
budget.windowHoursrequiredinteger
budget.updatedAtrequiredstring
budget.updatedByrequiredstring
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
POST/v1/haltThe kill switchtenant or admin key · details
Auth: tenant or admin keyhalt

Sets the halt flag for a log. While halted, every decision for that log is refused. A tenant may pull its own switch — that is the control, not a privilege — but only its own. Recorded on the chain with a name attached; it is the most consequential button in the product and the one most likely to be pressed in a hurry.

Request body
FieldTypeMeaning
logrequiredstring
haltedrequiredboolean
authorrequiredstring
request
{
  "log": "tenant_acme/prod",
  "halted": true,
  "author": "augusta"
}
Responses
200Recorded.
FieldTypeMeaning
okrequiredtrue
haltedrequiredboolean
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
Rules5 endpoints · browse

Customer-defined rules, versioned by content hash, never deleted.

GET/v1/policiesWhat is armed, in plain Englishtenant or admin key · details
Auth: tenant or admin keylistPolicies

Every rule the engine evaluates, described. An admin sees the built-ins plus the operator's custom rules and whether custom rules are configured at all; a tenant sees the built-ins that actually govern its decisions and customRulesEnabled: false.

Parameters
FieldTypeMeaning
logquerystringThe log whose rules to read. A tenant key may name only its own; the operator's key defaults to the operator's own log.
Responses
200The policy page's data.
FieldTypeMeaning
policiesrequiredPolicyDescription[]
policies[].idrequiredstring
policies[].englishrequiredstring
policies[].enforcingrequiredbooleanFalse ⇒ monitor mode.
policies[].descriptionrequiredstring
policies[].versionrequiredstring
policies[].builtInrequiredbooleanBuilt-ins cannot be edited or retired.
customRulesEnabledrequiredbooleanWhether a rule store is configured on this plane — distinct from "no custom rules yet".
customrequiredStoredRule[]
custom[].specrequiredRuleSpec
custom[].spec.idrequiredstring
custom[].spec.descriptionrequiredstring
custom[].spec.effectrequired"deny" | "pending_approval"
custom[].spec.conditionrequiredobject | object | object | objectA boolean tree over the decision context. Nesting is limited to 8 levels.
custom[].spec.monitorModerequiredbooleanRules ship watching. Arming is a deliberate, separately recorded act.
custom[].versionrequiredstringThe content hash of the spec.
custom[].englishrequiredstringThe rule, as a sentence.
custom[].createdAtrequiredstring
custom[].createdByrequiredstring
custom[].retiredAtrequiredstring | null
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
PUT/v1/policiesSave a rule, as a new versionadmin key · details
Auth: admin keyputPolicy

Validates the spec, retires whatever version of that rule id was live, and stores this one. The version is the content hash, so saving the same spec twice is a no-op that returns the existing version. Every change is itself an event on the chain, carrying both sides in plain English. A validation failure names the path — condition.all[1]: gt needs a number, got string.

Request body
FieldTypeMeaning
rulerequiredRuleSpec
rule.idrequiredstring
rule.descriptionrequiredstring
rule.effectrequired"deny" | "pending_approval"
rule.conditionrequiredobject | object | object | objectA boolean tree over the decision context. Nesting is limited to 8 levels.
rule.monitorModerequiredbooleanRules ship watching. Arming is a deliberate, separately recorded act.
authorrequiredstring
logstringThe log this belongs to and is chained on. Defaults to the operator's own log; a tenant key may name only its own.
request
{
  "rule": {
    "id": "wire-limit-emea",
    "description": "Wires above €25k wait for a human",
    "effect": "pending_approval",
    "condition": {
      "all": [
        {
          "field": "action",
          "op": "eq",
          "value": "wire_transfer"
        },
        {
          "field": "amount",
          "op": "gt",
          "value": 25000
        }
      ]
    },
    "monitorMode": true
  },
  "author": "augusta"
}
Responses
200The stored rule.
FieldTypeMeaning
rulerequiredStoredRule
rule.specrequiredRuleSpec
rule.spec.idrequiredstring
rule.spec.descriptionrequiredstring
rule.spec.effectrequired"deny" | "pending_approval"
rule.spec.conditionrequiredobject | object | object | objectA boolean tree over the decision context. Nesting is limited to 8 levels.
rule.spec.monitorModerequiredbooleanRules ship watching. Arming is a deliberate, separately recorded act.
rule.versionrequiredstringThe content hash of the spec.
rule.englishrequiredstringThe rule, as a sentence.
rule.createdAtrequiredstring
rule.createdByrequiredstring
rule.retiredAtrequiredstring | null
400Author missing, or the rule failed validation — `path` says where.
FieldTypeMeaning
errorrequiredstring
pathstring
400 example
{
  "error": "gt needs a number, got string (at condition.all[1])",
  "path": "condition.all[1]"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
GET/v1/policies/{ruleId}/historyEvery version of a ruleadmin key · details
Auth: admin keypolicyHistory

Newest first. Nothing is ever deleted: a rule that governed a real decision is part of that decision's evidence.

Parameters
FieldTypeMeaning
ruleIdrequiredpathstring
logquerystringThe log whose rules to read. A tenant key may name only its own; the operator's key defaults to the operator's own log.
Responses
200The audit view.
FieldTypeMeaning
ruleIdrequiredstring
versionsrequiredStoredRule[]
versions[].specrequiredRuleSpec
versions[].spec.idrequiredstring
versions[].spec.descriptionrequiredstring
versions[].spec.effectrequired"deny" | "pending_approval"
versions[].spec.conditionrequiredobject | object | object | objectA boolean tree over the decision context. Nesting is limited to 8 levels.
versions[].spec.monitorModerequiredbooleanRules ship watching. Arming is a deliberate, separately recorded act.
versions[].versionrequiredstringThe content hash of the spec.
versions[].englishrequiredstringThe rule, as a sentence.
versions[].createdAtrequiredstring
versions[].createdByrequiredstring
versions[].retiredAtrequiredstring | null
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
GET/v1/policies/{ruleId}/versions/{version}One exact versionadmin key · details
Auth: admin keypolicyVersion

The lookup the whole rule store exists for: turns the policyId and policyVersion on a nine-month-old decision back into the rule that made it, in the words it was written in.

Parameters
FieldTypeMeaning
ruleIdrequiredpathstring
versionrequiredpathstringThe content hash, as recorded on the decision.
logquerystringThe log whose rules to read. A tenant key may name only its own; the operator's key defaults to the operator's own log.
Responses
200The rule as it was.
FieldTypeMeaning
rulerequiredStoredRule
rule.specrequiredRuleSpec
rule.spec.idrequiredstring
rule.spec.descriptionrequiredstring
rule.spec.effectrequired"deny" | "pending_approval"
rule.spec.conditionrequiredobject | object | object | objectA boolean tree over the decision context. Nesting is limited to 8 levels.
rule.spec.monitorModerequiredbooleanRules ship watching. Arming is a deliberate, separately recorded act.
rule.versionrequiredstringThe content hash of the spec.
rule.englishrequiredstringThe rule, as a sentence.
rule.createdAtrequiredstring
rule.createdByrequiredstring
rule.retiredAtrequiredstring | null
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
404No such route, or no such thing — for an admin. A tenant never reaches a 404 for something outside its scope; it reaches the 403 first.
FieldTypeMeaning
errorrequiredstring
404 example
{
  "error": "no route for GET /v1/nope"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
DELETE/v1/policies/{ruleId}Retire a ruleadmin key · details
Auth: admin keyretirePolicy

Stops the rule being evaluated. Its history stays. 404 when nothing by that id is live — retiring twice would record two retirements and report the second one's answer.

Parameters
FieldTypeMeaning
ruleIdrequiredpathstring
authorrequiredquerystring
logquerystringThe log whose rules to read. A tenant key may name only its own; the operator's key defaults to the operator's own log.
Responses
200Retired.
FieldTypeMeaning
okrequiredtrue
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
404Nothing live by that id.
FieldTypeMeaning
okrequiredfalse
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
Verify2 endpoints · browse

Verification and public keys — so anyone can check a bundle without asking us.

GET/v1/keysPublic keystenant or admin key · details
Auth: tenant or admin keypublicKeys

Every checkpoint-signing key this plane has published, so anyone holding a bundle can verify it without asking us. Key ids are content-addressed: two different keys cannot collide on one id, and a rotation never overwrites the key that signed older checkpoints.

Responses
200The keys.
FieldTypeMeaning
keysrequiredPublicKeyEntry[]
keys[].keyIdrequiredstring`auditant-<12 hex of sha256(pem)>` — content-addressed.
keys[].pemrequiredstringSPKI PEM.
keys[].notBeforestring
keys[].notAfterstring
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
POST/v1/verifyVerify a bundle someone sent backadmin key · details
Auth: admin keyverifyBundle

The same verifier an auditor runs from the CLI and the same one embedded in every bundle, reached over HTTP so the operator console does not carry a second copy. Read-only and stateless: nothing is stored, nothing is appended. Admin only, purely because it is an unbounded parse of caller-supplied JSON. A malformed bundle is a 400, not a verification failure — "that is not a bundle" and "this record was altered" are different findings, and reporting the first as the second would be an accusation.

Request body
FieldTypeMeaning
bundleVersionrequired"1.0.0"
logIdrequiredstring
fromrequiredstring
torequiredstring
exportedAtrequiredstring
eventsrequiredAuditEvent[]
checkpointsrequiredSignedCheckpoint[]
checkpoints[].checkpointrequiredCheckpoint
checkpoints[].checkpoint.originrequiredstring`auditant.dev/<logId>` — namespaced so two deployments cannot collide.
checkpoints[].checkpoint.treeSizerequiredinteger
checkpoints[].checkpoint.headHashrequiredstring
checkpoints[].checkpoint.timestamprequiredstring
checkpoints[].bodyrequiredstringThe exact bytes that were signed.
checkpoints[].keyIdrequiredstring
checkpoints[].signaturerequiredstringbase64 ECDSA P-256 over `body`.
checkpoints[].timestampTokenstringbase64 RFC 3161 token, once an authority has countersigned.
checkpoints[].wormAnchoredbooleanOperator-side: the copy landed in write-once storage. Not part of the signed body.
publicKeysrequiredPublicKeyEntry[]
publicKeys[].keyIdrequiredstring`auditant-<12 hex of sha256(pem)>` — content-addressed.
publicKeys[].pemrequiredstringSPKI PEM.
publicKeys[].notBeforestring
publicKeys[].notAfterstring
startHeadChainHead
startHead.logIdrequiredstring
startHead.treeSizerequiredinteger
startHead.headHashrequiredstring
verifierstringThe standalone verifier as source — one dependency-free .mjs. Save it and run it with plain Node.
readmestringAdded on export: how a stranger checks this bundle.
Responses
200The verification report, with degrees of proof rather than a boolean.
FieldTypeMeaning
okrequiredboolean
assurancerequired"broken" | "unanchored" | "signed" | "timestamped"Worst-first. `unanchored` is internally consistent but externally unproven.
chainrequiredobject
chain.okrequiredboolean
chain.verifiedrequiredintegerEvents verified before the first failure, or in total.
chain.headChainHead
chain.head.logIdrequiredstring
chain.head.treeSizerequiredinteger
chain.head.headHashrequiredstring
chain.failuresrequiredobject[]
chain.failures[].namerequiredstring
chain.failures[].messagerequiredstringNames the sequence number.
checkpointsrequiredobject[]
checkpoints[].treeSizerequiredinteger
checkpoints[].verificationrequiredobject
checkpoints[].verification.okrequiredboolean
checkpoints[].verification.signatureValidrequiredboolean
checkpoints[].verification.bodyMatchesrequiredboolean
checkpoints[].verification.timestampedboolean
checkpoints[].verification.reasonsrequiredstring[]
checkpoints[].coversChainrequiredbooleanThe checkpoint's head matches the recomputed chain at that size.
anchoredThroughSeqrequiredintegerEvents at or below this sequence are anchored. -1 when none are.
summaryrequiredstring[]
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
Tenants3 endpoints · browse

Self-serve provisioning and key minting. Provisioning never returns a key.

POST/v1/tenantsEnsure a tenant existsadmin key · details
Auth: admin keyprovisionTenant

Idempotent. The log id is derived from the email (t_<12 hex>/prod) — deterministic so a re-provision lands on the same log, opaque so it reveals nothing about the address. Never returns a key: creating the tenant and minting a credential are different acts with different audiences.

Request body
FieldTypeMeaning
emailrequiredstring
request
{
  "email": "alice@example.com"
}
Responses
200The tenant's log.
FieldTypeMeaning
logIdrequiredstring
createdrequiredbooleanTrue when this call created the tenant.
200 example
{
  "logId": "t_5c1b2a9e4f07/prod",
  "created": true
}
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
POST/v1/tenants/keyMint a tenant key, revoking every earlier oneadmin key · details
Auth: admin keymintKey

The plaintext key exists in this response and nowhere else — it is stored only as SHA-256. Revocation-on-mint is the point: one tenant, one live key, always. A tenant key cannot mint, including its own, because a leaked key that could rotate itself would be unrevokable by the person it was stolen from.

Request body
FieldTypeMeaning
emailrequiredstring
Responses
200Shown once.
FieldTypeMeaning
logIdrequiredstring
apiKeyrequiredstring
200 example
{
  "logId": "t_5c1b2a9e4f07/prod",
  "apiKey": "ak_…48 hex…"
}
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
GET/v1/tenants/meA tenant key introspects itselftenant key only · details
Auth: tenant key onlywhoAmI

Only a tenant key: an admin key is not a tenant and gets a 403 that says so.

Responses
200The key's tenant.
FieldTypeMeaning
logIdrequiredstring
emailrequiredstring | null
hasLiveKeyrequiredboolean
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403Not a tenant key.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "only a tenant key can introspect itself"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
Operator3 endpoints · browse

Reads across every tenant. Admin only, and never a secret.

GET/v1/admin/overviewEvery log, in one queryadmin key · details
Auth: admin keyadminOverview

Per-log totals, head, anchoring state, tenant email and halt flag, plus computed findings — each naming the log and the threshold it crossed. Provisioned tenants that have not sent an event yet are included; omitting them would make the console report a smaller, healthier deployment than the real one.

Responses
200The fleet.
FieldTypeMeaning
generatedAtrequiredstring
logsrequiredLogSummary[]
logs[].logIdrequiredstring
logs[].eventsrequiredinteger
logs[].agentsrequiredinteger
logs[].blockedrequiredinteger
logs[].pendingApprovalrequiredinteger
logs[].costTotalrequirednumber
logs[].costIncompleterequiredinteger
logs[].headSeqrequiredinteger | null
logs[].headHashrequiredstring | null
logs[].checkpointsrequiredinteger
logs[].unanchoredTailrequiredinteger
logs[].lastCheckpointAtrequiredstring | null
logs[].timestampedrequiredinteger
logs[].wormAnchoredrequiredinteger
logs[].emailrequiredstring | null
logs[].haltedrequiredboolean
totalsrequiredobject
totals.logsinteger
totals.eventsinteger
totals.agentsinteger
totals.blockedinteger
totals.pendingApprovalinteger
totals.costTotalnumber
totals.costIncompleteinteger
totals.unanchoredTailinteger
findingsrequiredstring[]
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/admin/tenantsWho is here, and whether they can writeadmin key · details
Auth: admin keyadminTenants

Key state, never a key or a key hash. A console that could read out a credential would make everyone with console access able to impersonate any tenant.

Responses
200Every tenant.
FieldTypeMeaning
tenantsrequiredTenantSummary[]
tenants[].logIdrequiredstring
tenants[].emailrequiredstring
tenants[].createdAtrequiredintegerEpoch milliseconds.
tenants[].hasLiveKeyrequiredboolean
tenants[].keysIssuedrequiredinteger
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
GET/v1/admin/healthWhat the plane is configured to do, and whether it is doing itadmin key · details
Auth: admin keyadminHealth

Three states, not two: off (deliberately disabled) and degraded (configured and failing) are different facts, and collapsing them trains an operator to ignore the indicator.

Responses
200The checks.
FieldTypeMeaning
checksrequiredobject[]
checks[].idrequired"signing-key" | "checkpointer" | "timestamp-authority" | "object-lock" | "api-keys" | "slack"
checks[].labelrequiredstring
checks[].staterequired"ok" | "degraded" | "off"
checks[].detailrequiredstring
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
Capture1 endpoint · browse
POST/v1/tracesRaw OTLP/HTTP traces — the zero-SDK pathkey or webhook secret · details
Auth: key or webhook secretingestOtlp

The standard OTLP traces path, so OTEL_EXPORTER_OTLP_ENDPOINT=<this plane> is the whole exporter configuration. Accepts protobuf or JSON, gzip or deflate (inflated body capped at 64 MB → 413). Authenticates with a bearer key OR the write-only webhook secret. The log comes from x-auditant-log, ?log=, the resource attribute auditant.log_id, or — for a tenant key — the key itself, then the same scoping rule as /v1/events. Spans are mapped through the same OpenInference/GenAI mapper as the SDKs; spans that are not evidence are read and not recorded, which is not a rejection.

Parameters
FieldTypeMeaning
logquerystringThe log to write, when not given as a header or resource attribute.
Request body
Responses
200An empty ExportTraceServiceResponse in the request's own encoding. `x-auditant-spans` and `x-auditant-accepted` headers carry the counts; `x-auditant-log` the log written.
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
413The compressed body inflates past 64 MB — send smaller batches.
415Unsupported content-encoding.
429Over the per-key ceiling for this class of route. Per process; wait `Retry-After` seconds.
  • Retry-After — Whole seconds until the window resets.
  • x-ratelimit-limit — The ceiling.
  • x-ratelimit-remaining — Always 0 here.
  • x-ratelimit-reset — RFC 3339.
FieldTypeMeaning
errorrequired"rate limited"
scoperequired"ingest" | "decide" | "export"
limitrequiredinteger
windowSecondsrequiredinteger
retryAfterSecondsrequiredinteger
resetAtrequiredstring
429 example
{
  "error": "rate limited",
  "scope": "decide",
  "limit": 12000,
  "windowSeconds": 60,
  "retryAfterSeconds": 41,
  "resetAt": "2026-08-20T10:01:00.000Z"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
Billing6 endpoints · browse
POST/v1/billing/webhook/razorpayRazorpay's word — HMAC over the raw bodykey or webhook secret · details
Auth: key or webhook secretrazorpayWebhook

No bearer: the request carries x-razorpay-signature, an HMAC-SHA256 over the raw body, verified in constant time against the configured secret(s). Redeliveries are idempotent by x-razorpay-event-id; a delivery whose apply failed releases its claim so the retry lands. Every plan transition is a chained event on the tenant's log.

Request body
Responses
200Received (applied, duplicate, stale or unparseable — the body says which).
FieldTypeMeaning
okboolean
appliedboolean
outcomestringapplied | stale | unmatched | ignored
duplicateboolean
401Invalid signature.
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
503This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
503 example
{
  "error": "policy decisions are not configured"
}
GET/v1/billingThe band, the agents counted against it, cap state, invoicestenant or admin key · details
Auth: tenant or admin keybillingSummary

Plan, period, agent usage vs cap, cap state, subscription and invoices for one log. Never a gate on the record: at or past the cap the plane still accepts every event. sync=1 asks the provider for the live subscription before answering.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
syncquerystring`1` to refresh from the provider first.
Responses
200The summary.
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
POST/v1/billing/checkoutBuy Team or Scale — the provider's hosted page, never a card formtenant or admin key · details
Auth: tenant or admin keystartCheckout

Creates the subscription at the provider and returns its hosted checkout page. The operator's own log is never billed (400); a log with a live subscription is told to change plan instead (409).

Request body
FieldTypeMeaning
logrequiredstring
planrequired"team" | "scale"
currencystringUSD or INR
emailstring
authorrequiredstringThe person acting, recorded on the chain.
Responses
200The hosted checkout.
FieldTypeMeaning
subscriptionIdstring
checkoutUrlstring
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
409A live subscription already exists — change the plan instead.
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
502The provider returned no checkout page.
POST/v1/billing/changeMove to another bandtenant or admin key · details
Auth: tenant or admin keychangePlan

Upgrades take effect now; downgrades are scheduled for the cycle end. Chained under the author.

Request body
FieldTypeMeaning
logrequiredstring
planrequired"team" | "scale"
authorrequiredstring
Responses
200Changed or scheduled.
FieldTypeMeaning
okboolean
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
409No live subscription to change.
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
POST/v1/billing/cancelEnd the paid plan at the cycle endtenant or admin key · details
Auth: tenant or admin keycancelPlan

The record stays exportable; the log returns to Self-serve when the cycle ends.

Request body
FieldTypeMeaning
logrequiredstring
authorrequiredstring
Responses
200Cancellation scheduled.
FieldTypeMeaning
okboolean
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
409No live subscription.
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
POST/v1/billing/grantSet a plan by hand — pilot, bank transfer, enterprise paperadmin key · details
Auth: admin keygrantPlan

Admin only: a tenant key that could grant itself Enterprise would make the price a suggestion. Chained on the tenant's log under the author.

Request body
FieldTypeMeaning
logrequiredstring
planrequired"free" | "team" | "scale" | "enterprise"
untilstringRFC 3339 or epoch ms; null/absent = open-ended
notestring
authorrequiredstring
Responses
200Granted.
FieldTypeMeaning
okboolean
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
Seats6 endpoints · browse
POST/v1/members/resolveWhich log and seat a verified email lands onadmin key · details
Auth: admin keyresolveSeat

Admin only — the dashboard's server asks on every request. Pending invitations are accepted; a listed operator (operatorLog) is seated as owner of the deployment's log; otherwise the newest seat wins; otherwise a fresh tenant is provisioned and its first sign-in is its owner. Every seat change is a chained event.

Request body
FieldTypeMeaning
emailrequiredstring
operatorLogstringThe deployment's own log, when the email is on the dashboard's operator list.
Responses
200The seat.
FieldTypeMeaning
logIdstring
role"owner" | "approver" | "auditor"
canobject
createdboolean
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
GET/v1/membersWho holds which seat on a logadmin key · details
Auth: admin keylistMembers

Admin only; author must hold a seat (read) on the log. Members and pending invitations (14-day expiry).

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
authorrequiredquerystringThe seated person asking.
Responses
200The roster.
FieldTypeMeaning
membersobject[]
members[].logIdstring
members[].emailstring
members[].role"owner" | "approver" | "auditor"
members[].grantedAtstring
members[].grantedBystring
invitesobject[]
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
DELETE/v1/membersRemove someone's seatadmin key · details
Auth: admin keyrevokeSeat

Owner only (the author). A log keeps at least one owner. Chained under the author before the row changes.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
emailrequiredquerystringWhose seat.
authorrequiredquerystringThe owner acting.
Responses
200Revoked.
FieldTypeMeaning
okboolean
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
404No such route, or no such thing — for an admin. A tenant never reaches a 404 for something outside its scope; it reaches the 403 first.
FieldTypeMeaning
errorrequiredstring
404 example
{
  "error": "no route for GET /v1/nope"
}
409A log must keep at least one owner.
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
POST/v1/members/invitesInvite someone to a seatadmin key · details
Auth: admin keyinvite

Owner only. Chained under the inviter the moment it is issued; the invitee is seated on their first verified sign-in within 14 days.

Request body
FieldTypeMeaning
logrequiredstring
emailrequiredstring
rolerequired"owner" | "approver" | "auditor"
authorrequiredstring
Responses
200Invited.
FieldTypeMeaning
inviteobject
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
409Already seated or already invited.
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
DELETE/v1/members/invites/{inviteId}Withdraw an invitationadmin key · details
Auth: admin keyrevokeInvite

Owner only. Chained under the author.

Parameters
FieldTypeMeaning
inviteIdrequiredpathstringFrom the roster.
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
authorrequiredquerystringThe owner acting.
Responses
200Withdrawn.
FieldTypeMeaning
okboolean
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
404No such route, or no such thing — for an admin. A tenant never reaches a 404 for something outside its scope; it reaches the 403 first.
FieldTypeMeaning
errorrequiredstring
404 example
{
  "error": "no route for GET /v1/nope"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
POST/v1/members/grantsMove an existing member to a different seatadmin key · details
Auth: admin keychangeRole

Owner only; the last owner cannot be demoted. Chained under the author before the row changes.

Request body
FieldTypeMeaning
logrequiredstring
emailrequiredstring
rolerequired"owner" | "approver" | "auditor"
authorrequiredstring
Responses
200Changed.
FieldTypeMeaning
memberobject
member.logIdstring
member.emailstring
member.role"owner" | "approver" | "auditor"
member.grantedAtstring
member.grantedBystring
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
404No such route, or no such thing — for an admin. A tenant never reaches a 404 for something outside its scope; it reaches the 403 first.
FieldTypeMeaning
errorrequiredstring
404 example
{
  "error": "no route for GET /v1/nope"
}
409A log must keep at least one owner.
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
Lifecycle7 endpoints · browse
GET/v1/lifecycleRetention, legal hold, and the price tables in forcetenant or admin key · details
Auth: tenant or admin keylifecycleConfig

The log's retention schedule (null = keep forever), whether a legal hold suspends every purge and erasure, and the versioned price tables.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The configuration.
FieldTypeMeaning
logIdstring
retentionDaysinteger
legalHoldboolean
holdReasonstring
updatedAtstring
updatedBystring
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
PUT/v1/lifecycle/retentionHow long payloads are keptadmin key · details
Auth: admin keysetRetention

Admin only. Whole days (1–36,500) or null to keep forever. Both sides of the change are chained under the author. Events and hashes are never purged — only payload content.

Request body
FieldTypeMeaning
logrequiredstring
daysinteger
authorrequiredstring
Responses
200Saved.
FieldTypeMeaning
configobject
config.logIdstring
config.retentionDaysinteger
config.legalHoldboolean
config.holdReasonstring
config.updatedAtstring
config.updatedBystring
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
PUT/v1/lifecycle/holdPlace or release a legal holdadmin key · details
Auth: admin keysetLegalHold

Admin only. While held, retention purges are suspended and explicit erasure is refused (409). Placement and release are chained with the reason.

Request body
FieldTypeMeaning
logrequiredstring
holdrequiredboolean
reasonstring
authorrequiredstring
Responses
200Saved.
FieldTypeMeaning
configobject
config.logIdstring
config.retentionDaysinteger
config.legalHoldboolean
config.holdReasonstring
config.updatedAtstring
config.updatedBystring
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
POST/v1/lifecycle/eraseTombstone payload content by hash — the chain staysadmin key · details
Auth: admin keyerasePayloads

Admin only. Records a chained payload_erased event naming the actor and reason FIRST, then destroys the content. Hashes and events remain, so the bundle still verifies and the verifier reports the erasure. A hash never held here is still tombstoned (Mode B custody). Refused under legal hold.

Request body
FieldTypeMeaning
logrequiredstring
hashesrequiredstring[]
actorrequiredstring
reasonrequiredstring
subjectstringThe data subject, if any.
Responses
200Erased.
FieldTypeMeaning
okboolean
logIdstring
erasedstring[]
alreadyErasedstring[]
eventIdsstring[]
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
409Legal hold suspends erasure.
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
POST/v1/lifecycle/purgeRun the retention purge nowadmin key · details
Auth: admin keypurgeNow

Admin only. For one log or every log with a schedule. Records the purge on the chain before destroying anything; skips logs under hold.

Request body
FieldTypeMeaning
logstringOmit to purge every scheduled log.
Responses
200Run.
FieldTypeMeaning
resultsobject[]
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
GET/v1/lifecycle/payloadA payload this log holds, by hashtenant or admin key · details
Auth: tenant or admin keygetPayload

Scoped by log in the query itself — another log's copy of the same bytes is not this log's payload.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
hashrequiredquerystringsha256:<64 hex>
Responses
200The payload, or its tombstone.
FieldTypeMeaning
hashstring
logIdstring
bodystring
storedAtstring
erasedAtstring
erasedBystring
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
404No such route, or no such thing — for an admin. A tenant never reaches a 404 for something outside its scope; it reaches the 403 first.
FieldTypeMeaning
errorrequiredstring
404 example
{
  "error": "no route for GET /v1/nope"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
PUT/v1/lifecycle/payloadHold a payload, content-addressedtenant or admin key · details
Auth: tenant or admin keyputPayload

The content must hash to the given key. Re-storing an erased hash is refused (409). Keyed by (log, hash).

Request body
FieldTypeMeaning
logrequiredstring
hashrequiredstring
bodyrequiredstring
Responses
200Stored, or already held.
FieldTypeMeaning
hashstring
storedboolean
deduplicatedboolean
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
409This hash was erased on this log; erased content cannot be restored.
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
Readings11 endpoints · browse
POST/v1/policies/simulateReplay the record through a draft ruleadmin key · details
Auth: admin keysimulatePolicy

Admin only, reads only. The draft is validated like a saved rule, then evaluated by the SAME matcher the live engine runs against the newest window of the log (up to 100,000 events). Returns would-have-blocked / would-have-held counts with the exact events, what was already stopped, and caveats (context fields the record never carried are blind spots, not zero hits).

Request body
FieldTypeMeaning
logrequiredstring
rulerequiredobjectA RuleSpec, as for PUT /v1/policies.
limitintegerEvents to replay, newest first (default 500).
Responses
200The simulation.
400The draft is invalid — `path` names the field.
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/agentsEvery agent the log has heard fromtenant or admin key · details
Auth: tenant or admin keyagentIndex

One row per agent id: planes seen, action and tool counts, spend (a floor when unpriced), last seen, quiet/live. Read from the newest window of the chain.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The index.
FieldTypeMeaning
agentsobject[]
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/agents/{agentId}One agent's cardtenant or admin key · details
Auth: tenant or admin keyagentCard

Planes, actions, tools called, models, spend, the rules that bind it (three-valued: binds / cannot / would need a field the record lacks), sessions, effective budget, and its drift reading.

Parameters
FieldTypeMeaning
agentIdrequiredpathstringThe actor id as recorded.
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The card.
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
404No such route, or no such thing — for an admin. A tenant never reaches a 404 for something outside its scope; it reaches the 403 first.
FieldTypeMeaning
errorrequiredstring
404 example
{
  "error": "no route for GET /v1/nope"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/discoveryActors heard from that nobody introducedtenant or admin key · details
Auth: tenant or admin keydiscovery

Never-seen actor ids, gateway-seen agents with no SDK session, and OTel services emitting without a registration — from the chain only. No device sensor and no network tap: an agent that never reached this plane is not here.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The reading.
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/readinessPer-regime readiness, denominator attachedtenant or admin key · details
Auth: tenant or admin keyreadiness

For each compliance regime: satisfied / evidenceable / watching / outside, the percentage (null when nothing is evidenceable), and the open obligations with their todo. Arithmetic over compliance(), never a vanity score.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The report.
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/driftBehaviour against each agent's own baselinetenant or admin key · details
Auth: tenant or admin keydrift

Per agent: an action-profile baseline over a trailing window and today's deviations (new action, plane gone, volume collapse or burst) as findings with deductions. Signalling, not intervention — and an agent with no actions today is quiet, not drifting.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The reading.
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/packsRegulation-mapped rule setsadmin key · details
Auth: admin keylistPacks

Admin only. Each pack (EU AI Act Art 12, FINRA supervision, Colorado SB 26-189 …) with its rules and whether each is already installed.

Parameters
FieldTypeMeaning
logquerystringThe log whose rules to read. A tenant key may name only its own; the operator's key defaults to the operator's own log.
Responses
200The packs.
FieldTypeMeaning
packsobject[]
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
POST/v1/packs/{packId}/installInstall a pack, every rule in monitor modeadmin key · details
Auth: admin keyinstallPack

Admin only. Each rule goes through the rule store like a hand-written one — chained under the author, monitor mode forced, an existing rule id never overwritten.

Parameters
FieldTypeMeaning
packIdrequiredpathstringA pack id from GET /v1/packs.
Request body
FieldTypeMeaning
authorrequiredstring
logstringThe log this belongs to and is chained on. Defaults to the operator's own log; a tenant key may name only its own.
Responses
200Installed.
FieldTypeMeaning
installedstring[]
skippedstring[]
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
404No such route, or no such thing — for an admin. A tenant never reaches a 404 for something outside its scope; it reaches the 403 first.
FieldTypeMeaning
errorrequiredstring
404 example
{
  "error": "no route for GET /v1/nope"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
GET/v1/trustThis log's public trust page configurationtenant or admin key · details
Auth: tenant or admin keygetTrustPage

The slug, whether it is public, and which sections it shows. Nothing here is a figure — the figures are read when the page is.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The configuration.
FieldTypeMeaning
pageobject
page.logIdstring
page.slugstring
page.publicboolean
page.labelstring
page.sectionsstring[]
page.updatedAtstring
page.updatedBystring
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
PUT/v1/trustPublish, unpublish, retitle or scope the pagetenant or admin key · details
Auth: tenant or admin keysetTrustPage

Slug ^[a-z0-9][a-z0-9-]{1,39}$. The flip is chained under the author BEFORE the row changes; a no-op patch chains nothing. A slug another log holds is refused (409-class 400 with path).

Request body
FieldTypeMeaning
logrequiredstring
publicboolean
slugstring
labelstring
sectionsstring[]
authorrequiredstring
Responses
200Saved.
FieldTypeMeaning
pageobject
page.logIdstring
page.slugstring
page.publicboolean
page.labelstring
page.sectionsstring[]
page.updatedAtstring
page.updatedBystring
400Invalid — `path` names the field.
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
GET/v1/trust/{slug}A public trust page, resolved by slugadmin key · details
Auth: admin keyresolveTrustPage

Admin key only — the marketing host calls this on the reader's behalf. Private and absent slugs both 404 with the same body. The response never carries who edited the page. Cached for 30 s per slug; every PUT invalidates.

Parameters
FieldTypeMeaning
slugrequiredpathstringThe public slug.
Responses
200The page's data, read now.
FieldTypeMeaning
pageobject
page.logIdstring
page.slugstring
page.publicboolean
page.labelstring
page.sectionsstring[]
statsobject
coverageobject
policiesobject[]
haltedboolean
readinessobject
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
404No such route, or no such thing — for an admin. A tenant never reaches a 404 for something outside its scope; it reaches the 403 first.
FieldTypeMeaning
errorrequiredstring
404 example
{
  "error": "no route for GET /v1/nope"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
Egress4 endpoints · browse
GET/v1/egressDestinations, deliveries and dead letters for one logtenant or admin key · details
Auth: tenant or admin keyegressOverview

Every configured target (secrets never returned — hasSecret only), delivery stats, the dead-letter list, and the digest's state.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The overview.
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
POST/v1/egress/targetsAdd a webhook, Splunk HEC or Datadog destinationtenant or admin key · details
Auth: tenant or admin keycreateEgressTarget

HTTPS to a public host only (loopback, link-local, private, CGNAT, multicast, IPv4-mapped and NAT64 literals and bare hostnames are refused). Datadog v1 intake URLs (key in the path) are refused. The secret is shown once in the response and never again. Chained under the author.

Request body
FieldTypeMeaning
logrequiredstring
kindrequired"webhook" | "splunk" | "datadog"
namerequiredstring
urlrequiredstring
eventsrequiredstring | string[]Event types, or `*`.
tokenstringSplunk/Datadog token; ignored for webhooks.
authorrequiredstring
Responses
200Created.
FieldTypeMeaning
targetobject
secretstringShown once.
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
PUT/v1/egress/digestTurn the email digest on or offtenant or admin key · details
Auth: tenant or admin keysetDigest

Daily or weekly, to named recipients, via Resend's HTTP API. 501 when no mailer is configured on the plane (AUDITANT_RESEND_KEY + AUDITANT_MAIL_FROM).

Request body
FieldTypeMeaning
logrequiredstring
cadencerequired"off" | "daily" | "weekly"
recipientsstring[]
authorrequiredstring
Responses
200Saved.
FieldTypeMeaning
digestobject
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
POST/v1/egress/digest/sendSend the digest nowtenant or admin key · details
Auth: tenant or admin keysendDigestNow

One send, outside the schedule, to the configured recipients.

Request body
FieldTypeMeaning
logrequiredstring
Responses
200Queued.
FieldTypeMeaning
okboolean
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
501This plane is not configured for that (no budget store, no rule store, no self-serve tenants). Refused rather than degraded.
FieldTypeMeaning
errorrequiredstring
501 example
{
  "error": "policy decisions are not configured"
}
Standards4 endpoints · browse
GET/v1/aiucThe AIUC-1 evidence packtenant or admin key · details
Auth: tenant or admin keyaiucPack

Every AIUC-1 control the chain can evidence, control id → chain-derived proof with sequence numbers, and an honest not-evidenced for the rest. Deterministic for a given log and moment; empty logs say so rather than citing events that do not exist.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The pack.
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/receipts/{receiptId}One per-action signed receipttenant or admin key · details
Auth: tenant or admin keygetReceipt

The receipt body verbatim as it was signed (RFC 8785 canonical form, ECDSA P-256 with the checkpoint key), its signature and key id, and the public keys — enough to verify offline.

Parameters
FieldTypeMeaning
receiptIdrequiredpathstringFrom a /v1/decide response.
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
Responses
200The receipt.
FieldTypeMeaning
receiptIdstring
hashstring
keyIdstring
signaturestring
bodystring
receiptobject
publicKeysobject[]
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
404No such route, or no such thing — for an admin. A tenant never reaches a 404 for something outside its scope; it reaches the 403 first.
FieldTypeMeaning
errorrequiredstring
404 example
{
  "error": "no route for GET /v1/nope"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/telemetryOCSF projection of decisions — a pull, not a streamtenant or admin key · details
Auth: tenant or admin keytelemetry

Decisions and actions as OCSF API Activity (class 6003) with the dictionary's own disposition_id values (Allowed 1, Blocked 2, Delayed 14, Challenge 23, Other 99). Filter by action type, decision (including DEFER), agent and time. Paginate with limit.

Parameters
FieldTypeMeaning
logrequiredquerystringThe log id, e.g. `tenant_acme/prod`. A tenant key may only name its own; anything else is a flat 403.
actionTypequerystringtool_call | model_call | decision …
decisionquerystringallow | deny | pending_approval | defer | modify
agentquerystringAn actor id.
fromquerystringRFC 3339 lower bound.
toquerystringRFC 3339 upper bound.
limitqueryintegerMax events.
Responses
200The events.
FieldTypeMeaning
eventsobject[]
400The request is malformed: a required field is missing, a value is out of bounds, the body is not JSON or exceeds 8 MiB, or an event failed schema validation — the message names the field.
FieldTypeMeaning
errorrequiredstring
400 example
{
  "error": "ts must be RFC 3339 with an explicit offset (field: ts)"
}
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}
GET/v1/pricesThe versioned model price tabletenant or admin key · details
Auth: tenant or admin keyprices

Which table was in force at a moment, and — with model — the per-1M-token prices that model resolves to, with the candidate names tried. No key needed for the table; prices are public numbers.

Parameters
FieldTypeMeaning
atquerystringRFC 3339 — which table was in force then (default now).
modelquerystringA model name as it arrives; resolved through the candidate list.
Responses
200The table.
FieldTypeMeaning
tablesobject[]
priceobject
401No usable credential.
FieldTypeMeaning
errorrequiredstring
401 example
{
  "error": "unauthorized"
}
403The credential does not reach that. Deliberately flat: a tenant key asking about another tenant's log gets this whether or not that log exists, so nothing can be learned by asking.
FieldTypeMeaning
errorrequiredstring
403 example
{
  "error": "forbidden"
}
500Something failed on our side. Never a stack trace; the real error reaches the operator's error tracker.
FieldTypeMeaning
errorrequiredstring
500 example
{
  "error": "internal error"
}