If your endpoint returns a server error (5xx), we retry the webhook automatically every 3 minutes for up to 15 minutes after the event. Client errors (4xx) are never retried. When something happens to an order or a route in your account, we send a webhook to the callback URL in your app's webhook settings. Every webhook we send is recorded with its delivery status and the HTTP status code your endpoint returned. If a delivery fails because your server had a temporary problem, the retry worker sends it again so you do not miss the event.
Which responses are retried
Whether we retry depends only on the HTTP status code your endpoint returns.
| Your endpoint returns | Resulting status | Retried? |
|---|---|---|
| 2xx (e.g. 200, 204) | SUCCEEDED | No, delivery is complete |
| 5xx (e.g. 500, 502, 503) | PENDING | Yes, on the next retry run |
| 4xx (e.g. 400, 401, 404) | REJECTED | No, never |
A 4xx response tells us the request itself was refused, so sending it again would fail the same way. If you need us to try again later, return a 5xx code instead of a 4xx.
Retry schedule
A retry worker runs every 3 minutes and resends every webhook that is still PENDING. A failed webhook is therefore normally retried within 3 minutes.
| Time after the event | What happens |
|---|---|
| 0 min | First delivery attempt |
| up to 3 min | First retry, if the first attempt returned 5xx |
| every 3 min after that | Another retry while the webhook is still PENDING |
| 15 min | Webhook becomes STALE; no more retries |
In practice this gives a webhook about four to five retries before the 15-minute window closes. The retry interval is fixed; it does not grow between attempts.
When retries stop
A webhook stops being retried as soon as it reaches any status other than PENDING.
| Status | Meaning | Retried? |
|---|---|---|
| PENDING | Waiting for delivery or for the next retry | Yes |
| SUCCEEDED | Your endpoint accepted it with a 2xx response | No |
| REJECTED | Your endpoint refused it with a 4xx response | No |
| STALE | Replaced by a newer webhook, or older than 15 minutes | No |
A webhook becomes STALE in two cases:
- A newer webhook replaces it. If we send a newer webhook of the same type for the same order or route, the older pending one is dropped. You get the latest state instead of an outdated one.
- It is more than 15 minutes old. After 15 minutes the event is considered out of date and is not delivered.
A STALE webhook is not sent again. To catch up on missed changes, fetch the current state of the order or route through the API.
Building a reliable endpoint
- Return a 2xx as soon as you receive the webhook. Do heavy processing afterwards, so slow work does not cause a failure.
- Use the right error code. Return 5xx for temporary problems you want retried, such as a database outage. Return 4xx only when the request should never be retried.
- Handle duplicates. The same webhook can arrive more than once, so make sure processing it twice has no extra effect.
- Recover within 15 minutes. After that window, pending webhooks are dropped; use the API to resync any missed changes.
FAQ
My server was down for a few minutes. Will I lose webhooks? No, as long as it was returning 5xx errors and comes back within 15 minutes. Pending webhooks are retried on the next run, normally within 3 minutes.
I returned a 404 by mistake. Will the webhook be resent? No. Any 4xx response marks the webhook REJECTED for good. Fetch the latest order or route state through the API instead.
Why did I receive only the latest update for an order? When a newer webhook of the same type is sent for the same order or route, older pending ones become STALE and are not delivered.
Can I change the retry interval or the 15-minute window? Not at the moment. Both values are fixed for all apps.
