Audit API
Every registered /v1 route has mandatory audit metadata. Before body parsing,
authentication, authorization, or handler execution, the API writes an
api_request record. If that write fails, the handler does not run and the
response is 503 DEPENDENCY_FAILURE.
The request record starts with outcome incomplete. Successful finalization
adds the response status, end time, duration, and one of success,
client_error, or server_error. A process failure or finalization failure
leaves the incomplete record visible. Mutations also write an entity_change
event in the same database transaction as the changed entity.
Platform administrators query global events through GET /v1/audit-logs.
Platform and tenant administrators query safely scoped tenant events through
GET /v1/tenants/{tenantNumber}/audit-logs. Tenant queries include only records
whose tenant scope was established after successful authorization. The current
audit query excludes its own still-incomplete request record.
Queries default to the previous 24 hours. Explicit from and to values must
be supplied together and may span no more than 31 days. Available filters are
eventType, action, actorId, entityType, entityId, correlationId,
method, route, and statusCode. Results are ordered by occurredAt and the
unique Audit ID, newest first. A page contains at most 25 events, optional
nextCursor, and no exact total. The first page fixes to as the upper
investigation anchor. Every continuation must retain this anchor, scope, and
all filters; an incompatible cursor returns 400 VALIDATION_FAILED. A fresh
request without a cursor starts a new investigation. Retention is seven calendar
years.
Audit records never store request or response bodies, query values, passwords, tokens, cookies, authorization headers, IP addresses, user-agent contents, or raw login identifiers. Route templates are stored instead of raw URLs, and entity-change metadata contains field names rather than PII snapshots.