Webhook Retry Windows Across 7 Carrier APIs
We audited published webhook retry policies for FedEx, DHL, EasyPost, Shippo, ShipEngine, and Sendcloud, with intervals, attempt counts, and sources.
Every multi-carrier platform we've torn down handles webhook failure differently, and the published retry windows range from roughly 15 minutes to more than 7 hours. If you're building a carrier webhook retry policy into your idempotency layer, that spread is the whole ballgame: a dedup key sized for FedEx will drop events from DHL. This is a docs audit, not a live-fire test, so treat every number below as "what the vendor says it does," not "what we measured it doing."
Why retry windows are a design constraint, not a footnote
If you don't know how long a carrier keeps retrying a failed webhook, you can't size your idempotency key TTL, your dedup window, or your "did we miss an event" reconciliation job correctly. Get it wrong in one direction and you burn storage on keys that will never see a duplicate. Get it wrong in the other and a slow deploy window causes silent data loss with no error, no alert, nothing. The carrier just gives up and moves on.
Method
We pulled the current, publicly published webhook and retry documentation page for each provider on August 25, 2026 and recorded attempt count, interval pattern, response timeout, and total retry window where the vendor actually discloses one. No live endpoint was fired at any of these providers to time real behavior. That's the obvious follow-up, not this post.
What's not in this table:
- Freight and LTL EDI-based event delivery, including DB Schenker, which doesn't publish a comparable webhook retry spec
- Regional parcel carriers without a public retry document, including UPS, GLS, and DPD
- nShift, which we checked for a public retry schedule and found none published
Where a figure isn't publicly documented, it's marked "Not published." No interpolation, no vendor-support-chat guesses.
The numbers
| Provider | Type | Max attempts | Backoff pattern | Response timeout | Approx. total window | Source |
|---|---|---|---|---|---|---|
| FedEx | Direct carrier | 3 retries | 5-minute intervals | Not published | ~10-15 min | FedEx Developer Portal |
| DHL (eCommerce Americas) | Direct carrier | 3 delivery attempts | 1st retry after 1 hr; 2nd retry 6 hrs after that | 5 sec | ~7 hrs | DHL Developer Portal |
| EasyPost | Multi-carrier platform | Up to 6 retries | Increasing delay, exact schedule not published | 7 sec | Not published | EasyPost Webhooks Guide |
| Shippo | Multi-carrier platform | 2 retries | Not published (interval between retries not stated) | 3 sec | Not published | Shippo Webhooks docs |
| ShipEngine | Multi-carrier platform | 2 additional attempts (3 total) | Typically 30 min apart | 10 sec | ~1 hr | ShipEngine Webhooks docs |
| Sendcloud | Multi-carrier platform | 10 retries | Exponential, starting at 5 min, capped at 1 hr | Not published | Not published | Sendcloud API Developer Portal |
| UPS, GLS, DPD, DB Schenker, nShift | Direct carrier / platform | Not published | Not published | Not published | Not published | No public retry spec found at time of check |
Two things jump out. If a receiving system doesn't reply with a valid response within DHL's window, the system retries delivery in 1 hour, then 6 hours after the second attempt, and if the third delivery fails it will not try to send the event again, which is the longest window of any provider checked. FedEx sits at the opposite end: FedEx will hold the data and attempt to resend it within a span of 3 retries within 5 minute intervals, and if it doesn't receive a successful response in that time span, it will stop redelivery of that specific event.
Where the docs disagree with themselves
ShipEngine's current webhooks page states ShipStation API allows 10 seconds to acknowledge a payload, and if no acknowledgement arrives it makes a maximum of two additional attempts, typically separated by 30 minutes, before removing the event from the dispatch queue if all three attempts get no response. A separate ShipStation blog post on the same webhook system states something different: webhook delivery will be attempted 3 times with a 2-hour delay between each attempt, after which it will be discarded. Same vendor, same feature, two different retry cadences depending on which page you land on. If you built your dedup TTL off the blog post, you'd be under-provisioned by roughly 5.5 hours against what the live docs actually promise.
Shippo has the same pattern. A 2016 hackathon setup guide describes a completely different schedule than the current docs. Back then, if Shippo didn't receive a successful response it would re-try the POST request up to 5 times, with a 10 second delay between each, for a total of 6 messages within 1 minute, disabling the webhook if the 5th try also failed. The current documentation says something narrower: if your webhook endpoint doesn't process the payload in a timely manner or returns a 408, 429, or 5XX status code, Shippo will retry twice, with no retry attempted on other client error status codes. Five retries dropped to two, and the timing detail disappeared entirely. Retry policies change. Don't hardcode assumptions from a doc page you read eight months ago.
What this means for idempotency key TTL and dedup design
If you support DHL, your idempotency window needs to survive at least the roughly 7-hour span its retry sequence covers. If you're only handling FedEx-style webhooks, 15 minutes might be enough. A multi-carrier stack has to size for the longest vendor in the mix, not the shortest, which usually means DHL sets your floor whether you like it or not.
There's a second risk hiding in the short-window providers. Shippo, FedEx, and ShipEngine all give up within roughly an hour or less. Any receiver outage longer than that window means the event is gone, no retry, no notification, nothing in your logs to flag it. That's not a bug, it's the documented behavior. If your on-call rotation has ever had an outage longer than an hour, you've probably already lost webhook events from at least one of these providers without knowing it. A polling-based reconciliation job against the carrier's tracking API is the only real mitigation.
The multi-carrier abstraction problem
Platforms sitting between shippers and carriers all have to normalize this mess for their customers. EasyPost, Shippo, ShipEngine, Sendcloud, and Cargoson each run their own retry and dedup layer on top of whatever the underlying carrier does, precisely because raw carrier retry behavior is this inconsistent. That's a legitimate part of the value proposition for any multi-carrier API, and it's worth asking any vendor you're evaluating exactly what their own outbound retry policy looks like, not just what the carrier behind them does.
Follow-ups we'd run next
Docs describe intended behavior, not observed behavior. The obvious next step is a live test harness that fires intentional 500s at a public endpoint through a webhook-testing proxy and timestamps actual retry arrivals for each provider, then compares observed intervals against what's published here. We'd also want to check whether sandbox environments follow the same retry schedule as production, since we've seen that assumption break before on other endpoints.
If you've logged actual retry timestamps against any of these providers in production, we'd like to see them. Docs are a starting point, not a substitute for your own harness logs.