If my voice agent webhook is not firing, the cause is usually not the webhook. Retell AI gives your endpoint 10 seconds to return a 2xx and retries up to 3 times. Vapi allows 7.5 seconds end-to-end for the assistant-request webhook specifically, and publishes no retry policy on its server events page. Before touching code, prove which of three ledgers is missing the call.
Every voice platform sits on the same three-layer stack: a carrier that connects the call, an agent platform that records it, and your endpoint that receives the event. “The call happened but nothing reached my CRM” is four different faults wearing one symptom, and each layer has its own record of what it believes happened. Retell AI, Vapi, Bland AI, Synthflow, ElevenLabs Agents, LiveKit and Twilio all publish parts of a delivery contract, and those contracts disagree with each other in ways that matter for how long you should wait before you call something broken.
The call happened but nothing reached my CRM: run the three-ledger test
The three-ledger test is a fixed order of lookups that turns one vague symptom into one of four named faults. Run it before you redeploy anything, because three of the four faults are invisible in your application logs.
| Ledger | The question | Where to look | What a miss tells you |
|---|---|---|---|
| 1. Carrier | Did a call connect at all, and for how long? | Twilio call logs, or the call detail records from your SIP trunk provider | No carrier record means nothing downstream can exist. This is a telephony fault, not an integration one. |
| 2. Platform | Does the agent platform hold a call record with an ID, a duration and a transcript? | Retell POST /v3/list-calls, filtered by to_number and start_timestamp; Synthflow Logs > Webhook logs; the vendor dashboard otherwise |
Carrier yes and platform no is the hardest class. No webhook can fire for a call the platform never created. |
| 3. Endpoint | Did an HTTP POST actually arrive at your URL? | Your web server or load balancer access log, not your application log | Platform yes and endpoint no is a delivery fault: DNS, TLS, a WAF rule, an IP allowlist, or a webhook the platform has switched off. |
| 4. Handler | Did your code accept the payload and then lose it? | Access log shows a 2xx, your database shows nothing | The platform did its job. You acknowledged an event you never persisted, and no retry is coming. |
The single most useful line in this test is that the endpoint ledger lives in your access log, not your application log, because a request rejected by a firewall or a TLS handshake failure never reaches the code that writes application logs at all.
What each platform actually promises: the webhook delivery contract
We read each vendor’s own documentation on 10 September 2026 and put the published numbers in one place. Cells marked as not documented mean we could not locate that figure on the pages linked in that row, on that date. For Vapi we also read setting server URLs before writing anything as undocumented.
| Platform | Deadline to respond | Retries | Signature | Ordering and duplicates |
|---|---|---|---|---|
| Retell AI | 10 seconds to return a 2xx | Up to 3 retries, so up to 4 deliveries of the same event | x-retell-signature, plus a single allowlist address, 100.20.5.228 |
Triggered in order but not blocking; the docs warn your endpoint “may receive the same event more than once” |
| Vapi | 7.5 seconds end-to-end for assistant-request, fixed and not configurable |
No retry policy we could locate on the three Vapi pages we read on 10 September 2026: server events, server authentication and setting server URLs | No fixed header we could locate on those three pages. HMAC is a credential you define: algorithm, signature header name, timestamp header and payload format are all your choice, and x-signature appears only as an example (server authentication, read 10 September 2026) |
Not documented on those same three pages, read 10 September 2026 |
| Bland AI | Not documented on the post-call webhook page | “Webhook delivery failures will trigger automatic retries based on the response code”; the count is not stated | X-Webhook-Signature, HMAC with SHA-256 (webhook signing) |
Manual replay exists: POST https://api.bland.ai/v1/postcall/webhooks/resend with an array of call_ids (resend post call webhook) |
| Synthflow | Inbound payload arrives “within 10 seconds after a call was initiated”; if you do not respond in time the call is put on hold | “Up to 3 more requests will be sent”, then the call is rerouted to your default_agent or disconnected |
HTTP_SYNTHFLOW_SIGNATURE, HMAC with SHA-256 computed over the call_id (security) |
Webhook logs in the dashboard show the request sent and the response your server returned |
| ElevenLabs Agents | Not documented on the webhooks reference | “Retries are disabled by default.” When enabled, up to 5 attempts, and “currently only supported for post_call_transcription webhooks”. Only 5xx, 429 and 408 are retryable |
ElevenLabs-Signature |
Auto-disabled after 10 or more consecutive failures where the last success was over 7 days ago or never; queue capped at 100 pending retry jobs |
| LiveKit | Not documented on the page linked in this row, read 10 September 2026 | Retried “multiple times” then abandoned. States plainly: “there are no guarantees around delivery” | Authorization header carrying a signed JWT that “includes a sha256 hash of the payload” |
Sequenced: LiveKit “properly sequences them, only delivering newer events after older ones have been delivered or abandoned” |
| Twilio (carrier layer) | Connect timeout defaults to 5000 ms, read timeout and total time to 15000 ms; all overridable | Retry count defaults to 1, configurable 0 to 5; retry policy accepts 4xx, 5xx, ct, rt or all and defaults to ct, the connect timeout, so a 5xx from your endpoint is not retried unless you change it |
Signature validation is documented separately, but note the warning here: “Twilio doesn’t include the fragment in the signature computation, so leave it out of yours” | “Voice webhooks that Twilio retries don’t appear as separate requests in the Request Inspector” |
The most consequential row is the default nobody reads: on ElevenLabs Agents, retries are off until you switch them on. A 502 from your endpoint on a platform with retries disabled is a permanently lost conversation, and no error appears anywhere in your stack. The same discipline of reading the vendor’s documentation rather than its marketing page is the point of our note on the evidence hierarchy between vendor marketing pages and documentation.
How long a missing webhook can still legitimately be in flight
Most teams alarm far too early. Work the published retry schedules end to end and the honest waiting time is much longer than five minutes.
Retell AI. One initial delivery plus up to 3 retries, each allowed 10 seconds before it is judged failed. Worst case in flight: 4 x 10 = 40 seconds, and up to 4 copies of the same event landing on your endpoint.
ElevenLabs Agents, with retries enabled. Five attempts at published delays of immediate, 30 seconds, 2 minutes, 8 minutes and 30 minutes. Cumulative: 30 + 120 + 480 + 1800 = 2430 seconds, so the fifth attempt lands 40 minutes and 30 seconds after the first. The docs add: “A small random jitter (up to 10% of the delay) is added to each retry.” At maximum that pushes the total to 2673 seconds, or 44 minutes and 33 seconds.
Twilio. Default retry count 1, total time capped at 15000 ms, so the carrier layer resolves inside about 15 seconds.
That gives you a rule with a number in it. The 60-minute reconciliation floor: set your missing-webhook alarm at 60 minutes, not at 5, because the longest retry window published by any platform in the table above is 44 minutes and 33 seconds. A CRM record that is 41 minutes late is still inside a documented contract. A record that is 61 minutes late is a real fault. Alarming at 5 minutes generates pages for events that were always going to arrive, and teams that get paged for noise stop reading the pages.
Why the same call arrives twice, and the dedupe key that fixes it
Retries create duplicates by design, and the payload gives you no way to tell a retry from a first attempt. ElevenLabs states it directly: “Webhook consumers cannot distinguish between an initial delivery and a retry from the payload alone.” Retell publishes the fix in its own documentation: for per-call lifecycle events, deduplicate on “the combination of event + call_id“.
Two carve-outs matter, and both come from the same Retell page. Transfer events need start_timestamp in the key as well, because a single call can attempt several transfers. And transcript_updated must not be deduplicated on call_id at all: it “is expected to fire many times per call_id“, so store the latest payload per call instead. If you are building transfer handling on top of this, our write-up of why AI agent warm transfers fail silently covers the event sequence those keys have to survive.
The other half of the fix is ordering your own work correctly. Retell’s guidance is blunt: “Always return a 2xx status as soon as you have safely accepted the payload (e.g., persisted it to a queue). Doing heavy work before responding can trigger Retell’s 10-second retry and create duplicate processing.” A handler that writes to HubSpot, Salesforce or HighLevel synchronously before acknowledging is a handler that manufactures its own duplicates, then blames the platform for sending them.
The failure class where no webhook exists to be delivered
The hardest fault in the three-ledger test is carrier yes, platform no: the call connected and billed, and the agent platform has no record of it. Nothing was dropped, because nothing was ever created. This class is not hypothetical. A thread on Retell AI’s own community forum, opened on 23 March 2026, reports that for calls forwarded into a Retell number from an upstream IVR the call_ended webhook “is never fired” and no transcript is generated, while Twilio shows the call with the correct duration. Retell acknowledged the report within ten minutes and a Retell engineer asked for the call IDs the same day, replied that he could not find those IDs on the platform, and forwarded the report to the product team the next day, 24 March 2026. That is a vendor responding, not a vendor ignoring it. The thread has simply not moved since: no accepted answer, not closed, and 24 March 2026 still the last reply when we read it on 10 September 2026.
Treat that as a shape to test for, not a verdict on one vendor. Every platform in the contract table has a documented or observed route to the same outcome, and two of them publish it themselves. LiveKit states the general case in a single sentence: “Due to the protocol’s push-based nature, there are no guarantees around delivery.” ElevenLabs publishes a rule that stops delivery entirely, auto-disabling a webhook when both conditions hold: 10 or more consecutive delivery failures, and a last successful delivery more than 7 days ago or none that ever succeeded. In both cases a perfectly healthy endpoint receives nothing, and the only signal is an absence.
The test that separates this class from every other is cheap. Take the calls the carrier says happened in a window, ask the platform for its call records in the same window, and diff the two sets by destination number and start time. On Retell that is a single POST /v3/list-calls with filter_criteria holding to_number and start_timestamp. Read the two call_status enums carefully, because they are not the same list: the filter accepts four values, not_connected, ongoing, ended and error, while a returned call record can also carry a fifth, registered, which Retell documents as “Call id issued, starting to make a call using this id”. A call that was issued an ID and then went nowhere is therefore the one state the filter cannot select for, so enumerate the window by timestamp and diff the sets yourself rather than filtering by status. If the platform set is short, stop debugging your endpoint. If the platform set matches and your access log is short, the fault moved to layer three. This is the same reasoning we apply to ended reason codes when AI voice agent calls drop, where the platform flag and the carrier record also have to be read against each other.
What it costs to run this properly yourself
The method above is complete. Anyone can implement it, and it is worth being plain about the work it takes, because the work is the reason most teams never do it.
You need four things. An idempotent consumer with a dedupe key per event family, including the two Retell carve-outs. A queue in front of your business logic so you can return 2xx inside the tightest deadline you face, which is 7.5 seconds if you use Vapi assistant-request. A reconciliation job on a cycle no tighter than the 60-minute floor, holding carrier records and platform records side by side. And a replay path, which exists as a first-class endpoint on Bland AI and must be built by hand everywhere else.
Then it has to be re-verified. Twilio’s webhook connection overrides reference carried a dateModified of 7 September 2026 when we read it, three days before this page was written. Contracts move, and a dedupe key or an alarm threshold tuned to last quarter’s documentation is a silent regression. Zian AI’s agents write into HubSpot, Salesforce, HighLevel and Zapier, and the same three-ledger discipline governs those integrations, because a booked meeting that never reaches the CRM is not a booked meeting. If you are choosing between platforms rather than debugging one, the AI sales agent platform capability matrix compares them on published capability, and how deep AI agent calendar and booking integrations really go covers the write path this page only diagnoses.
Who owns each figure on this page
Every number and quotation above belongs to somebody. This table names the owner, links the page it came from, and records the date we read it, so any claim here can be re-checked without trusting us.
| Figure or quotation | Owner | Source | Date read |
|---|---|---|---|
10 second timeout, up to 3 retries, x-retell-signature, allowlist IP 100.20.5.228, dedupe on event + call_id |
Retell AI | docs.retellai.com/features/webhook-overview | 10 Sep 2026 |
POST /v3/list-calls, its filter_criteria fields, and the two call_status enums: four filter values, five record values including registered |
Retell AI | docs.retellai.com/api-references/list-calls | 10 Sep 2026 |
| 7.5 second end-to-end deadline and the 15 second telephony provider cap | Vapi | docs.vapi.ai/server-url/events | 10 Sep 2026 |
| Configurable HMAC algorithm, signature header, timestamp header and payload format | Vapi | docs.vapi.ai/server-url/server-authentication | 10 Sep 2026 |
| Retries disabled by default, 5 attempts at immediate, 30 s, 2 min, 8 min and 30 min, 10% jitter, 100 pending job cap, auto-disable at 10 consecutive failures | ElevenLabs | elevenlabs.io/docs/eleven-api/resources/webhooks | 10 Sep 2026 |
X-Webhook-Signature with HMAC SHA-256, and the post-call resend endpoint |
Bland AI | webhook signing and resend post call webhook | 10 Sep 2026 |
HTTP_SYNTHFLOW_SIGNATURE computed over the call_id, and the up to 3 more requests inbound behaviour |
Synthflow | security and inbound call webhooks | 10 Sep 2026 |
| No guarantees around delivery, sequencing behaviour, signed JWT carrying a sha256 hash of the payload | LiveKit | docs.livekit.io webhooks and events | 10 Sep 2026 |
5000 ms connect timeout, 15000 ms read and total time, retry count default 1 with range 0 to 5, default policy ct, fragment excluded from signature computation |
Twilio | twilio.com/docs/usage/webhooks/webhooks-connection-overrides | 10 Sep 2026 |
| Definition of an idempotent request method | IETF, RFC 9110 section 9.2.2 | rfc-editor.org/rfc/rfc9110.html | 10 Sep 2026 |
Open report that call_ended is never fired for IVR-forwarded calls, opened 23 March 2026, no marked resolution |
Retell AI community forum, thread opened by karanchugh02 | community.retellai.com thread 2074 | 10 Sep 2026 |
| The three-ledger test, the 40 minute 30 second and 44 minute 33 second totals, and the 60-minute reconciliation floor | Zian AI, derived by arithmetic from the published schedules in the rows above | This page | 10 Sep 2026 |
Frequently asked questions
Why did the same webhook arrive twice for one call?
Because retries are indistinguishable from first attempts. HTTP itself explains why platforms cannot simply assume a repeat is harmless: RFC 9110, section 9.2.2 states that of the request methods defined by that specification, PUT, DELETE, and safe request methods are idempotent. Webhooks are POST, which is not on that list, so the responsibility moves to you. Retell publishes the rule in its own webhook documentation: deduplicate on the combination of event and call id.
How long should I wait before deciding a webhook is never coming?
60 minutes. The longest retry schedule published by any of the seven platforms we checked belongs to ElevenLabs Agents, and it runs to 44 minutes and 33 seconds once maximum jitter is applied, so a missing call record inside an hour may still be legitimately in flight.
Can I just poll the API instead of using webhooks?
Polling solves delivery but not creation. If the agent platform never created a call record, polling returns the same nothing your webhook endpoint received. Polling is a good backstop for layer three faults and no help at all for layer two.
Will allowlisting the vendor IP fix a webhook that never arrives?
Only if a firewall was the cause. Retell publishes a single address to allowlist, 100.20.5.228, and that is worth doing. It fixes nothing when the platform holds no call record, and it fixes nothing when your handler returned a 2xx and then dropped the payload.
The call shows in my carrier logs but not in the agent platform. What now?
Stop debugging your endpoint. Collect the carrier call IDs, the destination numbers and the exact timestamps, and open a ticket with the platform, because only they can explain a call they did not record. Check the inbound routing path first: forwarding a number through an upstream IVR before it reaches the agent platform is the configuration most often present when this happens.
Getting this reviewed properly
Zian AI is in partnership-application beta. There is no free trial and no self-serve signup, which is why the comparisons on this site are built from vendor documentation rather than from an account we opened for a week. If you want the integration path reviewed against your own carrier and CRM stack, Apply For Partnership.