Admin audit log viewer
GET /admin/audit
Cursor-paginated read of the system-wide audit event log. Every filter is optional; combining them narrows the result. Returns the rows ordered newest-first along with the total count (cursor-independent) so the UI can render a “X events matched” header and a next-page button.
next_cursor is an opaque base64-url token wrapping the last
row’s (occurred_at, id) pair. Pass it back as the cursor
query param to fetch the next page. Null when the response
is the final page.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Query Parameters
Section titled “Query Parameters ”ISO-8601 lower bound on occurred_at (inclusive).
ISO-8601 upper bound on occurred_at (inclusive).
Responses
Section titled “ Responses ”Page of audit events + total count.
object
One row from audit_events. metadata is the
typed JSONB blob whose shape varies per event_type — see
app/internal/audit/events.go for the per-type schemas. The
UI renders well-known event types as structured changesets
(“active → disabled”, etc.) and falls back to JSON dump for
the rest.
object
Actor IP address — PERSONAL DATA, and returned only to
callers holding system.audit.pii.read on top of
system.audit.read (#425).
Absent from the response entirely for callers without that capability, rather than blanked, so an empty value always means “no IP recorded” and never “you may not see it”. Consumers must already tolerate absence: the field has always been optional and nullable, since not every event carries an address.
Typed per event_type — see audit/events.go.
object
Total rows matching the filter (cursor-independent).
Authentication required, missing, or invalid
object
Human-readable error summary
Example
the request could not be completedExample
{ "error": "authentication required: sign in and retry with a valid session or API token"}Authenticated but missing required capabilities
object
Human-readable error summary
Example
the request could not be completed