Dynamic blocklist with Twilio

For those moments where you wish you could dynamically block incoming calls within Twilio.. We all have them, right?

Desired end result

I have a file on my site that lists phone numbers. Any number in that list will be blocked from calling me.

You will need

  • A json file that contains an array of phone numbers
  • A Twilio number that receives calls from numbers you wish to block

First thing’s first, we’re going to pop over to a completely different site (I will write this up here if the source ever vanishes, ping me on the contact form if that’s the case)

Have a read of this article on Twilio’s help site. The section you’re after is under “Reject Calls from Specific Phone Numbers” if the anchor doesn’t work.

Come back here when you get to the “CODE” part.

That JSON file I mentioned

Simple enough, upload it somewhere public, it should look something like this (but with real numbers of course)

[
	"+441234567891",
	"+441234567893",
	"+441234567892"
]

Remember to not put the comma on that last number listed. JSON doesn’t like that.

Now for some code

Done the setup part? Sweet. Now in Twilio, under the Runtime -> Functions section go to Configure on the sidebar and under Dependencies add a new NPM module request.
Version shouldn’t be required but in case you’re after it, at the time of writing it’s 2.88.0.

Just to note: For me, the form input was hidden under the save button. Bit weird.. Click the version of the last one you can see and tab into it.

Once you hit the Save button it should pop up a message about saving, then deploying, then deployed.

Go back to the Manage -> Your function. Insert this code below, making three replacements

  • https://cohan.io/blocked-numbers.json: Replace with the URL to your blocked numbers file
  • https://ic4.io/twilio-voicemail: The URL to whatever was previously handling your inbound flow.

Personally I use a Twimlet to just dump everyone into voicemail.

exports.handler = function(context, event, callback) {

    var request = require('request');

    request(
        'https://cohan.io/blocked-numbers.json',
        function (error, response, body) {

        let twiml = new Twilio.twiml.VoiceResponse();
        let blocked = true;

        if (error) {
            twiml.redirect("https://ic4.io/twilio-voicemail");
        }
        else {
            let blocklist = JSON.parse(body);

            if (blocklist.length > 0) {
                if (blocklist.indexOf(event.From) === -1) {
                    blocked = false;
                }
            }
            if (blocked) {
                twiml.reject();
            }
            else {
                twiml.redirect("https://ic4.io/twilio-voicemail");
            }
            callback(null, twiml);
        }

    });

};

Running through this, when we receive a new inbound call we:

  • Make a request to fetch our blocklist
  • If that fails we’re going to assume we don’t have a blocklist, proceed as normal
  • If it succeeds we parse the JSON into blocklist
  • We then check if the number calling us right now against the list
  • If it is not listed, proceed as normal
  • If it is in the blocklist, reject the call

For curiosity purposes; When you reject a call, to the caller there’s an automated message that says the number is not in use then it instantly hangs up on them.

Make it so

To apply your newly created function to your phone number(s), check out the article Configuring Phone Numbers to Receive Voice Calls

Dun

That was easy enough… right? Ping me on the contact form if you need a hand :)