ErtisAuth

Events

The event log of a membership.

ErtisAuth records an event for most of what happens in a membership: sign-ins, token refreshes, user changes, role changes, sent webhooks and mails… Events serve three purposes:

  • an audit log you can read and query through the API,
  • the trigger of webhooks,
  • the trigger of mail hooks.

The event object#

json
{
	"_id": "66f1c0d2a4b5c6d7e8f90190",
	"event_type": "UserUpdated",
	"utilizer_id": "66f1c0d2a4b5c6d7e8f90124",
	"document": {
		"_id": "66f1c0d2a4b5c6d7e8f90127",
		"username": "ada",
		"lastname": "King",
		"…": "…"
	},
	"prior": {
		"_id": "66f1c0d2a4b5c6d7e8f90127",
		"username": "ada",
		"lastname": "Lovelace",
		"…": "…"
	},
	"event_time": "2026-01-05T09:12:44Z",
	"membership_id": "66f1c0d2a4b5c6d7e8f90123"
}
FieldDescription
event_typeWhat happened (see the list below).
utilizer_idThe id of the user or application who caused the event, or system.
documentThe resource after the change. Empty for deletions.
priorThe resource before the change, for updates and deletions.
event_timeWhen it happened, in UTC.

Password hashes and application secrets are never part of events.

Event types#

Tokens#

Eventdocument
TokenGenerateduser, and token with the metadata of the new token: token_type, expires_in, refresh_token_expires_in, created_at
TokenRefresheduser, and token with the metadata of the new token, as above. A refresh also records a TokenGenerated event.
TokenVerifiedtoken with token_type and, for Bearer tokens, is_refresh_token and expires_at (for Basic tokens, application_id)
TokenRevokedtoken with token_type and expire_time of the revoked access token. One event per revoked token pair.

Token events never contain the tokens themselves, so the event log and webhook receivers can't be used to act as a user.

Users and user types#

EventWhen
UserCreatedA user was created, including by a provider sign-up
UserUpdatedA user was updated, activated or frozen
UserDeletedA user was deleted
UserPasswordChangedA password was changed, or set with a reset token
UserPasswordResetA password reset was requested
UserTypeCreated, UserTypeUpdated, UserTypeDeletedA user type changed

Other resources#

Events
ApplicationCreated, ApplicationUpdated, ApplicationDeleted
RoleCreated, RoleUpdated, RoleDeleted
ProviderCreated, ProviderUpdated, ProviderDeleted
WebhookCreated, WebhookUpdated, WebhookDeleted
MailhookCreated, MailhookUpdated, MailhookDeleted
TokenCodePolicyCreated, TokenCodePolicyUpdated, TokenCodePolicyDeleted

Device code flow#

Eventdocument
TokenCodeApproveduser (who approved), and code with user_code, client_info (the device) and created_at
TokenCodeDeniedthe same, for a denied code

The device code is never part of these events. See Device Code Flow.

Hook results#

Eventdocument
WebhookRequestSentThe result of a successful webhook call: request, response status and body, attempt number
WebhookRequestFailedThe same for a failed attempt, with the error
MailhookMailSentThe recipients
MailhookMailFailedThe recipients and the error
Note: don't create a webhook or mail hook on its own result events (WebhookRequestSent, WebhookRequestFailed, MailhookMailSent, MailhookMailFailed): each call would trigger the next one.

Endpoints#

All routes are under /memberships/{membershipId}.

MethodRouteDescriptionPermission
GET/events/{id}Get an eventevents.read.{id}
GET/eventsList eventsevents.read
POST/events/_queryQuery eventsevents.read

Events are read-only.

Examples#

The latest sign-ins of a user:

shell
curl -X POST 'https://auth.example.com/memberships/<membership_id>/events/_query?limit=20&sort=event_time%20desc' \
	-H 'Authorization: Bearer <access_token>' \
	-H 'Content-Type: application/json' \
	-d '{
		"where": {
			"event_type": "TokenGenerated",
			"utilizer_id": "66f1c0d2a4b5c6d7e8f90127"
		}
	}'

Who changed roles this month:

json
{
	"where": {
		"event_type": { "$in": [ "RoleCreated", "RoleUpdated", "RoleDeleted" ] },
		"event_time": { "$gte": "2026-01-01T00:00:00Z" }
	},
	"select": { "event_type": 1, "utilizer_id": 1, "event_time": 1, "document.slug": 1 }
}

Failed webhook calls:

json
{ "where": { "event_type": "WebhookRequestFailed" } }
Note: events contain personal data (the user documents). Grant events.read only to those who need the audit log, and plan a retention policy for the events collection.

Found a mistake in the docs? Open an issue