Read the tenant evidence ledger
const url = 'https://example.com/v1/audit?from=1&limit=50';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://example.com/v1/audit?from=1&limit=50' \ --header 'Authorization: Bearer <token>'Reads a page of the tenant evidence ledger. Paging is keyset by SEQUENCE, not a cursor, and the page runs FORWARDS from ?from in ascending sequence order — oldest first. The response carries head_seq, the chain tip, which is what a caller pairs with ?from to address the newest events.
Authorizations
Section titled “ Authorizations ”Parameters
Section titled “ Parameters ”Header Parameters
Section titled “ Header Parameters ”Target tenant id; required when the principal can act in more than one tenant.
Query Parameters
Section titled “ Query Parameters ”Start from this sequence number. The page runs FORWARDS from it, in ascending sequence order; pair it with head_seq to address the newest events.
Maximum number of items to return.
Omit events whose action starts with this prefix. Repeatable: give it once per action family to leave out. It uses the SAME prefix rule as action, and it filters only what is RETURNED — the ledger still records every event, and a request without this parameter still returns them all. Its use is a caller that must not be shown its own footprint: the console’s notification bell passes exclude_action=audit.read so that reading the ledger does not itself become the newest activity in it.
Responses
Section titled “ Responses ”OK
object
The highest sequence number this tenant’s ledger has RECORDED, and 0 when it has never recorded one. from pages FORWARDS (events come back in ascending sequence order), so this is the only field that addresses the END of the chain: request from=max(1, head_seq-N+1)&limit=N and reverse the page to show the newest activity. Read the two bounds of that promise exactly, because a caller who assumes more will be wrong on a real ledger. (1) The window is N SEQUENCE POSITIONS, not N rows: a chain that declares a gap (an in-chain audit.gap marker) skips positions, so the page can come back SHORTER than N with older events still present below it. (2) head_seq is measured before this request’s own self-audit event joins the chain, and it is never behind the highest sequence in items — but it does not identify the exact snapshot the page was read from, because a concurrent append can land between the two reads. It is the RECORDED tip, which on a ledger emptied under a live head is deliberately not the last addressable row.
object
Hex-encoded SHA-256 of this event
Hex-encoded SHA-256 of the previous event
Base64-encoded Ed25519 signature
Example generated
{ "cursor": "example", "has_more": true, "head_seq": 1, "items": [ { "action": "example", "actor": "example", "actor_kind": "example", "hash": "example", "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "occurred_at": "2026-04-15T12:00:00Z", "prev_hash": "example", "seq": 1, "sig": "example", "target_id": "example", "target_kind": "example" } ]}Bad request
object
object
With code module_not_enabled: the namespace of the module this node does not run.
Example generated
{ "error": { "code": "example", "message": "example", "module": "example" }}Unauthenticated
object
object
With code module_not_enabled: the namespace of the module this node does not run.
Example generated
{ "error": { "code": "example", "message": "example", "module": "example" }}Forbidden
object
object
With code module_not_enabled: the namespace of the module this node does not run.
Example generated
{ "error": { "code": "example", "message": "example", "module": "example" }}Not found
object
object
With code module_not_enabled: the namespace of the module this node does not run.
Example generated
{ "error": { "code": "example", "message": "example", "module": "example" }}Conflict / setup required
object
object
With code module_not_enabled: the namespace of the module this node does not run.
Example generated
{ "error": { "code": "example", "message": "example", "module": "example" }}Rate limited
object
object
With code module_not_enabled: the namespace of the module this node does not run.
Example generated
{ "error": { "code": "example", "message": "example", "module": "example" }}