Retry policy
ModelRiver makes up to 3 delivery attempts in total for each webhook: the original attempt plus 2 automatic retries. Retries use a short exponential backoff, so all automatic attempts happen within a few minutes of the original delivery, not hours.
If all 3 attempts fail, the delivery is marked as failed in your Request Logs. There is no dead letter queue: no further automatic attempts are made. You can retry it manually for a short time afterwards (see Manual retries).
Successful delivery
Your endpoint should return a 2xx status code (preferably 200 OK) to acknowledge successful receipt. ModelRiver considers any 2xx response as successful and will not retry.
Failed delivery
Any of the following triggers a retry:
- Non-2xx status code (4xx, 5xx)
- Network timeout (ModelRiver waits up to 30 seconds for a response)
- Connection refused or DNS resolution failure
- TLS handshake failure
Monitoring webhooks
All webhook deliveries are logged in your project's Request Logs:
- Timeline view shows each delivery record (the original delivery and any manual retries) with timestamps
- Status indicators mark success, failure, or in-progress deliveries
- Payload inspection lets you view the exact data sent
- Callback logs (for backend pipeline workflows) show your backend's response
Use the Backend pipeline endpoint filter to isolate backend pipeline requests.
Manual retries
After automatic retries are exhausted, you can retry a failed delivery yourself. The original payload is resent to the endpoint currently configured for the webhook, and each manual retry creates a new delivery record.
- Console: Open the request in Request Logs and click Retry on the failed webhook delivery. Retry is available only within 5 minutes of the first delivery attempt and at least 30 seconds after the delivery you are retrying. Each delivery can be retried once, with at most 2 manual retries per request.
- API:
POST /v1/webhooks/{delivery_id}/retryqueues a new attempt. It is accepted only within 5 minutes of when that delivery was sent; later calls return400withevent_expired.
Best practices
- Respond quickly: Return
200 OKimmediately and process webhooks asynchronously in a background job - Implement idempotency: Use
channel_idas a deduplication key since retries may deliver the same payload multiple times - Monitor delivery rates: Track webhook success rates in Observability to catch endpoint issues early
- Use health checks: Ensure your webhook endpoint is monitored and alerts you to downtime
- Log failures: Record non-2xx responses with details to debug integration issues
Next steps
- Standard webhooks: Payload structure reference
- Signature verification: Secure your endpoints
- Observability: Monitor webhook delivery timelines