Skip to content

Read the tenant evidence ledger

GET
/v1/audit
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.

X-Olivares-Tenant
string format: uuid

Target tenant id; required when the principal can act in more than one tenant.

from
integer
default: 1

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.

limit
integer
default: 50 >= 1 <= 1000

Maximum number of items to return.

exclude_action
Array<string>

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.

OK

Media type application/json
object
cursor
string
has_more
required
boolean
head_seq
required

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.

integer
items
required
Array<object>
object
action
required
string
actor
required
string
actor_kind
required
string
hash
required

Hex-encoded SHA-256 of this event

string
id
required
string format: uuid
occurred_at
required
string format: date-time
prev_hash
required

Hex-encoded SHA-256 of the previous event

string
seq
required
integer format: int64
sig

Base64-encoded Ed25519 signature

string
target_id
string
target_kind
string
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

Media type application/json
object
error
required
object
code
required
string
message
required
string
Example generated
{
"error": {
"code": "example",
"message": "example"
}
}

Unauthenticated

Media type application/json
object
error
required
object
code
required
string
message
required
string
Example generated
{
"error": {
"code": "example",
"message": "example"
}
}

Forbidden

Media type application/json
object
error
required
object
code
required
string
message
required
string
Example generated
{
"error": {
"code": "example",
"message": "example"
}
}

Not found

Media type application/json
object
error
required
object
code
required
string
message
required
string
Example generated
{
"error": {
"code": "example",
"message": "example"
}
}

Conflict / setup required

Media type application/json
object
error
required
object
code
required
string
message
required
string
Example generated
{
"error": {
"code": "example",
"message": "example"
}
}

Rate limited

Media type application/json
object
error
required
object
code
required
string
message
required
string
Example generated
{
"error": {
"code": "example",
"message": "example"
}
}