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

Creating Tasks and Accepting Reservations: Set up the Assignment Callback URL


The basic lifecycle of a [successful] TaskRouter Task is as follows:

Task Created → eligible Worker becomes available → Worker reserved → Reservation accepted → Task assigned to Worker.

In this part of the tutorial, we'll create Tasks and observe them through each of these stages. We start by creating a Task using the Tasks REST API. First time around we accept the Task using the Reservations REST API, then we create another Task and accept it using assignment callback instructions.

(information)

Info

Both the Reservations REST API and assignment callback instructions are valid methods for accepting a Reservation; it's likely that you'll choose one or the other based on the amount of background work that must be performed by your server before it accepts or rejects a Reservation. For example, due to the amount of time required, if you were to build a user interface that allowed human agents to inspect a Task before accepting it, you would need to accept the Reservation asynchronously using the Reservations REST API.


Set up the Assignment Callback URL

set-up-the-assignment-callback-url page anchor

Whether we accept Reservations via the REST API or via assignment callback instructions, we always need an Assignment Callback URL that is reachable by TaskRouter. This is the URL at which TaskRouter will notify us when a Worker is reserved to perform a Task. Before creating any Tasks, let's get the Assignment Callback URL up and running.

Finally time to write some (albeit minimalist!) code.

We are going to write a C# server to respond to HTTP requests, so we can tell Twilio what to do when we receive an assignment callback.

Program.cs

programcs page anchor

_35
using System;
_35
using System.Net;
_35
using SimpleWebServer;
_35
_35
namespace taskroutercsharp
_35
{
_35
class MainClass
_35
{
_35
public static void Main (string[] args)
_35
{
_35
WebServer ws = new WebServer (SendResponse, "http://localhost:8080/");
_35
ws.Run ();
_35
Console.WriteLine ("A simple webserver. Press a key to quit.");
_35
Console.ReadKey ();
_35
ws.Stop ();
_35
}
_35
_35
public static HttpListenerResponse SendResponse(HttpListenerContext ctx)
_35
{
_35
HttpListenerRequest request = ctx.Request;
_35
HttpListenerResponse response = ctx.Response;
_35
_35
String endpoint = request.RawUrl;
_35
_35
if (endpoint.EndsWith("assignment_callback")) {
_35
response.StatusCode = (int) HttpStatusCode.OK;
_35
response.ContentType = "application/json";
_35
response.StatusDescription = "{}";
_35
return response;
_35
}
_35
response.StatusCode = (int) HttpStatusCode.OK;
_35
return response;
_35
}
_35
}
_35
}


_78
using System;
_78
using System.Net;
_78
using System.Threading;
_78
using System.Linq;
_78
using System.Text;
_78
_78
namespace SimpleWebServer
_78
{
_78
public class WebServer
_78
{
_78
private readonly HttpListener _listener = new HttpListener();
_78
private readonly Func<HttpListenerContext, HttpListenerResponse> _responderMethod;
_78
_78
public WebServer(string[] prefixes, Func<HttpListenerContext, HttpListenerResponse> method)
_78
{
_78
if (!HttpListener.IsSupported)
_78
throw new NotSupportedException(
_78
"Needs Windows XP SP2, Server 2003 or later.");
_78
_78
// URI prefixes are required, for example
_78
// "http://localhost:8080/index/".
_78
if (prefixes == null || prefixes.Length == 0)
_78
throw new ArgumentException("prefixes");
_78
_78
// A responder method is required
_78
if (method == null)
_78
throw new ArgumentException("method");
_78
_78
foreach (string s in prefixes)
_78
_78
_listener.Prefixes.Add(s);
_78
_78
_responderMethod = method;
_78
_listener.Start();
_78
}
_78
_78
public WebServer(Func<HttpListenerContext, HttpListenerResponse> method, params string[] prefixes)
_78
: this(prefixes, method) { }
_78
_78
public void Run()
_78
{
_78
ThreadPool.QueueUserWorkItem((o) =>
_78
{
_78
Console.WriteLine("Webserver running...");
_78
try
_78
{
_78
while (_listener.IsListening)
_78
{
_78
ThreadPool.QueueUserWorkItem((c) =>
_78
{
_78
var ctx = c as HttpListenerContext;
_78
try
_78
{
_78
HttpListenerResponse response = _responderMethod(ctx);
_78
byte[] buf = Encoding.UTF8.GetBytes(response.StatusDescription);
_78
response.ContentLength64 = buf.Length;
_78
response.OutputStream.Write(buf, 0, buf.Length);
_78
}
_78
catch { } // suppress any exceptions
_78
finally
_78
{
_78
// always close the stream
_78
ctx.Response.OutputStream.Close();
_78
}
_78
}, _listener.GetContext());
_78
}
_78
}
_78
catch { } // suppress any exceptions
_78
});
_78
}
_78
_78
public void Stop()
_78
{
_78
_listener.Stop();
_78
_listener.Close();
_78
}
_78
}
_78
}

This returns an empty JSON document to TaskRouter with a 200 (OK) response code. This tells TaskRouter that the assignment callback was successfully received and parsed, but that we don't want to take any action on the Reservation right now. Instead, it's implied that we will use the REST API to accept or reject the Reservation when we are ready.

Make sure your C# server is running. Your server will be available here: http://localhost:8080.

For this tutorial, we'll use ngrok(link takes you to an external page). After installing ngrok to your $PATH, run the following command at your terminal to start listening for requests from the outside world:

ngrok 8080

  • Note: Follow the instructions on this Twilio blog post(link takes you to an external page) on exposing your C# web service to the outside world.

Your local C# server is now accessible to anyone (including Twilio's servers) at your ngrok URL.

With those things working, edit your "Incoming Customer Care Requests" Workflow to point at the newly implemented Assignment Callback URL:

http://yourngrokserver.com/assignment_callback

Excellent. We're ready to create Tasks and accept Reservations.

Next: Create a Task using the REST API »


Rate this page: