The <Dial> element connects the current call to another phone number, SIP endpoint, or Plivo user. When the dialed party answers, both parties are connected. When either party hangs up, the connection ends.
Type of call. Values: voice, whatsapp. When set to whatsapp, the call is placed as a WhatsApp voice call (cannot route to PSTN, does not support machine detection)
Custom SIP headers in key=value format, specific to this user within the dial
sipAuthUsername
string
-
SIP digest authentication username. Used when calling a SIP endpoint that requires authentication (responds with 401/407 challenge). Must be paired with sipAuthPassword. See SIP Authentication.
sipAuthPassword
string
-
SIP digest authentication password (8-128 characters). Required when sipAuthUsername is provided. Credentials are stripped before forwarding calls externally.
Attribute names are camelCase (sipAuthUsername, not sip_auth_username).Authenticated SIP call example:
Hangup causes on auth failure:If outbound SIP authentication fails, the Dial action URL receives these values:
DialHangupCause
Code
DialStatus
Meaning
sip_auth_failed
4240
failed
Remote provider rejected the credentials
sip_auth_timeout
4250
timeout
Remote provider did not respond to the auth challenge
Reserved sipHeaders prefixes:Customer sipHeaders keys with the following prefixes (case-insensitive) are silently dropped: PH-, Plivo, FS-, SipAuth, ZT-, Twilio. The exact name ClientRegion is also reserved. See SIP Authentication for details.Raw-mode rendering with SIP authentication:When the inbound leg used SIP authentication, sipHeaders are emitted on the outbound B-leg INVITE without the X-PH- prefix (e.g., CustomerId=123 renders as X-CustomerId: 123 rather than X-PH-CustomerId: 123).
<Response> <Dial timeout="15" action="/dial-status/"> <Number>+14155551111</Number> </Dial> <Dial timeout="15" action="/dial-status/"> <Number>+14155552222</Number> </Dial> <Speak>Sorry, no one is available. Please try again later.</Speak></Response>
from plivo import plivoxmlresponse = plivoxml.ResponseElement()# First attemptdial1 = plivoxml.DialElement(timeout=15, action='/dial-status/')dial1.add(plivoxml.NumberElement('+14155551111'))response.add(dial1)# Second attemptdial2 = plivoxml.DialElement(timeout=15, action='/dial-status/')dial2.add(plivoxml.NumberElement('+14155552222'))response.add(dial2)response.add(plivoxml.SpeakElement('Sorry, no one is available.'))print(response.to_string())
<Response> <Speak>Thank you for calling. Goodbye!</Speak> <Hangup/></Response>
from plivo import plivoxmlresponse = plivoxml.ResponseElement()response.add(plivoxml.SpeakElement('Thank you for calling. Goodbye!'))response.add(plivoxml.HangupElement())print(response.to_string())
<Response> <Speak>This call will end in 60 seconds.</Speak> <Hangup schedule="60"/> <Play loop="0">https://example.com/hold-music.mp3</Play></Response>
This schedules a hangup while continuing to execute subsequent elements.
@app.route('/answer/', methods=['POST'])def answer(): response = plivoxml.ResponseElement() if not is_business_hours(): response.add(plivoxml.SpeakElement( 'Our office is currently closed. Please call back during business hours.' )) response.add(plivoxml.HangupElement()) else: response.add(plivoxml.SpeakElement('Welcome! Please hold.')) dial = plivoxml.DialElement() dial.add(plivoxml.NumberElement('+14155551234')) response.add(dial) return Response(response.to_string(), mimetype='application/xml')
@app.route('/answer/', methods=['POST'])def answer(): caller = request.form.get('From') response = plivoxml.ResponseElement() if is_blocked(caller): response.add(plivoxml.HangupElement(reason='rejected')) else: response.add(plivoxml.SpeakElement('Hello! How can I help you?')) # Continue with normal flow return Response(response.to_string(), mimetype='application/xml')
If your XML doesn’t end with <Hangup>, the call automatically ends when all elements are executed. However, it’s good practice to include it explicitly for clarity.
<Response> <Speak>Please hold while we connect you.</Speak> <Wait length="5"/> <Speak>Thank you for waiting.</Speak></Response>
from plivo import plivoxmlresponse = plivoxml.ResponseElement()response.add(plivoxml.SpeakElement('Please hold while we connect you.'))response.add(plivoxml.WaitElement(length=5))response.add(plivoxml.SpeakElement('Thank you for waiting.'))print(response.to_string())
<Response> <Wait length="5" beep="true"/> <Speak> Hello, this is a reminder from Dr. Smith's office about your appointment tomorrow at 2 PM. Please call us at 555-1234 to confirm. </Speak></Response>
The <PreAnswer> element plays audio to the caller before the call is answered. This is useful for custom ringback tones or screening calls. The caller is not billed during this phase.
<Response> <PreAnswer> <Speak>Please wait while we connect your call.</Speak> </PreAnswer> <Dial> <Number>+14155551234</Number> </Dial></Response>
from plivo import plivoxmlresponse = plivoxml.ResponseElement()preanswer = plivoxml.PreAnswerElement()preanswer.add(plivoxml.SpeakElement('Please wait while we connect your call.'))response.add(preanswer)dial = plivoxml.DialElement()dial.add(plivoxml.NumberElement('+14155551234'))response.add(dial)print(response.to_string())