Voice (Phone) Campaign


Note: You will need to complete the first part of the campaign tutorial (creating your customer data table) before starting this.

Create Your Bot

Now that we have a source of customer data to work with, we can start building the bot. Go back to your Bot Designer homepage and click the + button to create a new bot. Be sure to select “Add a blank bot”, since we are starting from scratch.

Screen Shot 2018-05-02 at 12.34.23 PM

Give the bot a name, and, optionally, a description and an image URL, then click Save.

Screen Shot 2018-05-15 at 13.56.53.png

Create Gateway Flow

Our first flow will be triggered via HTTP. The content of the call to be made will be included in the API call to trigger the flow. The flow will query our Sample CRM table to get a list of eligible customers, then it will loop through that list and trigger the subflow for each customer, sending over their contact info and the content of the message.

In your new bot, click the + button and select “Add a blank flow.”

Screen Shot 2018-05-10 at 15.51.56

Name your flow “HTTP Gateway”, add a description, and hit Save.

Screen Shot 2018-05-10 at 15.53.54.png

Download Steps

Before we can start building, we need to download the necessary step templates. In the sidebar, navigate to the Templates tab and click “Browse our templates in the Library” at the bottom to open up the Library download window.

Screen Shot 2018-05-10 at 15.56.03.png

Screen Shot 2018-05-10 at 15.59.06.png

You can scroll through and collapse the categories or use the search bar to find specific steps. Click “Download” to add the step to your flow. For this flow, we’ll need the following steps:

  • Check Condition

 Screen Shot 2018-05-10 at 16.00.23

  • Create Data

Screen Shot 2018-05-10 at 16.01.20

  • Custom Data

Screen Shot 2018-05-10 at 16.02.21

  • Go to a Step in Current Flow

Screen Shot 2018-05-10 at 16.03.02.png

  • Send Response (HTTP)

Screen Shot 2018-05-10 at 16.05.59

  • Wait for Request (HTTP)

Screen Shot 2018-05-10 at 16.07.13

  • Trigger a Flow and Proceed

Screen Shot 2018-05-10 at 16.08.14

Once you’ve downloaded all of the above step templates, you can close the Library window. Now the Templates list in the sidebar is populated.

Go ahead and save your flow, and remember to do this periodically as you work.

Configure HTTP Gateway

As with every flow, the first step must be a gateway. In this case, our gateway step is Wait for Request (HTTP), which means the flow will be triggered via incoming HTTP request, a.k.a. API call. Drag this step onto the Start node.

Screen Shot 2018-05-10 at 16.12.56.png

The Path is required, as that’s what will differentiate this flow from other HTTP-triggered flows in your Studio account. Let’s set the path to “bulkCall”.

Screen Shot 2018-05-15 at 13.59.02

Next, open up the Advanced dropdown. We’ll use the Request Example field here to create appropriate merge fields for the incoming request data. In Request Example, replace the default “null” value with the following JSON:

 "request": {
 "body": {
 "Message": "Content of bulk voice call."

Now, when we use the merge field suggestion list later in the flow, we will be presented with the option for {httpRequest.request.body.Message} instead of just {httpRequest}.

Query CRM

The next thing this flow will do is retrieve a list of customers eligible to be contacted from the CRM table we set up. We will use the Custom Data step to do this, and will only retrieve customers that opted-in to marketing messages and haven’t been contacted yet.

Add Custom Data to the next empty node on the canvas.

Screen Shot 2018-05-10 at 16.22.11.png

From the dropdown, select “Sample CRM” and the step UI will update accordingly.

Screen Shot 2018-05-10 at 16.23.34.png

Scroll down to the Operation section, where we’ll set our query parameters. The default operation is “Find one or more records”, which is exactly what we need. Click “Create filters” to add rules.

Screen Shot 2018-05-10 at 16.26.08.png

If you are familiar with MongoDB, you can write your own custom query. Otherwise, use the UI here to create filtering rules.

Click “+ Add Rule”. Our first rule will check if MarketingEnabled is true, so select MarketingEnabled from the Field dropdown and “true” from the Value dropdown on the far right. The operator “equals” can remain the same.

Screen Shot 2018-05-10 at 16.29.16.png

Click “+ Add Rule” again, and create a rule that checks if Status is equal to “new”.

Screen Shot 2018-05-10 at 16.30.56.png

Finally, make sure the switch at the top is set to “Match All“, since we want both of these rules to apply.

Screen Shot 2018-05-12 at 15.25.30

Close this window and the Custom Data step UI will now show the new rules.

Screen Shot 2018-05-12 at 15.26.40

We aren’t trying to limit the number of records we get back, so leave Limit at 0.

Notice how Custom Data automatically created three exit branches. The right two branches allow us to handle any potential failures when querying the data table. Under each of these branches, we’ll add a Send Response (HTTP) step and send back an error message. This means that whoever triggers this flow will be able to see what went wrong.

Under the “fail” branch, place Send Response (HTTP) and select “500 Internal Server Error” from the dropdown. For the response body, paste the following JSON:

 "error":"CRM lookup failure."

Screen Shot 2018-05-10 at 16.36.06

Under the “no records” branch, use Send Response (HTTP) again, but choose “404 Not Found” and set the following as the response body:

 "error":"Could not find any customers opted-into marketing who have not already been contacted."

Screen Shot 2018-05-10 at 16.40.06

Don’t forget to save your flow!

Loop through List of Records

If the Custom Data step successfully retrieves one or more customer records matching the criteria, it will exit via the “next” branch and we will need to iterate through the list of records. We will do this by creating a simple loop architecture making use of Create DataCheck Condition, and Go to a Step in Current Flow.

Under the “next” branch, place a Create Data step.

Screen Shot 2018-05-10 at 16.43.21

Give this step the name “set counter” and optionally add a description. In the Variables list, create a variable “counter” with value 0 and type “number”.

Screen Shot 2018-05-10 at 16.45.39

Add a Check Condition step below “set counter” and name it “Loop condition.” This step will check whether the logic inside the loop should execute by comparing the value of the counter (which will increment each time the loop iterates) with the length of the list of customer records.

Screen Shot 2018-05-10 at 16.49.38

Click the pencil icon to the right of the “next” condition to edit it.

Screen Shot 2018-05-10 at 16.51.05.png

Give the condition the description “counter is less than record.Items.length”, then mouse over the rule and click the < > button on the right side to switch to code mode. This will allow us to make a numeric comparison.

Screen Shot 2018-05-10 at 16.52.06.png

Screen Shot 2018-05-10 at 16.53.24

In the code box, paste the following:

this.get('createData.counter') < this.get('record.Items').length

This will check whether the value of the {counter} merge field we created is less than the length of the list of customer records. If so, it means we still have more records to handle, and the loop must continue.

Screen Shot 2018-05-10 at 16.55.41.png

Ignore the error message beneath the rule and click Save.

Now we will add the logic that will take place each time the loop executes. In this case, we will simply trigger a subflow before incrementing the counter and jumping back to the loop condition.

Under the “next” branch, add a Create Data step, labeling it “set currentRecord”. Create a variable currentRecord, switch the Value field to code mode, and paste the following:


This will set the value of {currentRecord} to the next customer record in the list.

Screen Shot 2018-05-10 at 17.00.24

Change the merge field here from {createData} to {setRecord}, to differentiate it from the other Create Data step.

Screen Shot 2018-05-12 at 16.40.46.png

Next, we will trigger the Voice subflow, sending over the individual customer data. Add a Trigger a Flow and Proceed step beneath “set currentRecord”. We can’t configure this step yet, since we don’t yet have any active subflows in the bot. For now, just give this step a label before moving on.

Screen Shot 2018-05-15 at 14.01.38

After triggering the subflow we must increment the counter, adding 1 to its current value to represent another iteration through the loop. Use Create Data again, labeling the step “increment counter”. Set Variable to “counter”, switch Value to code mode, and paste the following:

this.get('createData.counter') + 1

Screen Shot 2018-05-10 at 17.09.35.png

Now we can jump back to the loop condition, where the new value of {counter} will be compared to the length of the records list. Drag the Go to step onto the empty node beneath “increment counter” and select “Loop condition” from the dropdown.

Screen Shot 2018-05-10 at 17.11.32.png

Save your flow, then pat yourself on the back! You just created a loop.

Send Success Response

Once the loop completes, we need to send back a 200 OK response, letting whoever triggered the flow know that the flow executed successfully.

Under the “else” branch of “Loop condition”, add Send Response (HTTP). Leave the status code as 200 OK, and paste the following in Response body:

 "response":`Triggered Voice flow ${this.get('createData.counter')} times.`

Screen Shot 2018-05-15 at 14.02.43.png

That’s it for the gateway flow! Now we’ll move onto the subflow. Make sure you save your recent changes!

Create Voice Subflow

Each time the loop in our HTTP Gateway flow executes, it will trigger a subflow to make the phone call. This subflow will need to know several key pieces of information in order to do its job: the phone number of the recipient, the first name of the recipient, the message to speak, and the unique ID of the recipient’s entry in our CRM table.

Back in your Mass Caller bot, click the + button and create a new blank flow. Give it the title “Voice Subflow” and save.

Screen Shot 2018-05-15 at 14.04.40.png

Go to the Templates sidebar, open up the Library window, and download the following steps:

  • Custom Data

Screen Shot 2018-05-12 at 15.40.36

  • Hang Up Call (Phone)

Screen Shot 2018-05-15 at 14.30.47

  • Initiate Call

Screen Shot 2018-05-15 at 14.05.57

  • Say Message (Phone)

Screen Shot 2018-05-15 at 14.13.15

  • Wait for Trigger from Other Flow

Screen Shot 2018-05-12 at 15.42.50

Configure Subflow Gateway

As always, we’ll start with our gateway step. Drag Wait for Trigger from Other Flow onto the Start node. This gateway step creates a subflow, which is a flow that is triggered by another flow.

Screen Shot 2018-05-12 at 15.45.42

Under Parameters to expect on trigger, we will create parameters for all the pieces of data mentioned above. We’ll call these “Phone”,”Name”, “Message”, and “RecordId”.

Screen Shot 2018-05-12 at 15.48.38.png

The gateway step will helpfully create merge fields for these parameters so we can access their values later in the flow.

Update Status

Since we’re contacting a customer marked as “new”, we need to change their status to “contacted” to track the fact that we reached out to them. (If we had several different campaigns, we could have created separate “Status” fields for each campaign, but for this demo we will just work with the one.) Add Custom Data to the next node and select your CRM table again.

Screen Shot 2018-05-12 at 15.54.09

This time, we need to change the data in the table, so select “Update a record” from the Operation dropdown.

Screen Shot 2018-05-12 at 15.55.54

In the Record Id field, click the {x} merge field button and select {incomingEvent.params.RecordId}.

Screen Shot 2018-05-12 at 15.57.43

Finally, in the ‘fields/values to update’ code box, replace “SomeField” with “Status” and “this.get(“SomeFlowField”)” with “contacted”. We don’t need to use merge fields here, since we know exactly which field to update and what the new value should be.

Screen Shot 2018-05-12 at 16.01.15

We do this update before actually making the call to allow for the possibility of an update failure. If we made the call before updating the record, and the record happened to fail to update, that customer could receive a duplicate phone call the next time this bot runs.

Make Phone Call

Our final step is to call the customer and speak the message. Add Initiate Call to the “next” branch.

Screen Shot 2018-05-15 at 14.08.22.png

Select a bot phone number from the dropdown. In the Recipient number field, click on the {x} merge field button and select {incomingEvent.params.Phone}.

Screen Shot 2018-05-15 at 14.10.17.png

Notice that Initiate Call creates exit branches for all the possible outcomes. We will ignore the “no-answer”, “busy”, and “error” branches for this simple demonstration, but think about how you might react to these outcomes if you were designing a full solution.

Under the “success” branch, add a Say Message (Phone) step.

Screen Shot 2018-05-15 at 14.14.31

Use the merge fields created by the gateway step ({incomingEvent.params.Name} and {incomingEvent.params.Message}) to personalize the call and include the campaign content that was sent via the gateway flow.

Screen Shot 2018-05-15 at 14.17.51.png

Finally, add a Hang Up Call (Phone) step to end the call. This step does not require any configuration.

Screen Shot 2018-05-15 at 14.32.31

That’s it for this flow! Now you can save and activate it. (To activate, either click the arrow on the left of the save button while in Edit mode, or click “Activate” while in View mode.)

Once you get the notification that activation was successful, go back to your bot and open up the HTTP Gateway flow.

Screen Shot 2018-05-12 at 16.09.43

Send Data to Subflow

Back in the HTTP Gateway flow, get into Edit mode and navigate to the Trigger a Flow and Proceed step we weren’t able to configure earlier.

Screen Shot 2018-05-15 at 14.33.37.png

Select “Voice Subflow” from the Flow to trigger dropdown and the step UI will update to show the expected parameters.

Screen Shot 2018-05-15 at 14.34.33.png

Add the following merge fields for each parameter (you will have to type out some of these):

  • Phone: {setRecord.currentRecord.MobilePhone}
  • Name: {setRecord.currentRecord.FirstName}
  • Message: {httpRequest.request.body.Message}
  • RecordId: {setRecord.currentRecord._MetaData.Id}

HTTScreen Shot 2018-05-15 at 14.35.57.png

That was the last step for this bot! Now you can save and activate the HTTP gateway flow.

Try it out!

Once your flows are completed and active, open up your Sample CRM table in another tab or window. Back in your Bot Designer tab, navigate to View mode for the HTTP Gateway flow, go to the Deployment tab in the sidebar, and click “Copy URL”. This will copy the deployment URL for this flow to your clipboard.

Screen Shot 2018-05-12 at 16.23.47.png

Open up whatever program or site you use to make API calls (Postman will be shown here) and paste the deployment URL. Set the method to POST and use the following JSON body (you can replace the message content with whatever you want):

 "Message": "We've got exciting news over at OneReach! Visit our website at https://onereach.ai/ to learn more!"

Screen Shot 2018-05-12 at 16.34.57

If your API client doesn’t automatically add the “Content-Type: application/json” header when you configure your body, be sure to include it. Postman will add it automatically if you set the body format to raw > JSON (application/json).

Send the request, and you should get the 200 OK response:

 "response": "Triggered Voice flow 6 times."

Screen Shot 2018-05-15 at 14.41.43.png

Go check your Sample CRM table. Each entry with a “MarketingEnabled” value of true should now have the “Status” value of “contacted”.

Screen Shot 2018-05-12 at 16.45.47.png

If you added a record associated with your mobile phone, you should also receive the call, so you can hear how it sounds.

If you’d like to test again, you can edit the “Status” field from “new” back to “contacted” in your table. You can also add more entries.


Great job! You created a Voice campaign!