A few weeks ago I was talking an acquaintance from Uppsala’s 46elks about documenting their telephony API for .NET developers. They sent some helpful examples and within an hour I had built my own API client and was sending messages (See: ApiClient.cs)

At this point I received a call from the north pole:

This year, Santa wants to take your gift requests via SMS.

Not wanting to let Santa down, I got down to building and am now proud to present Santa’s SMS service:

Simply send your wish to +46 76 686 1249 and Santa will confirm your request!*

* Only from publicly listed Swedish mobile numbers

Implementation

Test account

The 46elks signup is super easy and only requires a confirmation via SMS. 46elks gives you a 20kr (~2 euro) starting credit. This is enough to rent a phone number for a month (9kr) and send around 30 messages.

Set up a number

When you reserve a 46elks number, you can specify a HTTP callback to receive all messages on. If you reply with a 200 OK status, the response body will be sent right back to the sender!

46elks dashboard screenshot

Handling messages

Building .NET APIs used to be fairly painful (WCF) but modern Microsoft options are much better. I decided to try a popular non-Microsoft microframework: Nancy

Set up is pretty effortless:

  • Create a Console Application
  • Add Nancy package from NuGet
  • Add Nancy.Hosting.Self package from NuGet
  • Add the following to your Main method:
static void Main(string[] args) {

    var config = new HostConfiguration() {UrlReservations = new UrlReservations {CreateAutomatically = true}};
    var address = new Uri("http://localhost:8080")
    Host = new NancyHost(config, address);
    Host.Start();

    Console.WriteLine("Nancy is started and listening on {0}...", address);

    for (var line = Console.ReadLine (); line != "quit";);
    Host.Stop();
}

To set up handlers and routing, you simply inherit from NancyModule and register your routes in the constructor:

public class SMSModule : NancyModule
{
    public SMSModule()
    {
        Post["/sms/echo"] = parameters =>
        {
            var sm = this.Bind<ShortMessage>();
            return sm.Message;
        };
        Post["/sms/gift", true] = async (ctx, token) =>
        {
            var sm = this.Bind<ShortMessage>();
            return await Santa.Reply(sm);
        };
    }
}

Note how the echo endpoint has a regular handler, while Santa runs in an async handler (he’s a little slow at his age).

this.Bind automatically maps incoming postdata to the provided model type, in this case ShortMessage:

public class ShortMessage
{
    // note: matched case-insensitively to incoming postdata/json/xml parameters
    public string From { get; set; }
    public string To { get; set; }
    public string Message { get; set; }
}

Santa knows all

A helpful (but creepy) discovery was that many Swedish mobile numbers can be reverse-searched using eg. Truecaller. This allows Santa to reply to you by name and even confirm he’s coming to your town!

Understandably, TrueCaller’s API is invitation-only so I resorted to scraping 118100.se instead. See the full implementation of Santa and the scraper for the gory details.

Testing and Deployment

Testing your handler is much easier if you don’t have to deploy it every time. Ngrok connects your local server via an SSH tunnel to a generated public URL:

Ngrok screenshot

Deploying the final handler is probably easiest via one of the integrated Nancy to Azure options, but I decided to try running it on Mono in a docker container

Conclusion

Building SMS integrations with an API like 46elks is feels reliable and low-effort, especially if you’re already running a web app or service. Although you might be tempted to store interactions in your database, 46elk’s own dashboard is pretty complete to start with.

As a .NET developer, my wishlist for the 46 elks API would be pretty short:

  • A NuGet package to get a faster proof-of-concept and guidance on API usage.
  • Alternatively, copy-and-pastable samples, maybe shortened by using something like RestSharp