Skip to main content
This page covers the mechanics of getting events to your endpoint reliably: what counts as a successful delivery, what happens when your endpoint fails, and how to build a handler that never loses an event. This applies to the account-level webhooks configured under Account → Webhooks. Other CloudTalk features that call an endpoint you own (the Call Flow Designer Webhook step, an AI Voice Agent’s Send via Webhook option, Workflow Automation actions) use their own delivery path and are not covered here. See the overview.

What counts as a successful delivery

A delivery succeeds when your endpoint responds with any 2xx status code within 15 seconds. Anything else is a failed attempt: a 4xx or 5xx, a timeout, a connection error, and 3xx redirects, which are not followed. Respond before you process. Do the minimum to durably accept the event (verify the signature, push it onto a queue), return 200, and do the real work asynchronously. Handlers that do heavy work inline risk hitting the timeout and receiving duplicate deliveries.

Retries

A failed delivery is retried automatically: up to 50 times over roughly 11.5 hours, with the delays growing quickly at first and then settling into a steady cadence: Every retry of an event carries the same event_id in the body and the same svix-id header, so a retry that arrives after a slow-but-successful first attempt is easy to recognise and skip. If all retries fail, that delivery is marked failed in the endpoint’s delivery log. Nothing is lost: you can resend it or recover a whole time range once your endpoint is healthy again.

Automatic disabling and re-enabling

An endpoint that fails continuously for about 5 days is disabled automatically, and no further events are sent to it. This protects both sides: a dead endpoint doesn’t accumulate an endless backlog. Disabling isn’t the end, though. For the next 12 hours, CloudTalk keeps probing the endpoint with a test event, backing off from a few minutes to a couple of hours between probes. The moment a probe gets a 2xx, the endpoint is re-enabled automatically and the deliveries that failed while it was down are replayed. If it hasn’t recovered within those 12 hours, it stays disabled until you re-enable it yourself. Account admins receive an email when an endpoint is automatically disabled and again when it is re-enabled. To re-enable an endpoint manually: fix the endpoint, open it under Account → Webhooks, switch it back on, then use Recover to replay the deliveries that failed while it was disabled.
The simplest way to never get disabled: return 200 as soon as the event is safely queued, and keep the processing that can fail out of the request path.

Delivery log, test events, and replay

Every endpoint under Account → Webhooks has its own operations panel:
  • Delivery log: every delivery attempt with its event type, status, response code, and time.
  • Resend: redeliver any single event from the log, for example after fixing a bug in your handler.
  • Recover: replay every failed delivery since a time you choose, in one action. Use it after an outage on your side.
  • Send test event: pick an event type and CloudTalk sends a sample payload to your endpoint, so you can verify connectivity and signature handling before real traffic arrives.

Data retention

Event payloads are stored for 30 days. Within that window you can open a delivery in the log, inspect the payload CloudTalk sent, resend it, or recover a range of failed deliveries. After 30 days the payload is deleted and can no longer be viewed or replayed. Plan around it: your own system should be the system of record for anything you need long term. Thirty days is comfortably longer than the retry and auto-disable windows above, so a normal outage never risks losing replayable events.

Duplicates and idempotency

Delivery is at-least-once: in rare situations (a retry racing a slow response, infrastructure failover) the same event is delivered more than once. Duplicates always carry the same event_id. Make your handler idempotent: claim the event_id before you do the work, not after. Insert it into a store with a uniqueness constraint (a unique index, SET NX in Redis, or an equivalent atomic operation) and only proceed when the insert succeeds. Checking first and recording afterwards leaves a window in which a retry and the original delivery, or two workers, both pass the check and both repeat the side effect. Keep those records for at least as long as you might replay. Resend and Recover reach back over the full 30-day retention window, so a store that expires after an hour will happily reprocess a three-week-old delivery and repeat whatever side effect it had. Thirty days of event_ids is the safe floor; a durable idempotency key on the work itself (the order you create, the ticket you open) is better still.

Ordering

Events are not guaranteed to arrive in order: a call.answered can occasionally arrive before its call.started, and events for different resources interleave freely.
  • Sort by occurred_at when sequence matters.
  • Don’t treat a “later” lifecycle event as an error when the earlier one hasn’t arrived yet.
  • When you need the current state of a resource rather than its history, fetch it from the REST API instead of reconstructing it from events.

Best practices

Reject requests that fail signature verification with a 401. Never process an unverified payload.
Return 2xx as soon as the event is durably accepted: queue it and process in the background. This keeps you inside the timeout and lets you absorb bursts.
Track processed event_ids and skip repeats. De-duplication plus idempotent processing makes at-least-once delivery indistinguishable from exactly-once.
New event types and new optional fields appear over time without a version bump. Ignore event types you don’t handle and fields you don’t recognize instead of failing.
Fewer subscribed events means less traffic to secure, queue, and pay attention to, especially high-frequency events like user.status_changed.
Web frameworks often apply CSRF checks to all POST routes. Your webhook route authenticates via signatures, not sessions: exempt it, or every delivery will be rejected.
Endpoints must be HTTPS. Expired or self-signed certificates cause failed deliveries that count toward automatic disabling.

Payload conventions worth knowing

  • Empty means absent. Optional fields with no value are omitted, never null.
  • Timestamps are RFC 3339 UTC (2026-08-17T09:34:21.512Z); sub-second precision may vary.
  • Versioning is per event type. version bumps only on breaking changes; both versions may be delivered during a migration window while you switch over.
  • Recordings and transcripts arrive by reference, never inline: fetch them through the API with your own credentials.