python-3.xtwiliocallforward

Forward unanswered calls in Twilio using python


Has anybody been able to capture the Twilio DialCallStatus? It's referred in many Twilio online documents but I never see one while debugging python scripts. I only see CallStatus such as in the following dump of request.values.

REQUEST VALUES>>> CombinedMultiDict([ImmutableMultiDict([]), ImmutableMultiDict([('AccountSid', 'ACxxxxxxx'), ('ApiVersion', '2010-04-01'), ('CallSid', 'CA0c9f4e7eb73dfcd72f273451c6aa249c'), ('CallStatus', 'in-progress'), ('Called', '+1785xxxxxxx'), ('CalledCity', 'TOPEKA'), ('CalledCountry', 'US'), ('CalledState', 'KS'), ('CalledZip', '66603'), ('Caller', '+1630xxxxxxx'), ('CallerCity', 'ROSELLE'), ('CallerCountry', 'US'), ('CallerState', 'IL'), ('CallerZip', '60193'), ('Digits', '1'), ('Direction', 'inbound'), ('FinishedOnKey', ''), ('From', '+1630xxxxxxx'), ('FromCity', 'ROSELLE'), ('FromCountry', 'US'), ('FromState', 'IL'), ('FromZip', '60193'), ('To', '+1785xxxxxxx'), ('ToCity', 'TOPEKA'), ('ToCountry', 'US'), ('ToState', 'KS'), ('ToZip', '66603'), ('msg', 'Gather End')])])

Actually, I need to forward an unanswered incoming call to another phone number and it seems to be a good time to do that when "no-answer" is reported in call back events. However, at that point, it seems that the call flow has been ended and response.dial.number('next-number') does not work any more.

Has anybody done that in the past?

#This is the route where the initial incoming call is answered
@app.route('/gather', methods=['GET', 'POST'])  
def gather():
    resp = VoiceResponse()
    dial = Dial(timeout=30)
    dial.number(
        '+1-initial-called-number',
        status_callback_event='initiated ringing answered completed busy failed no-answer canceled',
        status_callback='https://my.ngrok.io/response',
        status_callback_method='POST',
    )
    resp.append(dial)
    return str(resp)

@app.route('/response', methods=['POST'])        #This is the call back route
def outbound():
    status=request.values.get('CallStatus', None)
    resp = VoiceResponse()
    if (status=='no-answer'):
        resp.dial(timeout=20).number('+1-next-number')
    return str(resp)

Solution

  • Yes, I receive a DialCallStatus parameter. This is after a Dial completes and executes the Action url. Here is some Twiml:

    <?xml version="1.0" encoding="utf-8"?>
    <Response>
        <Dial action="https:XXXXXX/api/twilio/voice/noanswer" timeout="20">
            <Sip>sip:XXXXXX.sip.us1.twilio.com</Sip>
        </Dial>
    </Response>
    

    The https:XXXXXX/api/twilio/voice/noanswer endpoint receives the DialCallCstatus at the completion of the Dial. The Sip part in the example doesn't really matter - the same is true for Number, Client, and Conference actions. Once the Sip, Number, Client, or Conference completes the Dial action URL is called and will have that parameter. The documentation says it is the terminal status for the Dial command.

    I do not know Python well but it seems your example code is missing the Action url. Example code from Twilio for Python is in the "Specify an action URL and method"

    from twilio.twiml.voice_response import Dial, VoiceResponse, Say
    
    response = VoiceResponse()
    response.dial('415-123-4567', action='/api/twilio/voice/noanswer', method='GET')
    response.say('I am unreachable')
    
    print(response)