# Delivery and retries

## How it works

mondochat creates one delivery per enabled endpoint subscribed to the event type. It sends each delivery signed, through an egress proxy that refuses private and internal addresses.

- Your endpoint has 15 seconds to answer. Any 2xx answer is a success.
- Any non-2xx answer or a timeout is a failure and the delivery is retried.
- Attempts follow this schedule: 0s, 5s, 5m, 30m, 2h, 5h, 10h, 14h, 20h and 24h. After the last attempt the delivery is marked dead.
- Answering `410 Gone` disables the endpoint.
- The dashboard lists every delivery with its status, response code and attempts. It can replay one: a new delivery with the same `webhook-id`.
- **Send test event** on the endpoint sends one `webhook.test` delivery to that endpoint alone and shows your response code.

Callouts are different. They are answered within 5 seconds, a network error is retried once and anything else is a failure. See [Webhooks overview](/webhooks/overview/).

## Limits

- Timeout: 15 seconds per attempt. Do slow work after you answer.
- Events arrive in no guaranteed order. When the current state matters, fetch the resource from the API instead of rebuilding it from the order of events.
- A delivery can arrive more than once. The `webhook-id` header is the same on every retry and on a replay: drop duplicates by `webhook-id`.
- Webhooks go to your server with the real `last_seen_at` and read pointer, whatever the users' `last_seen` and `read_receipts` settings say.

## Where it ends

- After the last attempt, 24 hours in, a delivery is dead and is not retried again. It stays in the dashboard list, where you can replay it.
- mondochat does not promise exactly once delivery. Make your handler safe to run twice.

## Related topics

- [Verify signatures](/webhooks/verify/)
- [Webhooks overview](/webhooks/overview/)
- [Event catalog](/reference/webhook-events/)
- [`webhook.test`](/api/webhooks/webhook-test/)
- [Errors](/errors/)