generated: '2026-08-09' method: searched source: https://help.cerby.com/developer-tools/cerby-webhooks/implement-a-webhook-receiver spec_type: none spec_note: >- Cerby publishes NO AsyncAPI document. Probed https://api.cerby.com/asyncapi.yaml (404), https://help.cerby.com/asyncapi.yaml (404) and https://developer.cerby.com/asyncapi.json (404). What Cerby does publish is a complete prose webhook contract — envelope, headers, signature algorithm, event catalog, retry policy — captured here as a webhook catalog. This file is a faithful record of that documentation, not a generated spec. surface: webhooks docs: - https://help.cerby.com/developer-tools/cerby-webhooks/implement-a-webhook-receiver - https://help.cerby.com/setup-and-admin/workspace-settings/webhooks/explore-webhook-notifications - https://help.cerby.com/setup-and-admin/workspace-settings/webhooks/create-a-webhook - https://help.cerby.com/setup-and-admin/workspace-settings/webhooks/rotate-a-webhook-signing-key - https://help.cerby.com/setup-and-admin/workspace-settings/webhooks/test-a-webhook-endpoint envelope: version_field: envelope_version version: '1.0' content_type: application/json fields: envelope_version: {type: string, note: Always "1.0" in this release. New fields may be added without a version bump.} event_id: {type: string (UUIDv7), note: Unique per event. Stable across all retry attempts. Use as the per-event idempotency key.} event_type: {type: string} occurred_at: {type: string (RFC 3339, UTC, ms), note: When Cerby recorded the event, not the source-system time.} workspace_id: {type: string (UUID)} data: {type: object, note: Event-specific payload. Fields vary by event type.} error: {type: object, note: 'Present ONLY on failure events — absent, not null, otherwise. Fields: code, message, user_action.'} trace_id: {type: 'null', note: Reserved. Always null in this release.} correlation_id: {type: 'null', note: Reserved. Always null in this release.} headers: - name: X-Cerby-Signature description: '= where is ed25519 or hmac-sha256. Repeated during a key rotation (new key first, old key second).' - name: X-Cerby-Signature-Key-Id description: UUID of the signing key used. One header per signature row, in the same order as X-Cerby-Signature. - name: X-Cerby-Signature-Timestamp description: RFC 3339 millisecond-precision UTC timestamp, part of the signed message. Reject if more than five minutes from now. - name: X-Cerby-Delivery description: UUID constant across all retry attempts for the same event and webhook. Per-delivery idempotency key. - name: X-Cerby-Attempt description: Attempt number starting at 1, incremented on each retry, up to 6. - name: Idempotency-Key description: Same value as X-Cerby-Delivery, provided as a convenience alias. security: mechanism: request signing algorithms: [ed25519, hmac-sha256] signed_bytes: '.' canonicalization: none clock_skew_tolerance_ms: 300000 base64: base64url, unpadded (re-pad before decoding) reference_implementations: [python, nodejs] reference_implementations_note: Kept in sync with Cerby's CI test suite. key_retrieval_endpoint: GET /v1/event-webhooks/{webhook_id}/keys key_rotation: dual_sign_window_hours: 24 ordering: new key first (primary), old key second (secondary) cache_miss_signal: >- An unrecognized X-Cerby-Signature-Key-Id means a rotation has started — re-fetch both keys before rejecting. delivery: guarantee: at-least-once dedup: per_delivery: X-Cerby-Delivery + X-Cerby-Attempt per_event: event_id anti_pattern: Do not deduplicate on payload content, URL, or signature equality. retry_policy: max_attempts: 6 initial_interval_seconds: 60 backoff_multiplier: 4 approximate_schedule: [1m, 4m, 16m, 64m, 4.3h] max_interval_hours: 6 hard_deadline_hours: 24 response_handling: - receiver_returns: 2xx behavior: Delivery complete. - receiver_returns: 408, 429, or 503 with Retry-After behavior: Retried. Cerby honors Retry-After, clamped to one hour. - receiver_returns: any other 4xx behavior: Fail-fast. Dead-lettered immediately, not retried. - receiver_returns: 5xx, timeout, or TCP error behavior: Retried with standard backoff. guidance: Respond 2xx quickly and process the event asynchronously. channels: - transport: https description: Standard JSON envelope delivered to any HTTPS endpoint. - transport: slack-incoming-webhook host_trigger: hooks.slack.com description: >- Cerby delivers a Slack Block Kit message instead of the standard envelope. The Block Kit message is a lossy subset — data.action, data.automation_link, and other data fields are omitted. severity_colors: {success: '#2EB67D', failure: '#D50200'} events: - name: account.created domain: account data: [account_id, domain, vault_id, requestor_id] - name: account.deleted domain: account data: [account_id, requestor_id] status: not-delivered-this-release - name: account.disabled domain: account data: [account_id, requestor_id] - name: account.enabled domain: account data: [account_id, requestor_id] - name: account.credentials.updated domain: account data: [account_id, application, credentials_identifier] pii: credentials_identifier is the username or email. - name: account.credentials.rotated domain: account data: [account_id, application, credentials_identifier] - name: account.credentials.rotation_failed domain: account data: [account_id, application, automation_job_id, automation_link] carries_error: true status: provisional - name: account.access.shared domain: account data: [account_id, account_name, new_teams_ids, role] pii: account_name note: May co-fire with account.access.shared_with_user. - name: account.access.shared_with_user domain: account data: [account_id, account_name, new_users_ids, role] note: May co-fire with account.access.shared. - name: account.login.failed domain: account data: [account_id, application, automation_job_id, automation_link] carries_error: true status: provisional - name: account.mfa.enabled domain: account data: [account_id, application, automation_job_id] status: provisional - name: account.mfa.disabled domain: account data: [account_id, provider] - name: account.mfa.setup_failed domain: account data: [account_id, application, automation_job_id, automation_link] carries_error: true status: provisional - name: automation.users.provisioned domain: automation data: [automation_job_id, application, account_id, automation_link, child_count, child_failure_count] note: Rollup — one event per execution group. child counts are null this release. - name: automation.users.deprovisioned domain: automation data: [automation_job_id, application, account_id, automation_link, child_count, child_failure_count] note: Rollup. - name: automation.users.role_updated domain: automation data: [automation_job_id, application, account_id, automation_link, child_count, child_failure_count] note: Rollup. - name: automation.password.rotated domain: automation data: [automation_job_id, application, account_id, automation_link] - name: automation.mfa.enabled domain: automation data: [automation_job_id, application, account_id, automation_link] - name: automation.universal_logout.completed domain: automation data: [automation_job_id, application, account_id, automation_link] status: provisional - name: automation.succeeded domain: automation data: [automation_job_id, application, account_id, automation_link, action] note: Always-fire catch-all. Co-fires alongside the matching specific success event. - name: automation.failed domain: automation data: [automation_job_id, application, account_id, automation_link, action, remediation] carries_error: true error_catalog: errors/cerby-automation-failure-codes.yml reserved_events: note: Reserved for a future release. Subscribing currently returns HTTP 400. events: - account.vault.assigned - account.trusted_session.established - automation.users.attributes_updated - automation.users.synced limitations_published: - account.deleted is available for subscription but not delivered in this release. - Webhooks are not available for Canada-resident workspaces (ca-central-1). - trace_id and correlation_id are reserved and always null; most events are standalone. - Several event types are provisional and may not arrive in production. summary: event_types: 21 reserved_event_types: 4 domains: [account, automation] provisional: 5 x-evidence: - url: https://help.cerby.com/developer-tools/cerby-webhooks/implement-a-webhook-receiver.md http_status: 200 fetched: '2026-08-09' - url: https://api.cerby.com/asyncapi.yaml http_status: 404 fetched: '2026-08-09' - url: https://help.cerby.com/asyncapi.yaml http_status: 404 fetched: '2026-08-09'