Every meaningful action gets an audit event: hashed on receipt, Merkle-batched, and
anchored on Solana. The lifecycle is visible on the record itself:
received → batched → anchored.
What lands in an agent’s journal without you doing anything:
| Event type | Written by |
|---|---|
control.decision, control.decision.completed, control.decision.receipt | the gate: every decision, its completion and the retained receipt |
payment.authorized, payment.rejected | the mandate ledger: each allow or refusal of POST …/mandates/<id>/authorize |
mandate.created, mandate.version_created | a mandate issued, and every change of its terms (commitment only, never the ceilings) |
agent.revoked | the kill switch |
Events you ingest yourself (below) sit next to them under the same agent.
Read an agent’s journal
GET /v1/organizations/<org>/agents/<agent_id>/events?limit=50&offset=0Newest first. Each item carries event_type, status, payload_hash, batch_id and the
Merkle fields once batched.
Ingest an event
curl -X POST https://api.regentprotocol.org/v1/organizations/<org>/audit/events \
-H "Authorization: Bearer rgnt_..." -H "content-type: application/json" \
-d '{
"event_id": "action-<jti>",
"agent_id": "agent_688b10bc62aef…",
"event_type": "action.completed",
"payload": {"amount": "25", "currency": "USD", "authorization_jti": "…"}
}'event_id— your idempotency key (≤64 chars). Re-sending the same id is safe.event_type— dotted, e.g.action.completed,order.shipped.payload— arbitrary JSON; it is hashed (payload_hash) and stored.
Best practice: put the decision id or the authorization jti into the payload — that is
what ties the action to its permission when someone reconstructs the case later.
Read an event
GET /v1/organizations/<org>/events/<event_id>{
"event_id": "action-…",
"agent_id": "agent_688b…",
"event_type": "action.completed",
"payload_hash": "…",
"status": "anchored",
"batch_id": "…",
"merkle_index": 3,
"merkle_proof": ["…"],
"received_at": "…",
"anchored_at": "…"
}The event must belong to an agent of your organization; otherwise 404.
Verify a proof
POST /v1/organizations/<org>/events/<event_id>/verify
GET /v1/organizations/<org>/audit/events/<event_id>/proof
GET /v1/organizations/<org>/batches/<batch_id>verify recomputes the event’s Merkle path against its batch root and answers
verified: true|false. proof returns the same path together with the batch’s anchor so a
reader can recompute it elsewhere. The batch record carries the on-chain commitment:
anchor_tx (the Solana signature; anchor_chain: solana), solana_explorer_url, and the
audit-chain position seq / chain_tx / chain_head with Regent’s signed checkpoint.
The field arbitrum_tx_hash holds the same signature under its historical name and stays
for older clients.
For a file a third party can check offline — the event, its proof, the checkpoint, the epoch and the keys — use the evidence bundle:
GET /v1/organizations/<org>/audit/events/<event_id>/bundleAn auditor can go further and check the anchor independently against Solana — the end-to-end recipe is in Verifying on-chain. That page is the point of the whole design: the trail is checkable without trusting Regent or the operator.
On devnet, batches seal and anchor within a minute of ingestion.
Verified on production: 2026-10-13.