Enabling VoIP calls on Twilio Flex

March 14, 2023
Written by
Leroy Chan
Twilion
Reviewed by
Paul Kamp
Twilion
Aymen Naim
Twilion

image (4)

As businesses increasingly move towards remote work and virtual collaboration, the ability to make high-quality voice and video calls over the internet is more important than ever. Twilio Flex, a cloud-based contact center platform, offers an intuitive and flexible solution for managing customer interactions across multiple channels, including voice.

Introduction

Voice over Internet Protocol (VoIP) calls are a type of voice communication that takes place over the internet, bypassing the traditional Public Switched Telephone Network (PSTN). VoIP calls on Twilio are powered by Programmable Voice, which enables developers to build customized voice experiences using Twilio's cloud-based platform. With Programmable Voice, VoIP calls can be integrated into a variety of applications, including native mobile apps and websites, using Twilio's Programmable Voice SDKs.

In this comprehensive guide, we'll walk you through the process of enabling VoIP calls on Twilio Flex, empowering your business to deliver seamless customer experiences through the power of the internet.

Instructions and sample code provided in this guide are meant for Flex deployments that are running on Flex UI 2.x. 

Solution overview: inbound and outbound VoIP calls in Flex

The solution consist of the following key call flows:

  1. Inbound VoIP Calls to Twilio Flex (aka "Client-to-Flex")
  2. Outbound VoIP Calls to Client (aka "Flex-to-Client")

Twilio Flex - VoIP - Solution Flow

Inbound VoIP Calls to Twilio Flex (aka "Client-to-Flex")

To receive VoIP calls in Twilio Flex, there are several necessary components:

  1. Custom App: A custom end-user app (either a web or native mobile app) with a soft phone embedded that allows end-users to make and receive VoIP calls
  2. TwilML App: A serverless app responsible for directing all outgoing VoIP calls from a custom app to a Twilio Studio Flow
  3. Twilio Studio Flow: A flow to route outbound VoIP calls from the custom app into Twilio Flex. IVRs can also be configured in the Studio flow before hitting Twilio Flex.
  4. Twilio Flex: A Programmable Contact Center that enable agents to receive VoIP calls

In order to enable end users to make and receive VoIP calls, a custom frontend application must be embedded with a softphone. Fortunately, Twilio's Twilio's Programmable Voice SDKs makes this process straightforward.

To get started, generate an Access Token for each end user who needs to use the softphone. This token will also include a Voice Grant that specifies the outgoingApplicationSID, which indicates the TwiML App responsible for directing outgoing voice traffic from the custom frontend app. Once the Access Token has been generated, the softphone on the custom frontend app can be initialized using the Device object from the SDK. This will enable end users to start making and receiving VoIP calls seamlessly.

When a call is initiated from the custom app, the configured TwiML app will invoke a Studio Flow to process any Interactive Voice Response (IVR) configurations before routing the call to Twilio Flex via the "Send to Flex" widget.

For contact center agents on Twilio Flex to receive and handle VoIP calls, a Flex plugin is required to populate the from field of the incoming Task's conferenceOptions. This step is essential to ensure that all incoming VoIP tasks have the necessary attributes.

async init(flex, manager) {
    // Add a "from" field to allow accepting tasks on Flex UI
    flex.Actions.replaceAction("AcceptTask", (payload, original) => {
      if (
        !payload.conferenceOptions.from &&
        payload.task._task.attributes.caller &&
        payload.task._task.attributes.caller.startsWith("client:")
      ) {
        payload.conferenceOptions.from = payload.task._task.attributes.caller;
        console.log(
          `VoIP Plugin: Set conferenceOptions.from to ${payload.task._task.attributes.caller}`
        );
      }
      return original(payload);
    });
  }

With the Flex plugin deployed, contact center agents on Twilio Flex will now be able to receive and handle VoIP calls successfully.

Outbound VoIP Calls to Client (aka "Flex-to-Client")

Agents on Twilio Flex can use the native dialpad to make outbound PSTN and SIP calls. However, to add the ability to make outbound VoIP calls, the configuration settings in Flex must be updated by setting enableClientCalling to true.

This can be achieved by using a Flex plugin that does the following:

async init(flex, manager) {
    // Update Flex Config to Enable "client:" to allowing calling to other "clients"
    flex.Manager.getInstance().updateConfig({ enableClientCalling: true });
}

In addition, it's important to populate the outbound VoIP's Caller ID with the Twilio Flex agent identifier. This ensures that outgoing calls are properly identified.

async init(flex, manager) {
    // Update Flex Config to Enable "client:" to allowing calling to other "clients"
    flex.Manager.getInstance().updateConfig({ enableClientCalling: true });

    // Set Caller ID
    flex.Actions.replaceAction("StartOutboundCall", (payload, original) => {
      if (payload.destination.startsWith("client:")) {
        manager.user.identity
          ? (payload.callerId = `client:${manager.user.identity}`)
          : (payload.callerId = `client:voip`);
      }
      original(payload);
    });
}

The resulting Flex VoIP plugin that enables both inbound and outbound VoIP calls on Flex is:

async init(flex, manager) {
    // Update Flex Config to Enable "client:" to allowing calling to other "clients"
    flex.Manager.getInstance().updateConfig({ enableClientCalling: true });

    // Set Caller ID
    flex.Actions.replaceAction("StartOutboundCall", (payload, original) => {
      if (payload.destination.startsWith("client:")) {
        manager.user.identity
          ? (payload.callerId = `client:${manager.user.identity}`)
          : (payload.callerId = `client:voip`);
      }
      original(payload);
    });

    // Add a "from" field to allow accepting tasks on Flex UI
    flex.Actions.replaceAction("AcceptTask", (payload, original) => {
      if (
        !payload.conferenceOptions.from &&
        payload.task._task.attributes.caller &&
        payload.task._task.attributes.caller.startsWith("client:")
      ) {
        payload.conferenceOptions.from = payload.task._task.attributes.caller;
        console.log(
          `VoIP Plugin: Set conferenceOptions.from to ${payload.task._task.attributes.caller}`
        );
      }
      return original(payload);
    });
  }

Step by step guide

This section will guide you to set up and configure VoIP calls on Twilio Flex using a web-based demo frontend.

Prerequisites

Before you can start building the solution, you'll need to set up a few accounts (and download a few tools).

  1. Twilio Flex Account (Guide) with Flex UI 2.x
  2. Native Flex Dialpad enabled on Twilio Flex Account (Guide)
  3. Node.js v16.x.x (Guide)
  4. Twilio CLI v5.4.1 or above (Guide)
  5. Twilio CLI Flex Plugin v6.0.4 or above (Guide)
  6. Twilio CLI Serverless Plugin v3.1.3 or above (Guide)

Getting Started

The solution consists of two main components:

  1. Twilio Flex Plugin (plugin-voip): Twilio Flex plugin that allows agents to accept incoming VoIP calls and perform outbound VoIP calls to "client:" via the native Flex Dialpad
  2. Web Frontend (frontend-voip-to-flex-demo): Sample web interface that provides the ability to make and receive VoIP calls via Flex. Fully hosted on Twilio Functions.

Step 1: Create a Twilio API Key and Secret

  1. Login to Twilio Console and copy down your Account SID.
  2. Next, on the top right, select Account followed by API keys & tokens. Click on Create API key.
  3. Enter Flex - VoIP for the Friendly name and leave everything as default.

API_Key_Secret

Take note of your Account SID (ACxxx), API Key SID (SKxxxx) and the secret - you will need it later in Step 4.

Step 2: Create a Studio Workflow

  1. Within Twilio Console and under Studio, create a new Studio Flow.
  2. Still within the Studio Flow, drag-and-drop the Send to Flex widget and configure the Workflow and Task Channel accordingly. For Task Channel, please choose Voice.
  3. Once created, connect the Incoming Call trigger to the Send to Flex widget and click Publish.

The Studio Flow should be configured similar to the screenshot below:

Studio flow with the Send to Flex widget

Take note of the Studio Flow SID which starts with FWxxxxxxx. You will need it for the next Step 3.

Step 3: Create a TwilML app

  1. Within Twilio Console and under Voice, select TwiML Apps which is under the Manage section.
  2. Click on Create new TwiML App.

Fill up the following:

  1. Friendly name: Flex - VoIP Channel
  2. Under Voice Configuration - Request URL: https://webhooks.twilio.com/v1/Accounts/{{ACCOUNT_SID}}/Flows/{{FWxxxxxx}}. Replace {{ACCOUNT_SID}} with your Flex Account SID (from Step 1) and {{FWxxxx}} with Studio Flow SID (from Step 2)

Leave of the fields rest empty/default.

TwilML_App

Take note of the TwiML App SID which starts with APxxxxx. You will need it for Step 4

Step 4: Deploy Sample Web Interface for VoIP-to-Flex Demo

To configure the .env file, ensure that you have obtained the following values before proceeding:

  1. Twilio API Key (SKxxxxxx) - from Step 1
  2. Twilio API Secret - from Step 1
  3. TwiML App SID (APxxxxx) - from Step 3

In your terminal, run the following commands:

// Clone Project
git clone https://github.com/leroychan/twilio-flex-voip.git

// Change to working directory
cd twilio-flex-voip

// Change to frontend-voip-to-flex-demo directory
cd frontend-voip-to-flex-demo

// Install NPM Packages
npm install

// Copy sample enviroment file
cp .env.example .env

Configure the .env file using your preferred code editor with all the required values. You can leave ACCOUNT_SID=xxx empty, as it will be populated by default during run time.

Before you deploy, ensure that twilio profiles:list has an active account set.

Once configured and ready to deploy it, go back to your terminal and issue the following command:

twilio serverless:deploy

Once successfully deployed, visit the hosted index.html page to view your sample web interface to call or receive VoIP calls

The VoIP to Flex UI URL highlighted in the console

Step 5: Deploy the Twilio Flex VoIP Plugin

On your terminal, perform the following:

// Clone Project
git clone https://github.com/leroychan/twilio-flex-voip.git

// Change to working directory
cd twilio-flex-voip

// Change to plugin-voip directory
cd plugin-voip

// Install NPM Packages
npm install

// Local Development
twilio flex:plugins:start

// Deploy to Twilio Flex Instance
// Before you deploy, ensure that `twilio profiles:list` has an active Flex account set.
twilio flex:plugins:deploy --changelog "Deploy VoIP Plugin"

twilio flex:plugins:release --plugin plugin-voip@0.0.1 --name "Deploy VoIP Plugin" --description "Allows agents to accept incoming VoIP calls and perform outbound VoIP calls"

Step 6: Done!

Congratulations, you can now make or receive VoIP calls in Flex! The full source code used in this guide can be found over here.

Flex_VoIP

You are now ready to start testing the VoIP channel integration.

Demo inbound VoIP call into Flex

  1. Login to your Flex agent interface and set yourself to be of an Available status
  2. On your browser, open the hosted web interface URL (from Step 4)
  3. Click on the Step 1: Start up the Device button. You should be seeing Twilio.Device Ready to make and receive calls! under the Event log
  4. Click on Step 2: Call to Flex
  5. You should be seeing the call coming into Flex !

Demo outbound VoIP call to client

  1. On your Flex agent interface, click on the dialpad button
  2. In the phone number field, input client:<<CLIENT_NAME>> and click call. <<CLIENT_NAME>> can be obtained under Your Device Info in your sample web interface.
  3. The call should now be coming into your sample web interface

After successfully enabling inbound and outbound VoIP in Flex, you can include additional channels in Flex by referring to other blog posts that provide guidance on integrating Discord and Telegram.

Leroy is a seasoned solution architect with a knack for designing scalable architectures on the cloud. He is currently part of the Flex Solution Engineering team for APJ, focusing on driving joint Go-to-Market motions with partners. Leroy can be reached at lechan [at] twilio.com.