Receiving Twilio Webhooks Using DigitalOcean Functions
Time to read: 4 minutes
In this tutorial, we’ll explore how to receive Twilio webhooks using DigitalOcean Functions, enabling you to build powerful and flexible applications that interact with Twilio. Twilio webhooks provide a seamless way to receive real-time notifications from Twilio. By leveraging DigitalOcean Functions, a serverless computing platform, you can handle Twilio webhooks and perform custom actions based on the received data. For example, you can trigger a CI/CD workflow, such as Github Actions, whenever your Twilio number receives an SMS message.
Technical requirements
To follow along, you’ll need the following:
- A free Twilio account.
- A Python Development Environment running Python 3.9+. You need to have the virtualenv package running locally as well.
- A DigitalOcean account. You should also have doctl, which is DigitalOcean’s command line interface tool, installed and running locally. You can read more about setting it up here.
Creating a DO Function
To get started with creating a DO Function, you will be making use of the doctl
command line tool. However, you first need to install support for serverless functions. You can do that by running the following command:
This will install and download the serverless extension. Once that is completed, you are now ready to initialize a new function project using a helper command that the doctl
tool provides.
To work with DigitalOcean Functions via the command line using doctl
, you need to connect doctl
to a Functions namespace. Namespaces are used to isolate and organize functions and their settings. If this is your first time working with DO Functions, you’ll need to create a namespace before you can connect it and start deploying Functions. You can do this by running the following command:
The --label
flag is used to specify the name of the namespace while the --region
flag indicates which region the namespace should be in. You can learn more about creating namespaces here.
After doing that, you can now connect to the namespace by running the command below:
You can now create functions and deploy them to your namespace.
Next, from the directory where you want your project to reside, run the following to initialize a sample function project.
This will create a twilio project directory that contains a project.yml configuration file, a packages directory containing the sample package, a hello function directory, and the sample “Hello world” function code.
Here’s an outline of what the current directory structure looks like:
This is good for a start, however, you’ll need to rename some of the directories and files to align with the purpose of the function.
- Rename the
sample
package totwilio
- Rename the
hello
function directory towebhooks
- Rename the
hello.py
file to__main__.py
. This is in accordance with what DigitalOcean recommends where the file containing the handler function to be executed is named__main__.py
.You can read more about it here
Here’s an outline of what the new directory structure is supposed to look like:
Next, replace the project.yml
file at the root of the project’s directory with the following:
The packages and actions names are now consistent with the naming used for the directories. You’ve also added the environment variables the function needs to run. The environment variables will be fetched from a .env file you’ll be creating shortly using Templating.
Add the following code to the __main__.py file:
The first argument args
to the main()
function is typically an HTTP request event or web event that contains information about the request. The second parameter context
contains information about the function’s execution environment.
Within the main()
function, the request body is fetched from the args
dictionary using args.get(“http”).get(“body”)
. If the body
key is not found, it assigns an empty dictionary to the body
variable. If it is found, the returned value is a string. The parse_qs
function is then used to parse the body
into a dictionary.
To verify the request is authentic, you can use the RequestValidator
class included in the Twilio Helper library for Python. This class is initialized by passing in your Twilio Auth Token.
The validate()
method on the class is called passing in the webhook URL, which is obtained as an environment variable using os.getenv
, a dictionary with the request body, and the signature contained in the X-Twilio-Signature
header. If this method returns False
, the request is aborted with a status code of 400.
Deploying a DO Function
Functions with external dependencies require a build script and a requirements.txt file before they can be deployed. You can read more about why they are required here. Within the packages/twilio/webhooks directory, create a requirements.txt and build.sh file.
Note: Depending on the OS you’re currently running, you might need to give the right permissions to the build.sh file. On Mac/Linux, you can do that by running the command:
Add the twilio
library as a dependency to the requirements.txt file:
The build.sh script is used to create a virtualenv
and install the packages. Paste the following in the file:
Environment Variables
Before you can deploy the function to DigitalOcean, you need to configure your environment variables. Head over to your Twilio Console, and take note of your Auth Token.
Head back to the root of the project’s directory and create a .env file. Edit the file with the following credentials:
Replace the TWILIO_AUTH_TOKEN
with the actual value you noted from your Twilio Console.
For the TWILIO_WEBHOOK_URL
field, you can use a random string as the value there temporarily. You’ll be updating that field shortly after the function has been deployed.
Next, cd
out of the project directory and run the command below to deploy the function:
Once the function has been successfully deployed, you can now fetch the URL where the function was deployed by running the command below:
The command outputs the URL details:
You can now head back to the project’s directory, and update the TWILIO_WEBHOOK_URL
field in the .env file with the actual URL. Next, cd
out of the project and then redeploy the project by running the deploy
command:
Once you have deployed the function, you can get the function URL by running the following command:
You can now take the function URL and configure your Twilio account with it. You can learn more about doing that here.
Conclusion
In this tutorial, you’ve seen how to get started with DigitalOcean Functions and deploy a serverless function you can use for processing incoming webhooks from Twilio. You’ve also seen how convenient it is to deploy the function by running a command. This tutorial can serve as the foundation for building more complex serverless functions with DigitalOcean and Twilio.
Dotun is a backend software engineer who enjoys building awesome tools and products. He also enjoys technical writing in his spare time. Some of his favorite programming languages and frameworks include Go, PHP, Laravel, NestJS, and Node.
Website: https://dotunj.dev/
GitHub: https://github.com/Dotunj
Twitter: https://twitter.com/Dotunj_
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.