Outbound Voice Calls on AWS
Tags: aws, learning, javascript, tutorial
Published: 2024-01-29 09:28:40

## Background

I recently had a requirement to trigger an outbound voice call, and wanted to look at what options where available on AWS.

The background was linked to authenticating a customer in a regulated industry. A common approach here is adaptive authentication, where changes to factors such as location, device or some form of user behaviour leads to a step up in the level of authentication required. In this case, it was a need to support out of band authentication by making a voice call to provide a One Time Password (OTP).

From an AWS angle, the following services looked the most promising:

- Amazon Pinpoint
- Amazon Connect

## Amazon Pinpoint

Amazon Pinpoint is a service that was introduced to make it easy to run targeted campaigns across different channels: email, SMS, push notifications, in-app messaging, or custom channels.

At the end of 2018, a voice channel was introduced with several use cases identified, including "to send a One-Time Password (OTP) to your customer over the phone". You can read the original blog post [here](https://aws.amazon.com/blogs/messaging-and-targeting/introducing-the-amazon-pinpoint-voice-channel/).

Unfortunately, despite the documentation clearly identifying the United Kingdom as a region where you can lease a local phone number directly through the Pinpoint console, this proved not to be the case. It turns out this is true for SMS but not for Voice. What came as more of a surprise was that voice services are only supported in Asia Pacific (Mumbai), Asia Pacific (Sydney), Europe (Frankfurt), Europe (Ireland), US East (N. Virginia), and US West (Oregon) regions. This was despite there being clearly identified eu-west-2 endpoints for the SMS and Voice API v2. With a clear requirement to only utilise AWS services in the London region, this was not looking good.

In the end, after waiting over 5 days with an open ticket with AWS support, even with a friendly AWS SA chasing for me, I had to give up.

## Amazon Connect

Next up was Amazon Connect, especially given this [blog post](https://aws.amazon.com/blogs/contact-center/automating-outbound-calling-to-customers-using-amazon-connect/) which talks about making outbound calls to contact customers.

I decided to create a simple serverless application that exposes an API which takes in the number to call and OTP, and makes the outbound call.

![Amazon Connect Voice Call Architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lpex4tifef8jbvod9knv.png)

I started by creating a new Amazon Connect virtual contact centre instance, and configuring it to allow outgoing calls. Next I claimed a new Direct Inward Dialling (DID) phone number from the UK. These numbers present a local calling line identification when placing outbound calls, making it more likely to be accepted. They are threaded to a single carrier, and Amazon Connect doesn't offer carrier redundancy for DID numbers, though there is link redundancy across multiple Availability Zones.

I then created a new Queue specifically for these outbound calls. Note that you will need to make a note of the Queue ID which is the last part of the ARN after the `/queue/`.

![Amazon Connect Queue Configuration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/if773nyw6az8wgoz984u.png)

You set the outbound caller configuration as part of the Queue settings. This allows you to set the outbound caller ID number.

Finally, I created a new outbound contact flow:

![Amazon Connect Contact Flow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/93wrqvdf42lby4xejjpj.png)

The contact flow starts by setting the Queue to the one just created. It then plays the following prompt to the customer using Speech Synthetic Markup Language (SSML):

```
<speak>
Your One Time Passcode is 
<prosody rate='slow'>
<say-as interpret-as='digits'>$.Attributes.OTP</say-as></prosody>
</speak>
```

The assumption is the OTP is a series of numeric digits that are read out slowly one at a time. One of the advantages of using Amazon Connect, is that you can also add more functionality. In this case, I added a customer input flow block. This allows the customer to press 1 on the keypad (DTMF) to repeat the message.

The serverless API is built using the Serverless Application Model (SAM) and links together API Gateway and an AWS Lambda function.

The main code to invoke the `StartOutboundVoiceContactCommand` is shown below:

```
const params = {
  DestinationPhoneNumber: {numberToCall},
  ContactFlowId: {contactFlowID},
  InstanceId: {connectInstanceId},
  QueueId: {QueueId},
  Attributes: { // Attributes
    "OTP": {OTP},
  },
  TrafficType: "GENERAL",
};

try {
  const command = new StartOutboundVoiceContactCommand(params);
  await client.send(command);
} catch (err) {
  throw err;
} 
```
The full application can be deployed from the following GitHub repository - https://github.com/mlewis7127/connect-outbound-voice.

Once deployed, you can initiate an outbound call by passing in the destination phone number and the OTP. It turns out you need to create a support ticket to be able to call a `+447` UK mobile number, so I set up a local number on Skype for testing.

An example of the data passed in and returned is shown below:

![Postman Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1wb6pdluhdngt1yf0a6v.png)

Watch the following short video to see this demo in action:

{% embed https://youtu.be/CyIejdDxKsc %}