Skip to content
ResponseOutcome
2xxSuccess.
408, 429, any 5xxRetryable.
Any other 4xxPermanent failure — status failed, no retries.
Timeout, connection error, DNS failureRetryable.
1xx, 3xxRetryable. The endpoint is misbehaving, not refusing.

The distinction matters: a 404 from your endpoint means the route does not exist, and retrying for five hours will not create it. A 500 means your app broke on a request it accepted, so retrying is exactly right.

Return a 2xx as soon as the payload is safely on your side and do the work afterwards. A handler that finishes the job before answering will eventually hit the timeout, and a timeout is a failure.

The default schedule is 30s, 2m, 10m, 1h, 4h: five retries after the first attempt, covering about five and a half hours. Each delay carries ±20% jitter so that a destination coming back up is not hit by every queued retry at once.

The schedule is per destination and can be changed through the API — up to 10 intervals, each between 1 second and 24 hours. A short schedule fails fast; a long one holds a backlog longer. How exponential backoff is tuned in practice covers what the providers themselves do, if you are picking your own intervals.

When the last interval has been tried and failed, the delivery becomes exhausted and moves to the dead-letter queue.

Five consecutive retryable failures open a destination’s circuit. While it is open, deliveries to that endpoint pause for a cooldown that starts at 60 seconds and doubles on each re-open, up to 10 minutes. One probe is then let through:

StateShown asMeaning
closedNormal. Everything is being attempted.
openCircuit openCooling down. Deliveries wait.
half_openRecoveringOne probe in flight. Success closes the circuit, failure re-opens it.

Any response that proves the endpoint is reachable — a 2xx, or even a 4xx — closes the circuit and resets the counter. Nothing is lost while a circuit is open; deliveries queue and resume.

The source’s Dead letters tab lists deliveries that ended as exhausted or failed, with the last error and last response status for each, and a summary per gateway. Filter by all, exhausted or failed.

This is the list to work through after an outage: fix the endpoint, then replay. A dead-letter queue is what keeps an outage from becoming permanent data loss — the reasoning behind it is worth reading before you design the runbook around it.

The Dead letters tab of a sourceThe Dead letters tab of a source
Dead letters, grouped by destination. Replay all recreates every exhausted delivery as a fresh pending one.

One event. Open the event and resend it. New deliveries are created and run the normal retry schedule. Disabled gateways are included — a resend is an explicit operator action, not automatic traffic.

A backlog. Replay in bulk per gateway, optionally narrowed to a status and a time window. The default targets exhausted deliveries, which is the usual “my endpoint was down for two hours” case:

Terminal window
curl -X POST https://app.webhooker.eu/api/v1/deliveries/resend-bulk \
-H "Authorization: Bearer $WEBHOOKER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"connection_id": "…",
"statuses": ["exhausted", "failed"],
"since": "2026-09-18T00:00:00Z"
}'
{ "created": 143 }

Replay is only possible while the events are still inside your retention window.