Retries and replay
How usend retries failed webhook deliveries, and how to replay them.
Retries
A delivery succeeds when your endpoint returns a 2xx status within 20 seconds. Anything else is a failure: a 4xx or 5xx status, a redirect (redirects are not followed), a timeout or a connection error.
Failed deliveries are retried with exponential backoff, up to 13 attempts in total spread over roughly a day. The wait grows quickly: seconds after the first failure, minutes after a few, and hours towards the end.
Every attempt is signed again with a fresh webhook-timestamp, but keeps the same webhook-id, so you can recognize a retry of an event you already processed.
Make your handler idempotent: store the webhook-id of each processed event and skip it if it arrives again.
Delivery log
Each event sent to a webhook is a delivery. See them in the dashboard on the webhook's page, or with the API:
curl "https://api.usend.et/webhooks/4dd369bc-aa82-4ff3-97de-514ae3000ee0/deliveries?limit=20" \
-H "Authorization: Bearer us_123456789"{
"object": "list",
"data": [
{
"id": "2b7c4a51-1f0e-4f6e-9c8a-7d2f3e9a6b10",
"event_type": "email.delivered",
"status": "failed",
"attempts": 13,
"response_status": 500,
"last_error": "endpoint returned HTTP 500",
"created_at": "2026-10-10T09:12:47.118Z",
"delivered_at": null
}
],
"has_more": false
}status | Meaning |
|---|---|
pending | Not delivered yet. Attempts may still be in progress. |
succeeded | Your endpoint returned 2xx. delivered_at says when. |
failed | Every attempt failed. |
attempts counts the attempts made, response_status is the last HTTP status received (null if there was no response), and last_error describes the last failure. Deliveries are kept for 30 days.
Replay a delivery
After fixing your endpoint, send a delivery again:
curl -X POST https://api.usend.et/webhooks/4dd369bc-aa82-4ff3-97de-514ae3000ee0/deliveries/2b7c4a51-1f0e-4f6e-9c8a-7d2f3e9a6b10/replay \
-H "Authorization: Bearer us_123456789"The delivery goes back to pending and is sent again with the original payload and the same webhook-id. You can replay any delivery, including successful ones.
Disabled webhooks
While a webhook is disabled (enabled: false), new events are not recorded for it, and pending retries are not sent. Re-enable it with PATCH /webhooks/{id} and { "enabled": true }, then replay the deliveries you need.