Webhooks API
Lifecycle event handlers for Clerk and Svix
Danvas exposes webhook endpoints to receive lifecycle events from external services like Clerk (user management).
Clerk webhooks are owned by apps/api at /api/webhooks/clerk. Configure Clerk to deliver lifecycle events only to this canonical receiver.
webhookSignaturesvix-signature<token>Clerk webhook signature verification
application/json- body
type?string"user.created""user.updated""user.deleted"data?Webhook processed
application/json- response
received?booleancurl -X POST "https://example.com/api/webhooks/clerk" \
-H "Content-Type: application/json" \
-d '{}'{
"received": true
}Security
All webhook endpoints require signature verification to ensure requests originate from a trusted source.
Clerk Signature
Verify the svix-id, svix-timestamp, and svix-signature headers using your CLERK_WEBHOOK_SECRET.
Payload Schemas
Webhook payloads vary by event type. Refer to the specific service documentation for detailed object structures.
Idempotency
Providers may redeliver events. Each receiver uses its owning durable contract; a transport receipt is not proof that a business transition or notification was accepted.
The current Clerk receiver
uses command outcomes through @repo/idempotency/command: the verified Svix ID
identifies the command, with team/service actor scope and a canonical payload
hash. Domain synchronization and command completion follow the receiver's
transaction/retry contract. It does not use a generic body-hash webhook example
as its business authority.
Coupon automation uses the canonical producer's stable event identity and
canonical payload hash. Its bounded legacy compatibility path retains body-hash
receipt deduplication through processed_webhooks; that receipt alone cannot
prove feedback or authorize a notification. The durable worker boundary below
rechecks the records. Retryable receipt failures and permanent dispositions are
owned by the route, not an instruction to release any business command.
For command outcomes and provider receipt primitives, see the Idempotency package.
Coupon automation and durable event authority
The separate POST /api/automation/coupons receiver accepts canonical guest-event
transport and retains bounded legacy compatibility. Its
source owner
owns signature/authentication, validation, and compatibility behavior. It is not
the public guest activation or survey submission API.
Transport deduplication alone cannot authorize fulfillment or an alert. Canonical
messages retain the producer's stable eventId and converge on the existing guest
event queue identity. The owning worker reloads authoritative records and decides
eligible alerts, lifecycle no-ops, and gated recovery. A legacy rating hint cannot
send a notification without the corresponding durable feedback/response identity.
Queue/provider failures do not undo committed domain transitions. Route with the actual team/location and privacy-safe metadata, never Contact values, comments, private/public tokens, cookies, or staff proof. See Coupon and survey delivery.