Create Tasks from Phone Calls using TwiML: Receive an Incoming Call

We've seen how to create Tasks using the TaskRouter REST API and how to accept a Task Reservation using both the REST API and Assignment Callback instructions. TaskRouter also introduces new TwiML instructions that you can use to create a Task from a Twilio phone call.

To receive an incoming phone call, we first need a Twilio phone number. In this example we'll use a US toll-free number, but you can use a Voice capable number from any country.

Before purchasing or setting up the phone number, we need to add on to our run.py to handle incoming calls:

run.py
# -*- coding: latin-1 -*-

from flask import Flask, request, Response
from twilio.rest import Client
from twilio.twiml.voice_response import VoiceResponse

app = Flask(__name__)

# Your Account Sid and Auth Token from twilio.com/user/account
account_sid = "{{ account_sid }}"
auth_token  = "{{ auth_token }}"
workspace_sid = "{{ workspace_sid }}"
workflow_sid = "{{ workflow_sid }}"

client = Client(account_sid, auth_token)

@app.route("/assignment_callback", methods=['GET', 'POST'])
def assignment_callback():
    """Respond to assignment callbacks with an acceptance and 200 response"""

    ret = '{"instruction": "accept"}'
    resp = Response(response=ret, status=200, mimetype='application/json')
    return resp

@app.route("/create_task", methods=['GET', 'POST'])
def create_task():
    """Creating a Task"""
    task = client.workspaces(workspace_sid) \
                 .tasks.create(workflow_sid=workflow_sid,
                               attributes='{"selected_language":"es"}')

    print(task.attributes)
    resp = Response({}, status=200, mimetype='application/json')
    return resp

@app.route("/accept_reservation", methods=['GET', 'POST'])
def accept_reservation(task_sid, reservation_sid):
    """Accepting a Reservation"""
    task_sid = request.args.get('task_sid')
    reservation_sid = request.args.get('reservation_sid')

    reservation = client.workspaces(workspace_sid) \
                        .tasks(task_sid) \
                        .reservations(reservation_sid) \
                        .update(reservation_status='accepted')

    print(reservation.reservation_status)
    print(reservation.worker_name)

    resp = Response({}, status=200, mimetype='application/json')
    return resp

@app.route("/incoming_call", methods=['GET', 'POST'])
def incoming_call():
    """Respond to incoming requests."""

    resp = VoiceResponse()
    with resp.gather(numDigits=1, action="/enqueue_call", method="POST", timeout=5) as g:
        g.say("Para Español oprime el uno.".decode("utf8"), language='es')
        g.say("For English, please hold or press two.", language='en')

    return str(resp)

if __name__ == "__main__":
    app.run(debug=True)

You can use the Buy Numbers section of the Twilio Voice and Messaging web portal to purchase a new phone number, or use an existing Twilio phone number. Open the phone number details page and point the Voice Request URL at your new endpoint:

Using any phone, call the Twilio number. You will be prompted to press one for Spanish or two for English. However, when you press a digit, you'll hear an error message. That's because our <Gather> verb is pointing to another endpoint, enqueue_call, which we haven't implemented yet. In the next step we'll add the required endpoint and use it to create a new Task based on the language selected by the caller.

Next: Create a Task using Enqueue »

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.