Webhook Retries: How They Work

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 returnsResulting statusRetried?
2xx (e.g. 200, 204)SUCCEEDEDNo, delivery is complete
5xx (e.g. 500, 502, 503)PENDINGYes, on the next retry run
4xx (e.g. 400, 401, 404)REJECTEDNo, 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 eventWhat happens
0 minFirst delivery attempt
up to 3 minFirst retry, if the first attempt returned 5xx
every 3 min after thatAnother retry while the webhook is still PENDING
15 minWebhook 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.

StatusMeaningRetried?
PENDINGWaiting for delivery or for the next retryYes
SUCCEEDEDYour endpoint accepted it with a 2xx responseNo
REJECTEDYour endpoint refused it with a 4xx responseNo
STALEReplaced by a newer webhook, or older than 15 minutesNo

A webhook becomes STALE in two cases:

  1. 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.
  2. 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.