# Retries & Replay

> Delivery schedule, automatic disabling, the delivery log, and replaying from the portal or API.

Canonical: https://grout.app/developer/documentation/webhooks/retries/

## Delivery rules

- Timeout **10 seconds**. Success is any `2xx`. Redirects are not followed.
- Failures retry at **+1 m, +5 m, +30 m, +2 h, +12 h** — six attempts in total — then the delivery is marked `dead`.
- A `410 Gone` disables the endpoint immediately. **30 consecutive failures** also disable it (`disabled_reason: too_many_failures`).
- Re-enable a disabled endpoint with `PATCH { "status": "active" }`; the failure counter resets.
- Deliveries and events are retained **30 days**.

## Delivery log

Portal: **Developers → Deliveries** (admin) or the endpoint page on the developer dashboard. API:

```bash
curl "$API/webhooks/deliveries?status=dead" -H "Authorization: Bearer $KEY"
curl "$API/webhooks/deliveries?endpoint_id=we_…&event_type=exam.graded" -H "Authorization: Bearer $KEY"
curl $API/webhooks/deliveries/whd_… -H "Authorization: Bearer $KEY"     # payload + your response body
```

Each row shows status (`pending`, `delivering`, `succeeded`, `failed`, `dead`), attempt count, next attempt time, HTTP status, response time and the first 2 KB of your response.

## Replay

```bash
curl -X POST $API/webhooks/deliveries/whd_…/replay -H "Authorization: Bearer $KEY"
```

Replay creates a **new** delivery (`replay_of` points at the original) with a fresh signature timestamp. Use it after fixing a bug on your side. You can also replay an event to a different endpoint from the portal's event browser.

## Polling fallback

If you cannot receive webhooks at all:

```bash
curl "$API/events?since=2026-09-14T09:00:00Z&type=exam.*&limit=200" -H "Authorization: Bearer $KEY"
```

Persist the newest `created_at` you processed and pass it as `since` next time.

## Operational tips

- Respond `202` immediately and process from a queue.
- Alert when `GET /webhooks/endpoints` shows `status: disabled` or `consecutive_failures > 5`.
- Keep the endpoint idempotent on `id`; a replay or a retry after a timeout can deliver the same event twice.
