OdyDocs

Retries and delivery

Timeouts, the retry schedule, what counts as success, ordering, and how to debug failing deliveries.

#What counts as success

Any 2xx response within 10 seconds. Anything else counts as a failure and is retried: a 3xx (redirects aren't followed), 4xx, 5xx, a timeout, a TLS error or a refused connection.

#Retry schedule

Each event gets up to three attempts per endpoint:

AttemptWhen
1Immediately
2About 5 seconds after attempt 1
3About 30 seconds after attempt 2

Every attempt is signed fresh, with a new webhook-timestamp, and keeps the same webhook-id. Once the third attempt fails, the delivery is marked failed and not tried again.

Plan for missed events

The retry window is short (well under a minute), so an endpoint that's down for a deploy can miss events. Make your integration self-healing: periodically reconcile against the API (for example, page through GET /conversations ordered by lastActivityAt), and treat webhooks as a fast path rather than the only source of truth. A longer retry window is on the roadmap.

Endpoints are never disabled automatically. To pause deliveries, set status: "disabled" with PATCH /webhooks/:id.

#Ordering and duplicates

  • Events for different endpoints, and successive events for one endpoint, are sent concurrently. Arrival order isn't guaranteed; a call.summary.completed can arrive before its call.completed.
  • The same event can arrive more than once (for example, your server processed it but the response timed out). Store processed ids, for at least a day, and skip repeats.

#Debugging

ToolWhat it shows
GET /webhooks/:id/deliveriesEvery delivery and each attempt's statusCode or error and durationMs
POST /webhooks/:id/testOne signed ping with the result inline. No retries
Delivery with a failed first attempt
{
  "id": "d7e1…",
  "webhookId": "3a8f…",
  "eventId": "evt_4f9b2c0d8e1a4b7c9d2e3f4a5b6c7d8e",
  "status": "success",
  "attempts": [
    { "at": "2026-10-14T18:05:42.400Z", "statusCode": 503, "durationMs": 88 },
    { "at": "2026-10-14T18:05:47.493Z", "statusCode": 200, "durationMs": 121 }
  ],
  "createdAt": "2026-10-14T18:05:47.620Z"
}

#Common failures

SymptomLikely cause
error: "The operation was aborted due to timeout"Your handler takes over 10s. Return 200 first, then process
statusCode: 401 or 403Your signature check is failing: raw body, wrong secret, or the secret was rotated
statusCode: 404 or 405Wrong path, or the route doesn't accept POST
statusCode: 301 or 308Redirects aren't followed. Register the final URL
error mentioning a certificateInvalid or self-signed TLS certificate
No deliveries at allEndpoint disabled, or not subscribed to that type. Check what each type needs in Event types: for example contact.updated doesn't fire for CSV imports, and call.ringing is inbound-only
Last updated Wed Oct 14 2026 00:00:00 GMT+0000 (Coordinated Universal Time)Something wrong on this page? Tell us