Webhooks
Retries and failures
What happens when your endpoint does not answer.
A delivery succeeds on any 2xx. Anything else — including a timeout — is a failure and is retried.
Schedule
Six attempts total, with five gaps:
| After attempt | Wait |
|---|---|
| 1 | 30 seconds |
| 2 | 2 minutes |
| 3 | 10 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
After the sixth attempt the delivery is marked exhausted and is not retried again.
Timeouts
| Connect timeout | 5 seconds |
| Request timeout | 10 seconds |
Acknowledge quickly and process asynchronously. If your handler does real work inline — writing to a slow database, calling another API — you will hit the 10-second ceiling and be retried, and your handler will run again on a call it already processed. Return 2xx first, work after.
Designing a handler that survives retries
- Verify the signature first. See verifying signatures.
- Deduplicate on
delivery.idempotency_key. It is identical across all six attempts. - Return 2xx for events you do not recognise. A 4xx on
webhook.testmakes a healthy endpoint look broken. - Do not rely on ordering. Retries mean a later call's event can arrive before an earlier call's.