Webhooks
Delivery & Retries
Each event is delivered as a single HTTP POST to the endpoint URL configured for that environment.
What counts as a successful delivery
| Requirement | Value |
|---|---|
| Response deadline | 5 seconds |
| Success status codes | Any 2xx (200 to 299) |
| Response body captured for logging | First 1,000 characters |
Anything else, including a timeout, a non-2xx status, or a connection failure, is recorded as a failed delivery and queued for retry.
Because the deadline applies to your response and not to your processing, endpoints that do slow work should acknowledge the delivery first and process the payload afterwards.
Retries
A failed delivery is attempted up to seven times in total, with a longer wait after each failure:
| Attempt | Sent |
|---|---|
| 1 | Immediately |
| 2 | 1 second after attempt 1 |
| 3 | 1 minute after attempt 2 |
| 4 | 5 minutes after attempt 3 |
| 5 | 30 minutes after attempt 4 |
| 6 | 2 hours after attempt 5 |
| 7 | 1 day after attempt 6 |
The sequence spans a little over 26 hours. Once the seventh attempt fails the delivery is exhausted and is not tried again.
The X-UserCheck-Attempt header carries the current attempt number, so you can tell a retry from a first delivery.
When retries stop early
Not every failure is retried. A response showing the endpoint is misconfigured, rather than temporarily unavailable, ends the delivery immediately:
| Response | Behavior |
|---|---|
2xx |
Delivered |
3xx |
Rejected. Redirects are not followed, so the subscription needs to point at the final URL |
4xx other than 429 |
Rejected. The endpoint refused the payload rather than failing to receive it |
429 |
Retried |
5xx, timeout, or connection error |
Retried |
An endpoint that keeps failing is never disabled. Later events are still delivered to it however many earlier deliveries were exhausted.
Duplicate deliveries
Deliveries are not guaranteed to be unique, so the same event can arrive more than once. The X-UserCheck-Delivery-ID header and the idempotency_key payload field both identify the delivery and stay the same across all of its attempts, so recording the IDs you have already handled, and ignoring repeats, keeps an event from being processed twice.
Delivery attempts and their responses are visible in the webhook's history in the dashboard.