Skip to main content
Webhooks are the doorbell; the endpoints are the truth. Delivery is at-least-once and unordered, so the pattern that holds up is: verify the signature, dedupe on the event id, act on the payload, and reconcile with the cursor feeds on a schedule.

Registering an endpoint

Settings → Integrations → API access → Webhook endpoints → Add endpoint. Admins only. The signing secret (whsec_…) is shown once when the endpoint is created. Store it beside your API key; every delivery must be verified with it. Rotate secret issues a new one at any time — deliveries already queued are signed with the new secret from their next attempt, so update your side first.

The envelope

Every delivery is a POST with Content-Type: application/json:

Headers

What your endpoint must do

  1. Verify the signature before trusting anything in the body.
  2. Respond 2xx within 10 seconds. Queue the work and acknowledge; a slow handler is retried as a failure and you receive the event again.
  3. Dedupe on id. You will see the same event more than once — a retry after a timeout that actually succeeded is the common case.
  4. Ignore what you do not recognise. New event types and new fields ship without notice.

Testing an endpoint

Send test on the endpoint posts an integration.ping synchronously and shows the status code your URL returned. The delivery is recorded like any other, so it appears in the delivery log with its attempt and outcome.

Observability

  • The endpoint list shows last success, last error, and a consecutive failures count.
  • View deliveries on an endpoint lists recent deliveries with status (pending, delivered, dead), attempts, last HTTP status, and last error. Dead deliveries can be retried from there.
  • Consumers can read the same log with an API key: GET /webhook-deliveries?status=dead.
Retry timing, dead-lettering, and automatic disabling are on Delivery and retries.