Documentation
DocsAPI reference

Audit

The organization's append-only log of what happened and who did it, and the request timeline it tells.

Updated Sep 23, 2026

Events are never changed or deleted. List audit events pages by cursor: pass next_cursor back as cursor with the same filters until a page has no next_cursor.

List audit eventsHosted edition

GET/api/v1/auditSession or API keyRequires audit.read

Returns one page of the organization's audit log, newest first by default. Every filter is optional and they combine.

Paging is by cursor. When more events follow, the response carries next_cursor. Pass it back as cursor with the same sort, order and filters to get the next page. The last page has no next_cursor. total_count is how many events match the filters across every page.

Request

Parameters

ParameterTypeDescription
sortquery · enum

What to sort by. Events with the same value are ordered newest first.

One of occurred, event_type, actor
orderquery · enum

desc for newest first, asc for oldest first.

One of asc, desc
cursorquery · string

The next_cursor from the previous page. Use the same sort, order and filters.

qquery · string

Free text. Matches the event type, the actor's name and id, the subject id, the event id, and the event's data. Case does not matter.

event_typequery · array<string>

Only events of these types. Repeat the parameter to pass several.

actor_typequery · enum

Only events by this kind of actor.

One of human, agent, system, api_key
actor_idquery · string

Only events by one actor. A membership id also matches events recorded under its user id, and the other way round. An agent is given by its slug.

subject_typequery · string

Only events about this kind of thing, such as a request or a membership.

subject_idquery · string

Only events about one subject. Requires subject_type. An agent subject is given by its slug; every other subject by its id.

outcomequery · enum

Only events whose action ended this way. Resolved from the event's data, so you do not need to know its shape.

One of approved, denied, expired, cancelled, human, blocked
from_atquery · date-time

Only events at or after this time.

to_atquery · date-time

Only events before this time.

limitquery · integer

How many events to return. Defaults to 100.

Response

Response codes

StatusBodyDescription
200object

One page of events

400ErrorResponse

A filter is malformed, or subject_id was given without subject_type

401ErrorResponse

You are not signed in

403ErrorResponse

You cannot read the audit log

Response body200

eventsarray<AuditEvent>required

The events on this page.

Present when another page follows.

total_countint64required

How many events match the filters, across every page.

Example

GET /api/v1/audit
curl -X GET "$WITHHUMAN_URL/api/v1/audit" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"
200 response
{
  "events": [
    {
      "sequence": 1,
      "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
      "organization_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
      "event_type": "string",
      "actor_type": "string",
      "actor_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
      "actor_display_name": "string",
      "subject_type": "string",
      "subject_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
      "data": {},
      "occurred_at": "2026-09-08T12:02:11Z"
    }
  ],
  "next_cursor": "string",
  "total_count": 1
}

Retrieve an audit eventHosted edition

GET/api/v1/audit/{id}Session or API keyRequires audit.read

One entry of the organization's audit log by id, the record behind a deep link. An id from another organization is reported as not found.

Request

Parameters

ParameterTypeDescription
idrequiredpath · uuid

The audit event's id.

Response

Response codes

StatusBodyDescription
200AuditEvent

The event

400ErrorResponse

The id is not a UUID

401ErrorResponse

You are not signed in

403ErrorResponse

You cannot read the audit log

404ErrorResponse

No such event in this organization

Response body200

sequenceint64required

The event's position in the organization's log. Later events have higher numbers.

iduuidrequired
organization_iduuidrequired
event_typestringrequired

What happened, as a dotted key such as membership.suspended.

actor_typestringrequired

Who did it: human, agent, system, or api_key.

The person, agent, or key that acted. Absent for system.

The actor's name at the time.

subject_typestringrequired

What kind of thing the event is about, such as a request or a membership.

subject_iduuidrequired

The thing the event is about.

dataanyrequired

Details specific to the event type, as JSON.

occurred_atdate-timerequired

When it happened.

Example

GET /api/v1/audit/{id}
curl -X GET "$WITHHUMAN_URL/api/v1/audit/{id}" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"
200 response
{
  "sequence": 1,
  "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "organization_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "event_type": "string",
  "actor_type": "string",
  "actor_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "actor_display_name": "string",
  "subject_type": "string",
  "subject_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
  "data": {},
  "occurred_at": "2026-09-08T12:02:11Z"
}

List the event types this organization has recordedHosted edition

GET/api/v1/audit/event_typesSession or API keyRequires audit.read

The vocabulary for the audit log's event filter, sorted. Unlike a fixed list it can never name a type that does not occur.

Request

No parameters or body.

Response

Response codes

StatusBodyDescription
200object

Distinct event types

401ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

403ErrorResponse

Error response. A 403 from a permission check carries ForbiddenDetails in error.details.

Response body200

event_typesarray<string>required

Example

GET /api/v1/audit/event_types
curl -X GET "$WITHHUMAN_URL/api/v1/audit/event_types" \
  -H "Authorization: Bearer $WITHHUMAN_API_KEY"
200 response
{
  "event_types": [
    "string"
  ]
}