When Twilio returns DialCallStatus=completed but no person ever spoke to the caller, the cause is almost always one of four things: the dialed person's carrier voicemail answered the leg (a declined call, a phone that is off, or a ring window shorter than your timeout), a call screening URL ended the leg with <Hangup>, which Twilio also reports as completed, a screening prompt fell through without a keypress and bridged the caller into the voicemail anyway, or your code treated completed as proof a human answered. The fix is to put a call screening whisper on the dialed <Number> that only bridges on a keypress, and to branch your action URL on DialBridged, not on DialCallStatus. Answering Machine Detection is the alternative when you cannot ask the person to press a key.
A quick definition. <Dial> is the TwiML verb that places a second call leg (the child call) from a live inbound call (the parent call) and connects the two. When the child leg ends, Twilio requests the URL in the action attribute and sends DialCallStatus, DialCallSid, DialCallDuration and DialBridged, and whatever TwiML you return controls what the caller hears next. DialCallStatus tells you how the child leg ended. DialBridged tells you whether it was ever connected to the caller. Those are different questions, and this bug lives in the gap between them.
We ran into this on one of our own lines. The flow rang a person's cell for a few seconds with <Dial> and, if nobody picked up, handed the caller to an AI receptionist through the action URL. When the person declined a call, their carrier voicemail answered, Twilio reported completed, and the caller sat in a voicemail box instead of reaching the agent. The same failure shows up in any ring-then-fallback flow: missed call text back, sales routing in a speed to lead system, or forwarding that keeps landing in personal voicemail, which we cover in Google Voice forwarded calls going to voicemail.
Why does DialCallStatus say completed when voicemail answers?
Twilio reports completed whenever the dialed leg is answered, and a carrier voicemail answering is an answer as far as the phone network is concerned. Twilio documents completed as the called party answering and being connected. Voicemail picks up the line exactly the way a person does, so Twilio cannot tell the two apart without extra work. no-answer only appears when nothing answers before your timeout, and a declined or unreachable mobile call is often answered by voicemail before that timeout ever arrives.
Glossary, in one line each. Whisper (call screening): TwiML that plays to the person you dialed after they answer and before the caller is connected. Bridged: the two legs are actually connected and can hear each other. AMD: Twilio Answering Machine Detection, which listens to the first seconds of the answered leg and guesses human or machine.
The four causes we find most often.
- Carrier voicemail answered the leg: the person declined the call, the phone was off or out of coverage, or their ring-to-voicemail window is shorter than your
timeout, so voicemail picks up and Twilio sees an answer - Whisper ended with Hangup: since a TwiML change dated 2020.12.09, a
<Hangup>or<Reject>in the screening URL setsDialCallStatustocompleted, where it used to beno-answer, so screened-out calls look answered too - Screening prompt fell through:
<Gather>timed out with no keypress, control fell to the next verb, there was none, the whisper document ended, and the caller was bridged into the voicemail - Logic keyed on the wrong field: the action handler treats
completedas a human answer and returns empty TwiML, so the call either ends or sits in voicemail instead of falling back
How do you verify what actually answered?
Read the parameters Twilio posted to your action URL and the child call's log, not the status label in your own database. Three checks, in this order.
The action URL request. Log the full request body your action endpoint receives. The fields that matter are DialCallStatus, DialBridged, DialCallDuration and DialCallSid. A voicemail answer without screening shows completed with DialBridged=true and a duration that matches how long the caller sat there. A screened-out call shows completed with DialBridged=false.
Call Logs in the Twilio Console. Open Monitor, then Logs, then Calls, find the parent call, and open the child call by the DialCallSid.
The Request Inspector and Debugger. In the same call detail view, read the requests Twilio made to your whisper and Gather URLs and the TwiML you returned. If the Gather action was never requested, nobody pressed a key. If your whisper document has no verb after <Gather>, you have found the fall-through.
Diagnose top to bottom.
This is the order we run. Each step stops at one layer.
DialCallStatus and DialBridged side by side for the failing call.timeout on <Dial> defaults to 30 seconds, accepts 5 to 600, and Twilio adds a five-second buffer, so a value of 10 rings for about 15. If the person's voicemail answers inside that window, lowering the timeout alone will not save you.completed.url on the <Number> noun to a TwiML document with a <Gather numDigits="1"> that says press 1 to accept, followed by <Hangup/>. Set answerOnBridge="true" on the <Dial> so the caller keeps hearing ringing while the whisper runs.Digits is 1 and return TwiML that ends without a hangup, which lets the bridge proceed. Any other digit returns <Hangup/>. A voicemail greeting never presses 1, so the Gather times out, hits the Hangup, and the leg ends unbridged.DialBridged is true. Everything else, including completed with DialBridged=false, no-answer, busy, failed and canceled, goes to your fallback: the AI agent, a queue, or a callback flow.DialBridged=false or no-answer.What DialCallStatus values can Twilio return?
Twilio documents six values: completed, answered, busy, no-answer, failed and canceled, and only DialBridged tells you whether the caller was ever connected. As of October 2026 the docs define them as follows, and the last column is how we read each one in a ring-then-fallback flow.
| DialCallStatus | Twilio's meaning | How we treat it |
|---|---|---|
| completed | Called party answered and was connected | Answered only if DialBridged is true. Voicemail and screened-out calls also land here |
| answered | Called party answered, when dialing into a Conference | Only relevant to Conference dials |
| busy | Twilio received a busy signal | Fallback |
| no-answer | Called party did not pick up before the timeout | Fallback |
| failed | Twilio could not route to the number | Fallback, and alert on it, since it is usually a bad number |
| canceled | Call canceled via the REST API before it was answered | Fallback, unless your own code canceled it on purpose |
Symptoms, causes and fixes.
A completed status with DialBridged=false means the dialed leg answered but was never connected to the caller. The table below is the reference we use when a ring-then-fallback flow misbehaves.
| Symptom | Likely cause | Fix |
|---|---|---|
| Caller hears a personal voicemail greeting | Carrier voicemail answered the child leg | Add a keypress whisper on the Number url |
| Status is completed, no conversation happened | Code trusts DialCallStatus | Branch on DialBridged instead |
| Status completed, DialBridged false | Whisper ended with Hangup (expected since 2020.12.09) | Route to fallback; this is the screen working |
| Caller bridged into voicemail despite a whisper | No Hangup after Gather, so it fell through | Put Hangup as the verb after Gather |
| Declined calls never reach the fallback | Decline sends the call to carrier voicemail | Keypress whisper plus DialBridged check |
| Fallback fires later than expected | Five-second buffer added to timeout | Set timeout about 5 seconds below your target |
| Real person answers, call drops | They did not press the key in time | Clear prompt, longer Gather timeout, repeat once |
| Caller hears silence while the dialed person screens | answerOnBridge not set | Set answerOnBridge to true on Dial |
Should you use Answering Machine Detection instead?
AMD works on <Dial><Number> through the machineDetection attribute, but it is a guess, it costs time, and Twilio warns it can misread very short voicemail greetings as a human.
How it works. Set machineDetection to Enable to get a result as soon as Twilio decides, with AnsweredBy values of human, machine_start, fax or unknown. Set it to DetectMessageEnd to wait for the end of the greeting, which adds machine_end_beep, machine_end_silence and machine_end_other. The results arrive at amdStatusCallback. machineDetectionTimeout runs from 3 to 59 seconds with a default of 30, and returns unknown when it expires. The speech and silence thresholds (machineDetectionSpeechThreshold default 2400 ms, machineDetectionSpeechEndThreshold default 1200 ms, machineDetectionSilenceTimeout default 5000 ms) trade accuracy against speed.
The tradeoffs we weigh. AMD adds a per-call charge on answered calls (check Twilio's voice pricing page for your country). Synchronous detection holds the call until a result comes back, and the caller is waiting through that. You still have to act on the result yourself, for example by ending the child leg when AnsweredBy starts with machine, and you need a rule for unknown. A keypress screen is deterministic: no keypress, no bridge. For your own team's phones we use the screen. For outbound calls to the public, AMD is the practical choice.
What is normal and what is a red flag?
A ring window about five seconds longer than your timeout value is normal, because Twilio adds a five-second buffer to every <Dial>. Also normal once screening is live: some calls return completed with DialBridged=false. Those are declines and voicemails your screen caught.
Red flags: any completed call with DialBridged=true and no conversation in the recording, which means voicemail got bridged and your whisper is falling through. And a whisper URL that never appears in the request log, which means the url attribute is on the wrong element or returning an error. If these calls also feed ad reporting, check the downstream side with website call conversions showing zero and CallRail GA4 integration, because a voicemail counted as an answered call inflates call conversions too.
Why does Twilio say completed when the call went to voicemail?
Because voicemail answered the dialed leg, and Twilio documents completed as the called party answering and being connected. The network does not tell Twilio whether a person or a voicemail system picked up. Use a keypress whisper or Answering Machine Detection to tell them apart.
What is DialBridged in Twilio?
DialBridged is a parameter Twilio sends to the Dial action URL. It is true only if the dialed call was actually connected to the parent call. Twilio added it in a TwiML change dated 2020.12.09 so you can tell a screened-out call apart from a bridged one, since both can report completed.
How do I make Twilio only connect a call when a human answers?
Add a url attribute on the Number noun that returns a Gather asking the person to press 1, followed by Hangup. Set answerOnBridge to true on Dial. In the Gather action, let the call proceed only when the digit is 1. A voicemail never presses a key, so it never gets bridged.
What is the default timeout for Twilio Dial?
30 seconds. The minimum is 5 and the maximum is 600. Twilio adds a five-second buffer, so the real ring time is about five seconds longer than the value you set.
Does Answering Machine Detection work with Dial?
Yes. The Number noun supports machineDetection, machineDetectionTimeout, the speech and silence thresholds, and amdStatusCallback. Detection is a guess, it can misread very short greetings, it adds a charge on answered calls, and you still have to act on the AnsweredBy result yourself.
Why does my screened call still connect to voicemail?
Almost always because nothing follows the Gather in the whisper TwiML. When Gather times out without input, Twilio moves to the next verb, and when the whisper document ends, the call connects. Add Hangup after the Gather.