Events
Complete reference of all events emitted by AuthPI for webhooks, audit logs, and integrations.
Last updated 2026-07-03
AuthPI emits events whenever something significant happens in your account—a user signs up, a session is created, an API key is rotated, and so on. These events power webhooks, audit logs, and analytics.
This page documents all event types, their payloads, and when they’re triggered.
Event Structure
All events follow the CloudEvents 1.0 specification with AuthPI-specific extensions.
{
"spec": "1.0",
"id": "evt_01HN8K2X...",
"type": "user.created",
"source": "identities",
"timestamp": 1705330953123,
"subject": {
"account_id": "acc_xxx",
"issuer_id": "i_xxx",
"user_id": "usr_xxx"
},
"auth": {
"type": "api_key",
"id": "key_xxx",
"issuer": "i_xxx"
},
"data": {
"user_id": "usr_xxx",
"username_type": "email"
}
}
Fields
| Field | Type | Description |
|---|---|---|
spec | string | CloudEvents spec version (always "1.0") |
id | string | Unique event identifier |
type | string | Event type (see categories below) |
source | string | Service that emitted the event |
timestamp | number | Unix timestamp in milliseconds |
subject | object | Resource identifiers the event relates to |
auth | object | Who or what triggered the event |
data | object | Event-specific payload |
Subject Fields
The subject object contains identifiers for filtering and routing:
| Field | Present When |
|---|---|
account_id | Always |
issuer_id | Event relates to an issuer |
user_id | Event relates to a user |
agent_id | Event relates to an agent |
org_id | Event relates to an organization |
client_id | Event relates to a client |
session_id | Event relates to a session |
api_key_id | Event relates to an API key |
token_id | Event relates to a personal token |
webhook_id | Event relates to a webhook |
Delivery via Webhooks
When an event is delivered to a webhook, it is wrapped in a standard CloudEvents 1.0 envelope that differs slightly from the structure above:
subjectbecomes a single string set to the most specific entity ID (e.g. the user ID foruser.created, the org ID fororganization.deleted), and all subject fields are merged intodataalongside the event-specific payload.timestamp(Unix ms) is delivered astime(ISO 8601), andspecasspecversion.sourceidentifies the delivering webhook, andauthis not included.
See the webhooks guide for the full delivered payload format.
Auth Types
The auth.type field indicates what triggered the event:
| Type | Description |
|---|---|
user | End user action (via portal or authenticated session) |
client | OAuth client action |
api_key | Core API call with API key |
token | Core API call with personal token |
wallet | x402 wallet-authenticated action |
system | Automated system action (expiration, scheduled tasks) |
unauthenticated | Public endpoint (signup, login) |
unknown | Auth context could not be determined |
User Events
Events related to user accounts and identity management.
Events emitted during hosted portal flows (signup, login, MFA) carry additional flow context in data: flow_type ("portal_flow"), flow_id, ip_address, user_agent, and trace_id. The payload examples below show only the event-specific fields.
Lifecycle
| Event | Description |
|---|---|
user.created | New user account created |
user.updated | User profile or settings updated |
user.deleted | User account permanently deleted |
user.blocked | User account blocked (too many failed logins or admin action) |
user.unblocked | User account unblocked |
user.created payload:
{
"user_id": "usr_xxx",
"username_type": "email"
}
For users created through a hosted portal signup or SSO just-in-time provisioning, the payload also includes signup attribution when available: method ("password" or "sso"), ip_address, user_agent, and — for portal signups — flow_id.
user.created fires whenever the user record is created, including signups gated behind manual approval (those additionally emit user.approval.requested, and activation is signaled by user.approval.approved).
Authentication
| Event | Description |
|---|---|
user.verification.succeeded | Credential verification succeeded |
user.verification.failed | Credential verification failed |
MFA
| Event | Description |
|---|---|
user.mfa.factor-created | MFA factor enrolled (TOTP, backup codes, etc.) |
user.mfa.verification.succeeded | MFA verification succeeded |
user.mfa.verification.failed | MFA verification failed |
MFA factor removal and backup-code regeneration are delivered as verifier events — user.verifier.deleted and user.verifier.updated respectively (see Credentials below).
user.mfa.verification.succeeded payload:
{
"verifier_type": "totp"
}
Credentials (Verifiers)
| Event | Description |
|---|---|
user.verifier.created | New credential added (password, passkey, TOTP, etc.) |
user.verifier.updated | Credential updated (currently fires when backup codes are regenerated) |
user.verifier.deleted | Credential removed |
user.password.changed | Password changed |
user.password.reset-requested | Password reset email sent |
user.password.reset | Password reset completed |
user.verifier.created payload:
{
"verifier_id": "ver_xxx",
"verifier_type": "passkey"
}
For OAuth verifiers (social sign-in), the payload also includes provider (e.g. "github") and method_id (the issuer auth method, am_...).
Email Management
| Event | Description |
|---|---|
user.email.verified | Email address verified |
user.email.changed | Email address changed |
user.email.change-requested | Email change initiated (pending confirmation) |
Magic Links
| Event | Description |
|---|---|
user.login-link.requested | Magic link login requested |
user.login-link.consumed | Magic link used for authentication |
Signup Approval
| Event | Description |
|---|---|
user.approval.requested | Signup requires manual approval — fires alongside user.created; the user starts in a pending state |
user.approval.approved | Pending user approved and activated |
user.approval.rejected | Pending user rejected and blocked |
user.approval.requested payload:
{
"user_id": "usr_xxx",
"username_type": "email"
}
signup_reason (user-provided) and triggered_rule (the approval rule that matched) are included when set. Decisions carry user_id and decided_by (the deciding admin); rejections also include the reason shown to the user.
Consent
| Event | Description |
|---|---|
user.consent.granted | User granted OAuth consent to a client |
user.consent.revoked | Consent revoked for one client or for all clients |
user.consent.granted payload:
{
"consent_id": "cg_xxx",
"client_id": "c_xxx",
"scopes": ["openid", "profile", "email"]
}
Single-client revocations carry client_id and scope: "single"; revoke-all carries revoked_count and scope: "all".
Trusted Devices
| Event | Description |
|---|---|
user.device.trusted | Device trusted (skips MFA challenges until expiry) |
user.device.revoked | Trusted device revoked (single device or all) |
user.device.trusted payload:
{
"device_id": "dev_xxx",
"fingerprint": "5f4dcc3b5aa7...",
"name": "MacBook Pro",
"expires_at": 1708527753000
}
Single revocations carry device_id; revoke-all carries revoked_count and revoke_all: true.
SSO Linking
| Event | Description |
|---|---|
user.sso.provisioned | New user provisioned just-in-time through organization SSO |
user.sso.linked | Existing user linked to an SSO identity by email match |
Both carry the same payload:
{
"org_id": "org_xxx",
"provider_user_id": "24f80cc5-52a1-4a5b-8f3e-9d7c1b2a3f4e"
}
provider_user_id is the sub claim from the organization’s identity provider.
Session Events
Events related to user sessions.
| Event | Description |
|---|---|
session.created | New session created and activated |
session.updated | Session metadata updated |
session.token-refreshed | Session tokens refreshed |
session.expired | Session expired (TTL or idle timeout) |
session.terminated | Session terminated. data carries previous_status and a short reason string such as user_logout, security_event, session_limit_exceeded, or other. |
session.compromised | Session flagged as potentially compromised |
session.created payload:
{
"client_id": "c_xxx"
}
The session ID is in subject.session_id. Sessions created through a hosted portal sign-in also carry session_id, device_trusted, portal_flow_type (login, signup, or password_reset), and the portal flow context fields (flow_id, ip_address, user_agent, trace_id).
session.compromised payload:
{
"reason": "refresh_token_reuse"
}
reason is refresh_token_reuse or device_fingerprint_mismatch; the session ID is in subject.session_id.
This event triggers when AuthPI detects potential token theft, such as when a refresh token is used after it should have been rotated. All tokens for the session are immediately revoked.
Organization Events
Events related to organizations and multi-tenancy.
Organization Lifecycle
| Event | Description |
|---|---|
organization.created | Organization created |
organization.updated | Organization settings updated |
organization.deleted | Organization deleted |
organization.suspended | Organization suspended (also fires organization.updated) |
organization.reactivated | Suspended organization reactivated (also fires organization.updated) |
organization.created payload:
{
"name": "Acme Corporation",
"org_type": "business",
"created_by": "usr_xxx"
}
organization.suspended payload:
{
"status": "suspended",
"previous_status": "active",
"status_at": 1705935753000,
"status_reason": "non-payment",
"status_by": "usr_xxx"
}
When an organization is suspended, newly issued tokens (fresh logins, refreshes, /userinfo) stop carrying its claims. Use this event to revoke your own application sessions for the organization immediately, rather than waiting for access tokens to expire. status_reason and status_by are present only if they were set in the update.
Memberships
| Event | Description |
|---|---|
organization.membership.created | User added to organization |
organization.membership.updated | Membership scopes or settings updated |
organization.membership.deleted | User removed from organization |
organization.membership.created payload:
{
"member_id": "usr_xxx",
"scopes": ["member", "projects:read"],
"groups": [],
"user_title": "Developer"
}
member_id is a user (usr_...) or agent (agt_...) ID; the matching user_id or agent_id subject field is set accordingly.
Invitations
| Event | Description |
|---|---|
organization.invitation.created | Invitation sent |
organization.invitation.accepted | Invitation accepted |
organization.invitation.declined | Invitation declined |
organization.invitation.deleted | Invitation revoked (carries reason: "revoked"; expiry emits no event) |
organization.invitation.created payload:
{
"invite_id": "inv_xxx",
"email_invited": "new.employee@example.com",
"expires_at": 1705935753000
}
inviter ({ id?, name? }) is included when it was provided on the create request.
Groups
| Event | Description |
|---|---|
organization.group.created | Group created |
organization.group.updated | Group updated (scope changes re-sync member permissions) |
organization.group.deleted | Group deleted (memberships re-synced) |
organization.group.created payload:
{
"group_id": "grp_xxx",
"name": "Engineering",
"scopes": ["projects:write"]
}
Updates carry group_id and updated_fields (the list of changed fields); deletes carry group_id and name.
SSO Configuration
| Event | Description |
|---|---|
organization.sso.enabled | SSO enabled for the organization |
organization.sso.disabled | SSO disabled |
organization.sso.updated | SSO configuration changed while enabled (including secret rotation) |
organization.sso.domain-created | SSO domain added, pending DNS verification |
organization.sso.domain-verified | SSO domain ownership verified via DNS TXT record |
organization.sso.domain-deleted | SSO domain removed |
organization.sso.enabled carries protocol (e.g. "oidc"); organization.sso.updated carries updated_fields (a secret rotation reports ["client_secret"]); the domain events carry domain (normalized to lowercase). organization.sso.disabled has no payload.
Agent Events
Events related to agent identities (non-human principals).
| Event | Description |
|---|---|
agent.created | Agent created |
agent.updated | Agent updated |
agent.deleted | Agent deleted |
agent.verifier.added | Agent credential added |
agent.verifier.removed | Agent credential removed |
agent.created payload:
{
"name": "Support Triage Agent",
"description": "Triages inbound support tickets",
"model": "claude-sonnet-4-5",
"provider": "anthropic"
}
The agent ID is in subject.agent_id. agent.updated carries the fields that changed; agent.deleted has no payload.
agent.verifier.added payload:
{
"verifier_id": "v_xxx",
"verifier_type": "wallet"
}
verifier_type is wallet or secret; agent.verifier.removed carries the same fields.
Client Events
Events related to OAuth clients (applications).
| Event | Description |
|---|---|
client.created | OAuth client registered |
client.updated | Client configuration updated |
client.deleted | Client deleted |
client.secret.rotated | Client secret rotated |
client.blocked | Client blocked |
client.unblocked | Client unblocked |
client.created payload:
{
"name": "My Web App",
"description": null,
"type": "internal",
"confidential": true,
"protocol": "oidc"
}
The client ID is in subject.client_id.
client.secret.rotated carries no event-specific payload (data is {}) — the client, issuer, and account IDs are in subject, and the event timestamp is the rotation time.
Machine Tokens
| Event | Description |
|---|---|
machine.token.issued | Access token issued via the client_credentials flow |
machine.token.issued payload:
{
"subject_type": "client",
"scope_count": 3
}
subject_type is client (M2M client) or agent; subject carries the matching client_id or agent_id. The event fires on token issuance only, not on each use.
API Key Events
Events related to API keys for programmatic access.
| Event | Description |
|---|---|
api-key.created | API key created |
api-key.updated | API key settings updated |
api-key.deleted | API key revoked |
api-key.blocked | API key blocked |
api-key.unblocked | API key unblocked |
api-key.created payload:
{
"name": "Production API Key",
"scopes": ["users:read", "users:write"]
}
The key, organization, issuer, and account IDs are in subject.
Personal Token Events
Events related to personal access tokens (user-owned).
| Event | Description |
|---|---|
user.personal-token.created | Personal token created |
user.personal-token.updated | Personal token updated |
user.personal-token.deleted | Personal token revoked |
user.personal-token.created payload:
{
"name": "CI/CD Token",
"scopes": ["repos:read"]
}
The token and user IDs are in subject.token_id and subject.user_id.
Issuer Events
Events related to issuer configuration.
| Event | Description |
|---|---|
issuer.created | Issuer created |
issuer.updated | Issuer configuration updated |
issuer.deleted | Issuer deleted |
issuer.auth-method.created | Auth method added (OAuth provider, etc.) |
issuer.auth-method.updated | Auth method configuration updated |
issuer.auth-method.deleted | Auth method removed |
issuer.auth-method.created payload:
{
"issuer_id": "i_xxx",
"method_id": "am_xxx",
"method_type": "oauth2",
"name": "Google"
}
Account Events
Events related to your account: lifecycle, billing credits, and custom domains.
Account Lifecycle
| Event | Description |
|---|---|
account.created | Account created |
account.updated | Account changed (profile, features, limits, billing, payment methods, domains, suspension) |
account.deleted | Account deleted |
The account.updated payload always carries account_id plus a field describing what changed — for example changes (the updated fields), organization_changes, domain_added / domain_removed / domain_verified, primary_domain, or status ("suspended" / "active").
Credits
| Event | Description |
|---|---|
account.credits.updated | Credits added (topup or bonus) or refunded |
account.credits.depleted | Balance reached zero — fires once per depletion cycle, reset by the next topup |
account.credits.updated payload:
{
"account_id": "acc_xxx",
"transaction_type": "topup",
"entry_id": "cle_xxx",
"amount_μusd": 10000000,
"balance_after_μusd": 12500000,
"operation": null,
"reference": "pi_3OaXXXX"
}
transaction_type is topup, bonus, or refund. Bonus entries add expires_at; refunds add related_entry_id (the charge being refunded).
account.credits.depleted payload:
{
"account_id": "acc_xxx",
"balance_μusd": -1200,
"trigger_entry_id": "cle_xxx"
}
Custom Domains
| Event | Description |
|---|---|
account.domain.added | Custom domain added to the account |
account.domain.removed | Domain removed |
account.domain.assigned | Verified domain assigned to an issuer |
account.domain.unassigned | Domain unassigned from its issuer |
Payloads carry account_id and host; assignment events add issuer_id, and reassignments include previous_issuer_id. Domain verification itself is reported through account.updated with domain_verified.
Webhook Events
Events related to webhook configuration (meta-events).
| Event | Description |
|---|---|
webhook.created | Webhook subscription created |
webhook.updated | Webhook configuration updated |
webhook.deleted | Webhook deleted |
webhook.paused | Webhook manually disabled or auto-paused after persistent delivery failures |
webhook.resumed | Disabled webhook reactivated |
Email Events
Events related to email delivery.
| Event | Description |
|---|---|
email.sent | Email sent successfully |
email.failed | Email delivery failed |
Subscribing to Events
Via Webhooks
Configure webhooks to receive events in real-time:
curl -X POST https://api.authpi.com/v1/accounts/{account_id}/webhooks \
-u "{key_id}:{key_secret}" \
-H "Content-Type: application/json" \
-d '{
"name": "User Events",
"url": "https://your-server.com/webhooks/authpi",
"events": ["user.created", "user.deleted", "session.compromised"],
"auth": {
"type": "signature",
"signature_algorithm": "hmac-sha256"
}
}'
Event Filtering
Webhooks subscribe to exact event names (e.g. ["user.created", "user.deleted"]) — wildcard patterns are not supported. Unknown event names and internal-only event types (exception and api-key.verified, which never fan out to customer webhooks) are rejected when a webhook is created or updated. To narrow delivery to specific entities within your account, use subject filters.
Via API
Query historical events through the Core API:
curl "https://api.authpi.com/v1/accounts/{account_id}/events?type=user.created&limit=100" \
-u "{key_id}:{key_secret}"
Filter parameters:
| Parameter | Description |
|---|---|
type | Filter by event type |
source | Filter by source service |
user_id | Filter by user |
org_id | Filter by organization |
since | Events after timestamp |
until | Events before timestamp |
limit | Maximum results (default 50, max 1000) |
Common Patterns
Sync Users to External Systems
Subscribe to user lifecycle events to keep external systems in sync:
{
"events": ["user.created", "user.updated", "user.deleted"]
}
Security Monitoring
Monitor for security-relevant events:
{
"events": [
"user.verification.failed",
"session.compromised",
"user.blocked"
]
}
Audit Logging
Capture all administrative actions:
{
"events": [
"user.created",
"user.updated",
"user.deleted",
"organization.created",
"organization.updated",
"organization.deleted",
"client.created",
"client.updated",
"client.deleted",
"issuer.updated"
]
}
Billing Integration
Track usage-relevant events:
{
"events": [
"user.created",
"organization.created",
"session.created"
]
}
Event Delivery
Events are delivered asynchronously with at-least-once semantics. This means:
- Events may occasionally be delivered more than once
- Your webhook handler should be idempotent (use the event
idto deduplicate) - Events are typically delivered within seconds, but delays can occur during high load
For webhook retry behavior and failure handling, see the Webhooks guide.
Next Steps
- Set up Webhooks to receive events
- Learn about Users and their lifecycle
- Understand Organizations and membership events
- Review API authentication for querying events