Skip to main content

Admin API: Audit

Operations on audit in the Odudu admin API, one section each. Every request carries a bearer token; the index says which audience it needs and how a refusal is shaped.

GET /admin/tenants/{tenant}/audit​

Requires the "view-audit" capability.

Every read here runs under a five second statement timeout. Two filters whose rows are each common but that few rows share (an action and an actor, say) make Postgres read all of the cheaper one, so past the bound the read is refused with 400 of type about:blank#audit-query-too-broad: narrow it with from and to, which lead the index, or drop a filter. from and to are instants from 1970 to 9999, refused with 400 otherwise. Newest first, by an opaque cursor bound to the filters it was issued under.

Path parameters​

NameTypeRequiredDetails
tenantstringyesThe tenant being administered, addressed by name.

Query parameters​

NameTypeRequiredDetails
cursorstringnoThe next value of the previous page, to continue after it.
limitintegernoHow many items to return. A value over 200 is treated as 200; the default is 50. Constraints: at least 1.
event_typestringnoOnly events of this type. Constraints: one of admin_mutation, admin_access, authentication, session, token, credential.
actor_subject_idstringnoOnly events done by this subject. Constraints: a UUID.
resource_typestringnoOnly events on this kind of resource, such as client. Constraints: at least 1 character, at most 256 characters.
resource_idstringnoOnly events on this resource; needs resource_type. Constraints: at least 1 character, at most 256 characters.
actionstringnoOnly events with this action, such as client.create. Constraints: at least 1 character, at most 256 characters.
outcomestringnoOnly events with this outcome. Constraints: one of allowed, refused, failed.
fromstringnoOnly events at or after this instant. Constraints: an ISO 8601 date and time.
tostringnoOnly events before this instant. Constraints: an ISO 8601 date and time.

Responses​

200 OK​

Body: application/json

FieldTypeRequiredDetails
itemsarray of objectyesThe entries of this answer.
items[]objectyes
items[].idstringyesThe event’s identifier.
items[].occurred_atstringyesWhen it happened.
items[].event_typestringyesThe kind of event: admin_mutation, admin_access, authentication, session, token or credential.
items[].actionstringyesWhat happened, such as client.create or login.password.
items[].outcomestringyesallowed, refused or failed. Constraints: one of allowed, refused, failed.
items[].actor_tenant_idstring or nullyesThe tenant of whoever did it, or null.
items[].actor_subject_idstring or nullyesThe subject who did it, or null.
items[].actor_client_idstring or nullyesThe client it was done through, or null.
items[].actor_namestring or nullyesThe actor’s username, or null.
items[].actor_originstring or nullyesWhere the actor comes from: this tenant, the system tenant, or other-tenant. Constraints: one of tenant, system, other-tenant.
items[].resource_typestring or nullyesThe kind of thing acted on, or null.
items[].resource_idstring or nullyesThe thing acted on, or null.
items[].request_idstring or nullyesThe x-request-id of the request, to correlate with logs.
items[].ipstring or nullyesThe address the server saw the request come from.
items[].detailobjectyesExtra facts about the event. Never a secret, a token or a password. Constraints: other fields accepted.
nextstringnoAn opaque cursor for the next page; absent on the last page.
{
"items": [
{
"id": "0192f5c4-1d4e-7a3b-9c11-5a2f0e6b7c01",
"occurred_at": "2026-10-19T09:30:00.000Z",
"event_type": "admin_mutation",
"action": "client.create",
"outcome": "allowed",
"actor_tenant_id": "0192f5c4-0000-7000-8000-000000000001",
"actor_subject_id": "0192f5c4-0000-7000-8000-000000000002",
"actor_client_id": "0192f5c4-0000-7000-8000-000000000003",
"actor_name": "ada",
"actor_origin": "tenant",
"resource_type": "client",
"resource_id": "0192f5c4-0000-7000-8000-000000000004",
"request_id": "0192f5c4-0000-7000-8000-000000000005",
"ip": "203.0.113.7",
"detail": {}
}
]
}

401 RFC 9457 problem details​

Body: application/problem+json, an RFC 9457 problem document described under problem details.

403 RFC 9457 problem details​

Body: application/problem+json, an RFC 9457 problem document described under problem details.

GET /admin/tenants/{tenant}/audit/count​

Requires the "view-audit" capability.

Every read here runs under a five second statement timeout. Two filters whose rows are each common but that few rows share (an action and an actor, say) make Postgres read all of the cheaper one, so past the bound the read is refused with 400 of type about:blank#audit-query-too-broad: narrow it with from and to, which lead the index, or drop a filter. from and to are instants from 1970 to 9999, refused with 400 otherwise.

Path parameters​

NameTypeRequiredDetails
tenantstringyesThe tenant being administered, addressed by name.

Query parameters​

NameTypeRequiredDetails
event_typestringnoOnly events of this type. Constraints: one of admin_mutation, admin_access, authentication, session, token, credential.
actor_subject_idstringnoOnly events done by this subject. Constraints: a UUID.
resource_typestringnoOnly events on this kind of resource, such as client. Constraints: at least 1 character, at most 256 characters.
resource_idstringnoOnly events on this resource; needs resource_type. Constraints: at least 1 character, at most 256 characters.
actionstringnoOnly events with this action, such as client.create. Constraints: at least 1 character, at most 256 characters.
outcomestringnoOnly events with this outcome. Constraints: one of allowed, refused, failed.
fromstringnoOnly events at or after this instant. Constraints: an ISO 8601 date and time.
tostringnoOnly events before this instant. Constraints: an ISO 8601 date and time.

Responses​

200 OK​

Body: application/json

FieldTypeRequiredDetails
countintegeryesHow many items match, up to a cap.
cappedbooleanyesTrue when more match than count says, because counting stops at the cap.

401 RFC 9457 problem details​

Body: application/problem+json, an RFC 9457 problem document described under problem details.

403 RFC 9457 problem details​

Body: application/problem+json, an RFC 9457 problem document described under problem details.

GET /admin/tenants/{tenant}/audit/export​

Requires the "view-audit" capability.

Every read here runs under a five second statement timeout. Two filters whose rows are each common but that few rows share (an action and an actor, say) make Postgres read all of the cheaper one, so past the bound the read is refused with 400 of type about:blank#audit-query-too-broad: narrow it with from and to, which lead the index, or drop a filter. from and to are instants from 1970 to 9999, refused with 400 otherwise. Every row the same filters list, newest first, one JSON object per line, built in full before it is sent rather than streamed. Refused whole with 413 past 10,000 rows rather than cut short. Audited as audit.export.

Path parameters​

NameTypeRequiredDetails
tenantstringyesThe tenant being administered, addressed by name.

Query parameters​

NameTypeRequiredDetails
event_typestringnoOnly events of this type. Constraints: one of admin_mutation, admin_access, authentication, session, token, credential.
actor_subject_idstringnoOnly events done by this subject. Constraints: a UUID.
resource_typestringnoOnly events on this kind of resource, such as client. Constraints: at least 1 character, at most 256 characters.
resource_idstringnoOnly events on this resource; needs resource_type. Constraints: at least 1 character, at most 256 characters.
actionstringnoOnly events with this action, such as client.create. Constraints: at least 1 character, at most 256 characters.
outcomestringnoOnly events with this outcome. Constraints: one of allowed, refused, failed.
fromstringnoOnly events at or after this instant. Constraints: an ISO 8601 date and time.
tostringnoOnly events before this instant. Constraints: an ISO 8601 date and time.

Responses​

200 OK​

Body: application/x-ndjson

FieldTypeRequiredDetails
idstringyesThe event’s identifier.
occurred_atstringyesWhen it happened.
event_typestringyesThe kind of event: admin_mutation, admin_access, authentication, session, token or credential.
actionstringyesWhat happened, such as client.create or login.password.
outcomestringyesallowed, refused or failed. Constraints: one of allowed, refused, failed.
actor_tenant_idstring or nullyesThe tenant of whoever did it, or null.
actor_subject_idstring or nullyesThe subject who did it, or null.
actor_client_idstring or nullyesThe client it was done through, or null.
actor_namestring or nullyesThe actor’s username, or null.
actor_originstring or nullyesWhere the actor comes from: this tenant, the system tenant, or other-tenant. Constraints: one of tenant, system, other-tenant.
resource_typestring or nullyesThe kind of thing acted on, or null.
resource_idstring or nullyesThe thing acted on, or null.
request_idstring or nullyesThe x-request-id of the request, to correlate with logs.
ipstring or nullyesThe address the server saw the request come from.
detailobjectyesExtra facts about the event. Never a secret, a token or a password. Constraints: other fields accepted.

401 RFC 9457 problem details​

Body: application/problem+json, an RFC 9457 problem document described under problem details.

403 RFC 9457 problem details​

Body: application/problem+json, an RFC 9457 problem document described under problem details.

Documentation coverage: 60 of 60 fields described (100%).