Skip to contentSkip to navigationSkip to topbar
Rate this page:
On this page

Create Tasks from Phone Calls using TwiML: Dequeue a Call to a Worker


In the previous step we created a Task from an incoming phone call using <Enqueue workflowSid="WW0123401234..">. In this step we will create another call and dequeue it to an eligible Worker when one becomes available.

Back in Part 1 of the Quickstart, we created a Worker named Alice that is capable of handling both English and Spanish inquiries. With your Workspace open in the TaskRouter web portal(link takes you to an external page), click 'Workers' and click to edit the details of our Worker Alice. Ensure that Alice is set to a non-available Activity state such as 'Offline'. Next, edit Alice's JSON attributes and add a "contact_uri" field. Replace the dummy 555 number below with your own phone number.

Alice's modified JSON attributes:


_10
{"languages": ["en", "es"], "contact_uri": "+15555555555"}

Or, as displayed in the web portal:

In this step, we again use <Enqueue> to create a Task from an incoming phone call. When an eligible Worker (in this case Alice) becomes available, TaskRouter will make a request to our Assignment Callback URL. This time, we will respond with a special 'dequeue' instruction; this tells Twilio to call Alice at her 'contact_uri' and bridge to the caller.

For this part of the Quickstart, although not totally necessary it will be useful to have two phones available - one to call your Twilio number, and one to receive a call as Alice. Experienced Twilio users might consider using the Twilio Dev Phone as one of the endpoints.

Before we add the 'dequeue' assignment instruction we need to create a new Activity in our TaskRouter Workspace. One of the nice things about integrating TaskRouter with TwiML is that our Worker will automatically transition through various Activities as the call is assigned, answered and even hung up. We need an Activity for our Worker to transition to when the call ends.

With your Workspace open in the TaskRouter web portal(link takes you to an external page), click 'Activities' and then 'Create Activity'. Give the new Activity a name of 'WrapUp' and a value of 'unavailable'. Once you've saved it, make a note of the Activity Sid:

Create a WrapUp Activity.

To return the 'dequeue' assignment instruction, modify Program.cs assignment_callback endpoint to now issue a dequeue instruction, substituting your new WrapUp ActivitySid between the curly braces:

Alice's Worker Details.

Program.cs

programcs page anchor

_111
using System;
_111
using System.Net;
_111
using SimpleWebServer;
_111
using Twilio;
_111
using Twilio.Rest.Taskrouter.V1.Workspace;
_111
using Twilio.Rest.Taskrouter.V1.Workspace.Task;
_111
using Twilio.TwiML;
_111
_111
namespace taskroutercsharp
_111
{
_111
class MainClass
_111
{
_111
// Find your Account Sid and Auth Token at twilio.com/user/account
_111
const string AccountSid = "{{ account_sid }}";
_111
const string AuthToken = "{{ auth_token }}";
_111
const string WorkspaceSid = "{{ workspace_sid }}";
_111
const string WorkflowSid = "{{ workflow_sid }}";
_111
_111
public static void Main (string[] args)
_111
{
_111
// Initialize the Twilio client
_111
TwilioClient.Init(AccountSid, AuthToken);
_111
_111
WebServer ws = new WebServer (SendResponse, "http://localhost:8080/");
_111
ws.Run ();
_111
Console.WriteLine ("A simple webserver. Press a key to quit.");
_111
Console.ReadKey ();
_111
ws.Stop ();
_111
}
_111
_111
public static HttpListenerResponse SendResponse(HttpListenerContext ctx)
_111
{
_111
HttpListenerRequest request = ctx.Request;
_111
HttpListenerResponse response = ctx.Response;
_111
_111
String endpoint = request.RawUrl;
_111
_111
if (endpoint.EndsWith("assignment_callback")) {
_111
response.StatusCode = (int) HttpStatusCode.OK;
_111
response.ContentType = "application/json";
_111
response.StatusDescription = "{\"instruction\":\"dequeue\", \"from\":\"+15556667777\", \"post_work_activity_sid\":\"WA0123401234...\"}";
_111
return response;
_111
} else if (endpoint.EndsWith ("create_task")) {
_111
response.StatusCode = (int)HttpStatusCode.OK;
_111
response.ContentType = "application/json";
_111
TaskResource task = TaskResource.Create(
_111
WorkspaceSid,
_111
attributes: "{\"selected_language\":\"es\"}",
_111
workflowSid: WorkflowSid);
_111
_111
response.StatusDescription = task.Attributes;
_111
return response;
_111
} else if (endpoint.EndsWith ("accept_reservation")) {
_111
response.StatusCode = (int)HttpStatusCode.OK;
_111
response.ContentType = "application/json";
_111
var taskSid = request.QueryString ["TaskSid"];
_111
var reservationSid = request.QueryString ["ReservationSid"];
_111
ReservationResource reservation = ReservationResource.Update(
_111
WorkspaceSid,
_111
taskSid,
_111
reservationSid,
_111
ReservationResource.StatusEnum.Accepted);
_111
_111
response.StatusDescription = "{\"reservation_status\":\"" + reservation.ReservationStatus + "\"}";
_111
return response;
_111
} else if (endpoint.EndsWith ("incoming_call")) {
_111
response.StatusCode = (int)HttpStatusCode.OK;
_111
response.ContentType = "application/xml";
_111
var twiml = new VoiceResponse();
_111
twiml.Gather(new Gather(numDigits: 1, action: "enqueue_call")
_111
.Say("Para Espanol oprima el uno.", language: "es")
_111
.Say("For English, please hold or press two.", language: "en"));
_111
_111
response.StatusDescription = twiml.ToString();
_111
return response;
_111
} else if (endpoint.Contains("enqueue_call")) {
_111
response.StatusCode = (int)HttpStatusCode.OK;
_111
response.ContentType = "application/xml";
_111
_111
int digitPressed = 0;
_111
var language = "";
_111
var digitsQuery = request.QueryString["Digits"];
_111
if(digitsQuery != null) {
_111
try
_111
{
_111
digitPressed = Int32.Parse(request.QueryString ["Digits"]);
_111
} catch (FormatException e)
_111
{
_111
Console.WriteLine(e.Message);
_111
}
_111
}
_111
_111
if (digitPressed == 1) {
_111
language = "es";
_111
} else {
_111
language = "en";
_111
}
_111
_111
var twiml = new VoiceResponse();
_111
twiml.Enqueue(
_111
"{\"selected_language\":" + language + "\"}",
_111
workflowSid: WorkflowSid);
_111
_111
response.StatusDescription = twiml.ToString();
_111
return response;
_111
}
_111
response.StatusCode = (int) HttpStatusCode.OK;
_111
return response;
_111
}
_111
}
_111
}

This returns a very simple JSON object from the Assignment Callback URL:



_10
{"instruction":"dequeue", "from": "+15556667777", "post_work_activity_sid": "WA01234012340123401234"}

The JSON instructs Twilio to dequeue the waiting call and, because we don't include an explicit "to" field in our JSON, connect it to our Worker at their "contact_uri". This is convenient default behavior provided by TaskRouter.

In the next step, we test our incoming call flow from end-to-end.

Next: End-to-End Phone Call Task Assignment »


Rate this page: