Every state-changing API call is recorded in a hash-chained audit log. Each entry references the hash of the previous entry, so any tampering is detectable.
List audit entries
GET /v1/audit?from=2026-04-01T00:00:00Z&to=2026-04-30T23:59:59Z&actor=usr_...&action=transaction.create&page=1&per_page=100
Filters
| Param | Type | Description |
|---|
from | RFC 3339 | Inclusive start time |
to | RFC 3339 | Exclusive end time |
actor | string | User or credential ID |
action | string | Action name (e.g. transaction.create, policy.update) |
resource_type | string | One of the 12 RBAC resources |
resource_id | string | Specific resource |
request_id | string | API Request-Id header value |
Response 200
{
"entries": [
{
"id": "aud_01HXYZ...",
"tenant_id": "tnt_...",
"actor_id": "usr_...",
"actor_type": "user",
"action": "transaction.create",
"resource_type": "transaction",
"resource_id": "tx_...",
"request_id": "req_...",
"ip": "203.0.113.10",
"user_agent": "qustody-go/1.4.2",
"metadata": {"vault_id": "vault_...", "amount_wei": "1000000000000000000"},
"prev_hash": "sha256:...",
"entry_hash": "sha256:...",
"created_at": "2026-04-27T10:15:00Z"
}
],
"page": 1,
"per_page": 100,
"total": 4823
}
Verify the chain
Recomputes hashes for the requested range and reports any tampering.
GET /v1/audit/verify?from=2026-04-01T00:00:00Z&to=2026-04-30T23:59:59Z
Response 200 (intact)
{
"from": "2026-04-01T00:00:00Z",
"to": "2026-04-30T23:59:59Z",
"entries_checked": 4823,
"first_entry_hash": "sha256:...",
"last_entry_hash": "sha256:...",
"broken_at": null,
"valid": true
}
Response 200 (tampering detected)
{
"entries_checked": 4823,
"broken_at": "aud_01HXYZ...",
"valid": false
}
Run GET /v1/audit/verify from an out-of-band system on a schedule (e.g. daily). Persist last_entry_hash to detect retroactive deletions.
Required permissions
| Endpoint | Permission |
|---|
GET /v1/audit | audit:read |
GET /v1/audit/verify | audit:read |
The compliance_officer and admin roles have this permission by default; viewer does not.