Selecting the "From" number to use for voice solutions within a single country is straightforward because there is typically just one phone number. However, many voice solutions need to make calls across the globe, and the optimal customer experience for these outgoing calls is to provide localized "From" numbers. For globalized voice solutions making outgoing calls, we recommend that customers implement a process for selecting FROM numbers based on the specific TO number for each call.
While you could certainly build a solution internally to select FROM numbers before making API calls to Twilio to initiate outgoing calls, this blog post outlines a solution that uses Twilio Functions to handle FROM number selection on-the-fly. This solution also uses Twilio Lookup to determine the country code for each TO number and also validate the TO number format before initiating the outgoing call.
FROM number selection is relevant to any solution that needs to initiate outgoing calls. This blog post will walk you through building a two factor authentication (2FA) solution that can receive API requests, select the best FROM number for a given TO number, then initiate Studio Flows to deliver 2FA codes via voice.
Outgoing voice call FROM number selection architecture
Let's take a quick look at the solution.
POSTcall to a Twilio Function starts things off
- The Twilio Function calls the Lookup API to validate the number formatting and get details on the phone number
- Based on the details returned from the Lookup API, the Function selects the best FROM number to use for the outgoing call
- The Function creates a Studio Flow "Execution" which makes the outgoing call and delivers the 2FA code
- A Twilio Account - Sign up for free today if you don’t yet have an account
- Twilio CLI - CLI Quickstart
- Twilio Serverless Plugin - Install
- Two Twilio Numbers with Voice capability - Purchase a number
Let’s Build It!
Initial Setup and Twilio Studio
- Purchase two Twilio Phone Numbers
- Clone this repo
- From the repo directory, rename sample.env to .env
- From the repo directory, enter
twilio serverless:deploy(you may need to run
twilio serverless:deploy command will build a service in your Twilio account and upload some assets. The output of the command will look like this:
Copy down the Domain and the full url for the Asset that ends with "/create-studio-flow.html". Both are marked with a red arrow in the image above.
Paste the url that ends with "/create-studio-flow.html" and was copied in the step above, into a web browser. That will bring up a simple single page app, or SPA, that will create a studio flow for you. The SPA will look like this:
- Enter a name for the
STUDIO_FLOW_FRIENDLY_NAME. For example, "Voice 2FA Demo Flow". Click the Update button to save the changes.
- Click on the Deploy Flow button to deploy the Studio Flow.
- Copy value in the
STUDIO_FLOWvariable once it populates.
When you clicked Update, you saved an environment variable to the Twilio Functions Service you just deployed. When you clicked on Deploy Flow, you called a Function that opened up a JSON file that contained the description of the Studio Flow, and then created the flow in your Twilio Account. All of these Functions and assets are in this repo for you to check out but they are secondary to the purpose of this blog post. The result is getting a Studio Flow deployed quickly to your account!
You can now go to your Twilio Console and go to Studio, and you will see a new flow titled "Voice 2FA Demo Flow" (or whatever you entered for that variable). You can click into that flow to see how you could build a Studio Flow to deliver a 2FA code via voice. In Studio, the flow looks like this:
Deliver codes with Twilio Functions
Now, let’s look at the Twilio Function that handles incoming requests to deliver voice 2FA codes. Again, the goal of this Twilio Function is to select the best FROM number and then kick off a Studio Flow Execution to deliver the code in a phone call. Here is a flow diagram:
- The POST request will contain the "TO" number to call, and the code.
- The Function will first pass the TO number to Twilio's Lookup API to validate that the number is formatted correctly and to return the country code for the number. (Line 132 of
- The function will then check if the country code matches a number from the pool (Line 73 of
initiate-outgoing-call.js), and then fallback to a regional number, and then ultimately a default number. (Line 112 of
- Lastly, the function will initiate the Studio Flow Execution with the selected FROM number. (Line 157 of
Once you’re done with this demonstration, Twilio has a terrific service called Verify, which handles delivering user verification on voice as well as many other channels. If you need to implement or upgrade your 2FA solution – or you’re eventually taking this code to production – check out Verify!
Let's update the
.env file with a default phone number and the url pointing to the
STUDIO_FLOW we created above.
From your favorite text editor, open the
.env file and enter one of your two phone numbers as the
DEFAULT_FROM_NUMBER. Next enter the value for
STUDIO_FLOW that you generated when your deployed the flow (you already created this environment variable, but adding it to your
.env file will keep it from being overwritten when you deploy changes). Save the file.
twilio serverless:deploy again to deploy the changes. This time we only made changes to the
.env file, but this is the same process to push changes to your functions and other assets to your Twilio Service.
With those changes in place, you can now try it out...
Let’s try it out!
Edit this curl command:
curl -L -X POST 'http://YOUR-TWILIO-DOMAIN/initiate-outgoing-call' \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'to=YOUR-E.164-PHONE-NUMBER' \ --data-urlencode 'message=Hello, this is a demonstration verification service!' \ --data-urlencode 'code=513567'
YOUR-TWILIO-DOMAINwith the Domain your noted when deploying the service
YOUR-E.164-PHONE-NUMBERwith your phone number (in E.164 format)
- Run the command!
If everything is set up correctly, you should get a phone call from your default phone number to deliver to the code you passed in.
Great, how is the FROM number specified?
The function titled
initiate-outgoing-call.js has a helper function called
getFromNumber(). This helper function will serve as your pool of numbers. The pool of numbers is divided into two objects:
countryNumberPool=> key is the country code, value is the number to use for that country
regionalNumberPool=> key is the first two chars of the to number (
+3, ...), value is the number to use for that region.
To manage your pool of numbers, you will need to maintain the properties in those two objects. FROM number selection will first try to match for the country code, then fallback to a regional number, then finally your default phone number.
You can manage this code in your source code repository, and use twilio
serverless:deploy to update your service whenever you add or edit numbers.
Let’s try it again! (With geo-aware numbers)
The first time we ran the curl command, we only had the default number set so the FROM number selection fell back all the way to that number.
Now, let's use our second phone number... uncomment line 65 of
initiate-outgoing-call.js, and enter the two letter country code for the TO number you are using (in my case it was
US since I am in the United States). Enter the second phone number you provisioned for the value. Run
twilio serverless:deploy to update your Twilio Service with the changes.
Now, run the same curl command as before, but note that the FROM number should be the one assigned to your country code!
Hardening for production
The code in this blog is not ready for production use! For starters, you would need to secure the Twilio endpoints. Here are some ways you could do that: Basic Auth, JWT.
Additionally, if you’re adding a two factor authentication solution in production you should use Twilio Verify.
This demonstration works for countries and regions. You could certainly get more granular by parsing the TO number beyond the first two characters (area codes) to localize FROM number selection even further.
Excellent! You have deployed a Twilio Serverless solution that validates TO numbers using Twilio Lookup, handles FROM number selection, and can initiate outgoing voice calls using Twilio Studio!
This example uses 2F as the use case for the outgoing calls but it could be applied to any use case that needs to place outgoing calls. If you have a true 2FA use case, be sure to check out Twilio Verify as it handles things like FROM number selection automatically plus allows for 2FA over other channels like SMS, Email, Push, and more.
Lastly, Twilio Functions are really powerful and are a terrific way to extend and customize your resources deployed on the Twilio platform.
Dan Bartlett has been building web applications since the first dotcom wave. The core principles from those days remain the same but these days you can build cooler things faster. He can be reached at dbartlett [at] twilio.com.