Auth guides
08 · Webhooks + audit

Hear about lifecycle events. Read the audit log.

Two trailing-edge surfaces: webhooks deliver real-time events to your backend (signup, verification, role change, tenant added); the audit log is the durable record of every mutation, queryable for support and compliance.


1

What you can subscribe to

Every event, with a plain description, its group and an example data object, is listed by the API, so your code (and the console's event picker) never has to hard-code the names:

GET /v1/apps/:appId/webhooks/event-types
curl https://api.auth.productcraft.co/v1/apps/<appId>/webhooks/event-types \
  -H 'authorization: Bearer pcft_live_...'
Event types
# Users
user.signup                       # by sign-up, admin, invite or first social sign-in
user.signin
user.suspended
user.deactivated
user.reinstated
user.role_changed
user.deleted                      # data.reason "unverified_expired" when auto-deleted (see below)

# Verification and passwords
user.contact_verified             # any email/phone contact verified
user.email_verified               # older name, sent too when it's the primary email
user.password_reset.requested
user.password_reset.completed

# Two-step verification
user.mfa.factor_enrolled
user.mfa.factor_disabled
user.mfa.recovery_code_used
user.mfa.step_up_succeeded
user.mfa.step_up_locked
user.mfa.enrollment_required
user.mfa.reenrollment_required

# Organizations
tenant.created
tenant.updated
tenant.deleted
tenant.member.added
tenant.member.removed
tenant.member.role_changed
tenant.invite.created
tenant.invite.accepted
tenant.invite.revoked

# App
app.slug_changed                  # your issuer and JWKS URL are moving: 30-day alias

Webhooks are per app, and an app can have up to 10 endpoints, each with its own URL, events and signing secret: one for your backend, one for analytics, a third for a staging receiver. An endpoint subscribed to no events receives every event.

Unverified accounts are deleted automatically when the app's unverified_account_ttl_days is set (new apps: 7 days; apps created before the setting existed: off). Each nightly deletion sends user.deleted with "reason": "unverified_expired", so delete your own copy of the user when it arrives. Only accounts that never verified their email, never signed in, refreshed a session or reset their password after signing up, and have no two-step factor or social login qualify. To protect someone who uses your app without verifying, set "metadata": { "app_active": true } on them with PATCH /v1/apps/:appId/end-users/:userId.


2

Add an endpoint

From the console (Auth → your app → Integration → Webhooks) or the API. Endpoints, signatures, tests, retries and replay work the same in every ProductCraft product.

POST /v1/apps/:appId/webhooks/endpoints
curl -X POST https://api.auth.productcraft.co/v1/apps/<appId>/webhooks/endpoints \
  -H 'authorization: Bearer pcft_live_...' \
  -H 'idempotency-key: add-backend-endpoint-1' \
  -H 'content-type: application/json' \
  -d '{
    "url":         "https://acme.example.com/webhooks/auth",
    "event_types": ["user.signup", "user.email_verified", "user.role_changed"]
  }'

The answer carries the whsec_… signing secret exactly once. Endpoints belong to one app; each app can have up to 10. Verifying the signature, Send test, automatic retries, auto-disable, the event log, replay and secret rotation are in the Webhooks guide, with Node code you can paste.


3

What an Auth event looks like

Signed with Standard Webhooks like every ProductCraft event; app_id says which app it came from.

user.email_verified
{
  "id":         "evt_fb580f79-...",
  "type":       "user.email_verified",
  "created_at": "2026-05-11T11:38:42Z",
  "app_id":     "53641fdb-...",
  "data":       { ...event-specific fields... }
}

Upgrading from the single webhook? Endpoints that existed before 17 October 2026, or that are set up through the older PUT .../webhook route, also get the old x-auth-signature header plus x-auth-event-id and x-auth-event-type, until 15 January 2027. The old /v1/apps/:appId/webhook routes keep working until the same date, acting on the app's first endpoint. The Webhooks guide covers the old header and moving your verifier.


4

The audit log — the durable record

Every state-changing call on Auth writes an audit_log row. Per-app. Append-only. Searchable + exportable.

Audit captures the same surface as webhooks plus more:

  • Every signup / signin (including failures) / logout / token refresh (auth.*)
  • Every verification + password-reset mint and consume
  • Every member add / remove / role change (app.member.*)
  • Every role CRUD + role-permission change (app.role.*)
  • Every M2M credential mutation (app.m2m.*)
  • Every tenant lifecycle event (tenant.*)
  • Every webhook endpoint change, test and replay (app.webhook.*)
  • Every MFA factor + recovery-code event (auth.factor.*)
  • Permission denials — on apps with permission enforcement enabled, a request that fails the permission gate writes authz.app_permission_denied with the missing permission

5

Read the audit log

GET /v1/apps/:appId/audit-logs
curl 'https://api.auth.productcraft.co/v1/apps/<appId>/audit-logs?limit=20&action=auth.signin.success' \
  -H 'authorization: Bearer pcft_live_...'
{
  "data": [
    {
      "id":          "...",
      "app_id":      "53641fdb-...",
      "actor_id":    "648616c8-...",   // who did it (account uuid, or null for M2M/system)
      "actor_type":  "end_user",        // | platform_user | m2m | api_key | system
      "action":      "auth.signin.success",
      "resource":    "account",
      "resource_id": "648616c8-...",
      "metadata":    {},
      "ip":          "203.0.113.4",
      "created_at":  "2026-05-11T..."
    }
  ],
  "pagination": { "next_cursor": "...", "has_more": true }
}

Filter via query params: action (exact match, one action per query) and actor_id, plus limit (50 default, 200 max) and cursor for pagination. “Everything Ada did” is ?actor_id=<account>; walk the cursor for time ranges.


6

Webhook vs audit — when to use which

  • Webhook = real-time push. Use for sync that needs to happen immediately when the event fires — flipping a feature flag on the user's account, kicking off provisioning, sending a confirmation in your own UI.
  • Audit = pull, on demand. Use for support workflows (“what happened to this user 3 days ago?”), compliance exports, security investigations, and post-hoc debugging. The data covers everything; the latency is whatever your query takes.
  • Don't treat audit as a stream. There's no “tail the audit log” primitive today — for that, configure a webhook. The audit log is designed for cursor-paginated point-in-time queries.

What's next

You've finished the series

That was the comprehensive tour. From here:

  • API reference — every endpoint, every status code, generated from the live OpenAPI spec.
  • Core concepts — the conceptual model in one page.
  • Platform docs — the administrative surface that sits underneath Auth. Read this if you're managing your workspace from CI or infrastructure-as-code.
  • Mail docs — transactional email, the natural pairing for verification + reset flows.