How to Send an SMS or WhatsApp Message with Twilio Functions and TypeScript

July 12, 2023
Written by
Felistas Ngumi
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by

A serverless function is a single purpose, independent function deployed in a managed cloud infrastructure. By the sole fact that it lives in a managed infrastructure, the responsibility of ensuring your function is secure, always available and scale as needed, is offloaded from you and is handled by the infrastructure company, at a reduced cost! Twilio, provides this serverless  environment, which enables developers to quickly develop and deploy Twilio specific functions.

Setting up a Twilio Function to send SMS and WhatsApp messages with TypeScript offers developers a convenient way to leverage Twilio's powerful messaging and infrastructure capabilities. With TypeScript, a statically typed superset of JavaScript, you can benefit from enhanced code organization, type checking, and editor support, leading to more robust and maintainable code. Whether you're building a notification system, customer support feature, or any application that requires programmatically sending messages, this step-by-step guide will walk you through the process of creating a Twilio Function that integrates seamlessly with Twilio's SMS and WhatsApp APIs. By the end of this tutorial, you'll have a functional solution that can be easily extended and customized to suit your specific messaging needs. So, let's dive in and unlock the full potential of Twilio's serverless environment in combination with TypeScript!

Prerequisites

Getting Started

In your preferred terminal, run the following commands to install twilio-cli and typescript globally.

npm install -g typescript
npm install -g twilio-cli

A clean installation of the twilio-cli doesn’t ship with the serverless plugin, which we will need in order to build our functions. To add this plugin, run the following command:

twilio plugins:install @twilio-labs/plugin-serverless

Next, navigate to the Twilio Console to create and verify your account on Twilio. When creating the account, state the Twilio project you would like to use, in this case select Messaging and select Javascript as the preferred programming language. In the resulting dashboard, take a note of the ACCOUNT SID and AUTH TOKEN.

Log in to your Twilio account in your terminal for Twilio CLI to authenticate to Twilio by running the following command and export the ACCOUNT SID and AUTH TOKEN:

twilio login

You’ll can export the following in environment variables your terminal with the following command:

export TWILIO_ACCOUNT_SID=<your_account_sid>
export TWILIO_AUTH_TOKEN=<your_auth_token>

If you are on windows, run:

set  TWILIO_ACCOUNT_SID=<your_account_sid>
set TWILIO_AUTH_TOKEN=<your_auth_token>

Activate Twilio Sandbox For WhatsApp

In the Twilio console, head over to the All Products & Services tab to the left and select Programmable Messaging. Next, click on Try it Out then Try WhatsApp to activate the sandbox as shown below:

WhatsApp Sandbox menu on Twilio Console
 

Send the code displayed on your console (join ****), as a WhatsApp message from your personal mobile number to the WhatsApp sandbox number indicated in the page. After a successful activation, you should receive a confirmation message stating you are connected to the sandbox and are all set to receive and send messages.

Building Our Functions

Now that we have the base setup done, navigate back to your terminal and run the following command to create our serverless project.

twilio serverless:init demo --typescript

This command bootstraps a Typescript project with the following directory structure.

screenshot of the project directory

The src/assets directory stores all our project assets and all functions are defined in  the src/functions directory by default. You can, however, specify a different folder for the assets and functions while creating the project by using the  --assets-folder and --functions-folder CLI flags respectively.

The tsconfig.json file defines the compiler options needed by typescript when building our project. These options include:

  • module - sets the module system for the project. This can be AMD, CommonJS, System, UMD etc.
  • target- Specifies the ECMAScript version for the project.
  • outDir- Where the transpiled JS files will be emitted to. For our case, edit this configuration to “dist/functions”
  • strict- enables strict type checking of the JS files.
  • sourceMap- generates a corresponding source map file for all the transpiled JS files.
  • skipLibCheck- skip the typechecking of declaration files. These files normally have the *.d.ts extension.

To learn more about the configuration options above, you can have a look here

For the scope of this project, feel free to delete the assets folder and all the files defined inside the functions directory as we will not be needing them.

Next, create a file called whatsapp.ts in the src/functions folder and add the following lines of code.

import {
 Context,
 ServerlessCallback,
 ServerlessFunctionSignature,
} from '@twilio-labs/serverless-runtime-types/types';

export const handler: ServerlessFunctionSignature = function (
 context: Context,
 event,
 callback: ServerlessCallback,
) {
 const client = context.getTwilioClient();
 try {
   client.messages
     .create({
       from: 'whatsapp:<your_whatsapp_sandbox_number>',
       body: 'Hi, there!',
       to: 'whatsapp:<your_phone_number>',
     });
   return callback(null);
 } catch (e: any) {
   return callback(e);
 }
};

The above code uses the Twilio client to send a WhatsApp message to the specified number. The handler function is an interface between Twilio Functions and your application logic. It accepts three main arguments which are:

  • context - This is an object that provides access to environment variables and helper methods that can be accessed at execution time. In our case, we are using the context object to get access to the TwilioClient to enable us to send a WhatsApp message.
  • event - This contains the request parameters passed to our function.
  • callback - Completes the execution of our handler function and emits the response passed to it.

Ensure to replace the<your_phone_number> and <your_whatsapp_sandbox_number> placeholders with the respective values.

Since we will be using Twilio functions to send an SMS too, next, create another file called sms.ts inside the functions folder and add the following lines of code:

import {
 Context,
 ServerlessCallback,
 ServerlessFunctionSignature,
} from '@twilio-labs/serverless-runtime-types/types';

export const handler: ServerlessFunctionSignature = function (
 context: Context,
 event,
 callback: ServerlessCallback,
) {
 const client = context.getTwilioClient();
 try {
   client.messages
     .create({
       from: '<your_twilio_phone_number>',
       body: 'Hi, there!',
       to: '<your_phone_number>',
     });
   return callback(null);
 } catch (e: any) {
   return callback(e);
 }
};

Ensure to replace the <your_twilio_phone_number> and <your_phone_number> placeholders with their respective values.

Testing Our Functions

To start the application locally, navigate to the demo directory and run the following command:

npm start

You should see a similar output like below.

terminal output after starting application locally

To test the functions, open the links in your browser and you should expect an sms and     WhatsApp message to be sent to your personal phone number.

Deploying Our Functions

Now that we have verified the functions work as expected, the next step would be to deploy our functions. In your terminal, press control + C to stop the existing process and then run the command below to deploy your Functions:

npm run deploy

You should see a similar screen like the one below. Test your deployed functions by running their respective URLs displayed in the terminal.

Terminal output after deploying functions

Conclusion

Congratulations on reaching this far! You can learn more about Twilio functions here and I can’t wait to see what you build!

Felistas is a Software Engineer who enjoys writing technical articles from time to time and loves solving problems through code.