Concepts
Audit log
Every consequential thing that happens in your project — authentication, organization changes, recovery requests, webhook activity — lands in audit_events. Filter, export, or stream it.
audit_events is the single platform-wide event log. Every Authio service (auth-core, management-api, scim, sso, fga, webhooks, audit-worker, billing) writes here for any state change worth surfacing. It's the source of truth for the dashboard's /audit view, the webhook subscriber, and audit-stream destinations (Datadog, Splunk, S3, Snowflake, …).
Event taxonomy
Event names follow <namespace>.<subject>.<verb> — e.g. auth.signin_attempt, webhook.endpoint.revoked, organization.member.invited. The current canonical list, by namespace:
auth.*
auth.signin_attempt— every primary auth (passkey, magic-link, OAuth) regardless of outcome. Carriesscore,decision,reasons, and the device/ip/UA inmetadata.auth.risk_evaluated— compact mirror of the decision withdecision_idpointing at therisk_decisionsrow. See risk engine.auth.blocked_by_risk_policy— emitted when a score lands ≥threshold_block.auth.step_up_required— emitted when a step-up challenge is created.auth.step_up_satisfied— emitted when a step-up completes via a fresh passkey assertion or magic link.
organization.* / membership.* / invitation.*
organization.created,organization.updated,organization.deletedmembership.created,membership.role_changed,membership.status_changed,membership.removedinvitation.created,invitation.accepted,invitation.revoked
webhook.*
webhook.endpoint.created,webhook.endpoint.revoked,webhook.endpoint.secret_rotatedwebhook.delivery.replayed
risk.*
risk.policy.updated— emitted by management-api onPUT /v1/risk/policy. Metadata carries the new thresholds and enabled-signal count.
Others
api_key.created,api_key.revokedscim.user.synced,scim.group.synceddashboard_operator.bootstrapped,dashboard_operator.added,dashboard_operator.removedrecovery.request.created,recovery.request.approved,recovery.request.deniedincident.created,incident.updated,incident.resolvedmaintenance.scheduled,maintenance.started,maintenance.completed
GET /v1/audit/events/types to discover the action strings that have actually flowed through your project in the last 30 days, so you only see types you emit.Retention & partitioning
audit_events is range-partitioned by created_at at monthly granularity (see migration 0016_audit_events_partition.sql). The authio_audit worker runs a partition manager loop at startup and every 24h:
- Forward roll:
CREATE TABLE IF NOT EXISTSnextAUTHIO_AUDIT_FORWARD_MONTHSpartitions (default 3). Inserts crossing month boundaries always land in a pre-allocated partition. - Drop old: any partition whose upper bound is older than
AUTHIO_AUDIT_RETENTION_MONTHS(default 3) isDROP TABLE'd. This is the fast O(1) retention path that motivated partitioning in the first place — DELETE-by-date on a ~100M row audit_events would be catastrophic vacuum work;DROP PARTITIONis metadata-only.
Set those env vars on the audit worker to extend the window — e.g. AUTHIO_AUDIT_RETENTION_MONTHS=12 for a-year-of-history projects.
Exporting
One-shot CSV / JSONL (dashboard)
On /audit, click Export CSV or Export JSONL. Both stream from GET /v1/audit/events.{csv,jsonl} with the currently-applied filters and cap at 100 000 rows per request. Cursor pagination internal to the export keeps memory flat regardless of result-set size.
# CSV columns
id, created_at, action, actor_type, actor_id,
user_id, project_id, target_type, target_id, ip,
user_agent, description
# JSONL: one row per line, full JSON shape including metadataProgrammatic export (API key)
curl -sN \
-H "Authorization: Bearer sk_live_…" \
"https://authiomanagement-api-production.up.railway.app/v1/audit/events.jsonl?from=2026-04-01T00:00:00Z&type=auth.risk_evaluated" \
> events.jsonlReal-time webhook subscriptions
Create a webhook endpoint at /webhooks/new and subscribe to specific event types (or * for everything). The webhooks worker delivers with HMAC signatures and an exponential-backoff retry; see Webhooks for the payload shape and verification snippets.
Audit-streams (SIEMs and warehouses)
Create an audit stream on /audit/streams to forward every event to Datadog Logs, Splunk HEC, S3, Snowflake, Sumo Logic, or a generic JSON webhook. Streams are ordered, cursor-tracked per stream, and survive worker restarts without dupes/gaps.
Filtering & search
GET /v1/audit/events supports keyset pagination plus the following filters — all combinable, all backed by indexed scans:
?type=auth.signin_attempt,risk.policy.updated(comma-separated)?user=user_…— exact match onuser_id?actor=…— exact match onactor_id?from=…&to=…— ISO timestamps?q=foo— substring across action / actor_id / target_id / metadata->>description?cursor=…&limit=…— keyset on(created_at, id)
GET /v1/audit-events endpoint (with the before= ISO cursor and action_prefix= filter) stays available indefinitely — existing customer integrations keep working.