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"}

Ensure you use the E.164 format for the contact_uri. Or, as displayed in the web portal:

Alice's Worker Details.

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 Twilio Client 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 TwilioTaskRouterServlet assignment_callback endpoint to now issue a dequeue instruction, substituting your new WrapUp ActivitySid between the curly braces:


TwilioTaskRouterServlet.java

twiliotaskrouterservletjava page anchor

_115
import java.io.IOException;
_115
import java.util.HashMap;
_115
import java.util.Map;
_115
_115
import javax.servlet.http.HttpServlet;
_115
import javax.servlet.http.HttpServletRequest;
_115
import javax.servlet.http.HttpServletResponse;
_115
_115
import org.json.simple.JSONObject;
_115
_115
import com.twilio.Twilio;
_115
import com.twilio.rest.taskrouter.v1.workspace.Task;
_115
import com.twilio.rest.taskrouter.v1.workspace.task.Reservation;
_115
import com.twilio.twiml.*;
_115
_115
public class TwilioTaskRouterServlet extends HttpServlet {
_115
_115
private String accountSid;
_115
private String authToken;
_115
private String workspaceSid;
_115
private String workflowSid;
_115
_115
@Override
_115
public void init() {
_115
accountSid = this.getServletConfig().getInitParameter("AccountSid");
_115
authToken = this.getServletConfig().getInitParameter("AuthToken");
_115
workspaceSid = this.getServletConfig().getInitParameter("WorkspaceSid");
_115
workflowSid = this.getServletConfig().getInitParameter("WorkflowSid");
_115
_115
Twilio.init(accountSid, authToken);
_115
}
_115
_115
// service() responds to both GET and POST requests.
_115
// You can also use doGet() or doPost()
_115
@Override
_115
public void service(final HttpServletRequest request, final HttpServletResponse response)
_115
throws IOException {
_115
if (request.getPathInfo() == null || request.getPathInfo().isEmpty()) {
_115
return;
_115
}
_115
_115
if (request.getPathInfo().equals("/assignment_callback")) {
_115
response.setContentType("application/json");
_115
_115
Map<String, String> dequeueInstruction = new HashMap<String, String>();
_115
dequeueInstruction.put("instruction", "dequeue");
_115
dequeueInstruction.put("from", "<caller_number>");
_115
dequeueInstruction.put("post_work_activity_sid", "WA0123401234...");
_115
_115
response.getWriter().print(JSONObject.toJSONString(dequeueInstruction));
_115
} else if (request.getPathInfo().equals("/create_task")) {
_115
response.setContentType("application/json");
_115
response.getWriter().print(createTask());
_115
} else if (request.getPathInfo().equals("/accept_reservation")) {
_115
response.setContentType("application/json");
_115
String taskSid = request.getParameter("TaskSid");
_115
String reservationSid = request.getParameter("ReservationSid");
_115
response.getWriter().print(acceptReservation(taskSid, reservationSid));
_115
} else if (request.getPathInfo().equals("/incoming_call")) {
_115
response.setContentType("application/xml");
_115
response.getWriter().print(handleIncomingCall());
_115
} else if (request.getPathInfo().equals("/enqueue_call")) {
_115
response.setContentType("application/xml");
_115
response.getWriter().print(enqueueTask());
_115
}
_115
}
_115
_115
public String createTask() {
_115
String attributes = "{\"selected_language\":\"es\"}";
_115
_115
Task task = Task.creator(workspaceSid, attributes, workflowSid).create();
_115
_115
return "{\"task_sid\":\"" + task.getSid() + "\"}";
_115
}
_115
_115
public String acceptReservation(final String taskSid, final String reservationSid) {
_115
Reservation reservation = Reservation.updater(workspaceSid, taskSid, reservationSid)
_115
.setReservationStatus(Reservation.Status.ACCEPTED).update();
_115
_115
return "{\"worker_name\":\"" + reservation.getWorkerName() + "\"}";
_115
}
_115
_115
public String handleIncomingCall() {
_115
VoiceResponse twiml =
_115
new VoiceResponse.Builder()
_115
.gather(new Gather.Builder()
_115
.say(new Say.Builder("Para Español oprime el uno.").language(Say.Language.ES)
_115
.build())
_115
.say(new Say.Builder("For English, please hold or press two.")
_115
.language(Say.Language.EN).build())
_115
.numDigits(1).timeout(5).build())
_115
.build();
_115
_115
try {
_115
return twiml.toXml();
_115
} catch (TwiMLException e) {
_115
return "Error creating TwiML: " + e.getMessage();
_115
}
_115
}
_115
_115
public String enqueueTask() {
_115
com.twilio.twiml.Task task =
_115
new com.twilio.twiml.Task.Builder().data("{\"selected_language\":\"es\"}").build();
_115
_115
EnqueueTask enqueue = new EnqueueTask.Builder(task).workflowSid(workflowSid).build();
_115
_115
VoiceResponse twiml = new VoiceResponse.Builder().enqueue(enqueue).build();
_115
_115
try {
_115
return twiml.toXml();
_115
} catch (TwiMLException e) {
_115
return "Error creating TwiML: " + e.getMessage();
_115
}
_115
}
_115
}

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



_10
{"instruction":"dequeue", "from": "<caller_number>", "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: