Skip to main content
Skip table of contents

Twilio functional guide

The following guide describes the capabilities of Twilio SMS within Redpoint Interaction (RPI), how sending messages/synchronizing state data works, and links to other resources.

Key capabilities

The Twilio SMS connector providers the following key capabilities:

  • Channel Configuration

  • The ability to send SMS messages via an Interaction using an Offer Activity and/or Queue Listener

  • Receiving state/disposition date via the Channel Synchronization Task

  • Using state/disposition data as inputs to additional workflows and downstream activities

Unique features

Compared to the other SMS connectors that RPI supports, Twilio SMS connector supports the following features:

  • Enhanced fulfillment states, including:

    • Sent Count: messages that were sent via the platform. 

    • Queue Count: messages that are currently in queue, pending delivery.

    • Sending Count: messages that are currently sending and have not been yet delivered.

    • Undelivered Count: messages that were undelivered.

  • Ability to pool the sending phone numbers, utilizing Twilio's Copilot functionality. This service will help improve deliverability for larger sends. More information is available here:  https://www.twilio.com/blog/2017/03/introducing-the-copilot-api-for-programmable-sms.html

  • Support for long and short codes.

  • Ability to configure keywords for managing responses and capturing those respective keywords within the offer history states table. This would be ideal for sending follow-up messages, depending on the response.    

  • Ability to configure retry limits to minimize failures when executing large sends.

  • Ability to configure the retrieval period for event data, at the channel level.

  • Ability to configure the number of event records to process per channel sync.

  • Support for email notifications when processing bulk export jobs during channel sync, configurable at the channel level.

Process flow

The following flow chart shows how the Twilio SMS channel works within both outbound fulfillment and inbound state synchronization.

Outbound processing

Inbound processing

Outbound fulfillment

The Twilio SMS connector performs the following steps when it is used as part of an outbound Offer Activity:

Step #

Step Description

APIs / SQL

1

Initiate a connectivity test to validate the credentials configured in the channel are valid. The connectivity test will fail if the response code does not return a 200.

MethodGET

Endpointhttps://api.twilio.com/2010-04-01/Accounts/<account>/IncomingPhoneNumbers.json

Request Body

N/A

Response Body (Example):

JSON
{
  "first_page_uri": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/IncomingPhoneNumbers.json?PageSize=50&Page=0",
  "end": 4,
  "previous_page_uri": null,
  "incoming_phone_numbers": [
    {
      "sid": "PN2910cb9bddee096fa834c312ef6609e1",
      "account_sid": "AC73b0fd840079f623791424bcff9bcc03",
      "friendly_name": "(619) 555-1234",
      "phone_number": "+16195551234",
      "voice_url": "https://demo.twilio.com/welcome/voice/",
      "voice_method": "POST",
      "voice_fallback_url": "",
      "voice_fallback_method": "POST",
      "voice_caller_id_lookup": false,
      "date_created": "Tue, 18 Jul 2017 08:14:53 +0000",
      "date_updated": "Mon, 30 Nov 2020 18:58:24 +0000",
      "sms_url": "https://demo.twilio.com/welcome/sms/reply/",
      "sms_method": "POST",
      "sms_fallback_url": "",
      "sms_fallback_method": "POST",
      "address_requirements": "none",
      "beta": false,
      "capabilities": {
        "voice": true,
        "sms": true,
        "mms": true
      },
      "status_callback": "",
      "status_callback_method": "POST",
      "api_version": "2010-04-01",
      "voice_application_sid": "",
      "sms_application_sid": "",
      "origin": "twilio",
      "trunk_sid": null,
      "emergency_status": "Inactive",
      "emergency_address_sid": null,
      "address_sid": null,
      "identity_sid": null,
      "bundle_sid": null,
      "uri": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/IncomingPhoneNumbers/PN2910cb9bddee096fa834c312ef6609e1.json",
      "status": "in-use"
    }
  ],
  "uri": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/IncomingPhoneNumbers.json?PageSize=50&Page=0",
  "page_size": 50,
  "start": 0,
  "next_page_uri": null,
  "page": 0
}

2

This request is to check if the sending phone number has any recipients that have opted-out within the retrieval period, which is 13 months, but this can be configured in the channel.   

Records will be loaded to the TwilioSMS_Suppression table.

Twilio will not send the message if the recipient has opted out, but RPI will check the TwilioSMS_Suppression table before the message is sent to avoid making the request and being charged the fee to send.   

MethodGET

Endpointhttps://api.twilio.com/2010-04-01/Accounts/<account>/Messages.json?To=%2B18312267881&DateSent%3E=2020-06-09T15%3A58%3A51Z

Request Body

N/A

Response Body (Example):

JSON
{
  "first_page_uri": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages.json?To=%2B18312267881&DateSent%3E=2020-06-09T15%3A58%3A51Z&PageSize=50&Page=0",
  "end": 12,
  "previous_page_uri": null,
  "messages": [
    {
      "body": "QUIT",
      "num_segments": "1",
      "direction": "inbound",
      "from": "+xxxxxxxxxx",
      "date_updated": "Fri, 19 Feb 2021 08:46:32 +0000",
      "price": "-0.00750",
      "error_message": null,
      "uri": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages/SMc4da864a1d88b08e0a1826450c2e55a6.json",
      "account_sid": "AC73b0fd840079f623791424bcff9bcc03",
      "num_media": "0",
      "to": "+18312267881",
      "date_created": "Fri, 19 Feb 2021 08:46:32 +0000",
      "status": "received",
      "sid": "SMc4da864a1d88b08e0a1826450c2e55a6",
      "date_sent": "Fri, 19 Feb 2021 08:46:32 +0000",
      "messaging_service_sid": null,
      "error_code": null,
      "price_unit": "USD",
      "api_version": "2010-04-01",
      "subresource_uris": {
        "media": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages/SMc4da864a1d88b08e0a1826450c2e55a6/Media.json",
        "feedback": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages/SMc4da864a1d88b08e0a1826450c2e55a6/Feedback.json"
      }
    }
  ],
  "uri": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages.json?To=%2B18312267881&DateSent%3E=2020-06-09T15%3A58%3A51Z&PageSize=50&Page=0",
  "page_size": 50,
  "start": 0,
  "next_page_uri": null,
  "page": 0
}

3

RPI temp table used during execution to dedupe the records by recipient phone number. This table is dropped after execution of the offer.

Multiple queries against the New_Twilio_SMS_Channel_1_Dedupe_XXXXXXXX table.

4

RPI temp table used during execution to load any records that have opted-out OR opted back in.  This table is dropped after execution of the offer.

Multiple queries against the RPI_TwiSMSSupTemp_XXXXXXXX table.

5

This table used to store recipient phone numbers that have opt-out or opted back in.    

Multiple queries against the TwilioSMS_Suppression table. 

6

This request will initiate the sending of the message, and Twilio will queue the message on their end.  

MethodPOST

Endpointhttps://api.twilio.com/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages.json 

Request Body

To=%2B1xxxxxxxxxx&From=%2B1xxxxxxxxxx&Body=Visit+us+at+http://www.redpointglobal.com!

Response Body (Example):

JSON
{
  "sid": "SMf7b6fa0a4b564e41a336e494028ba566",
  "date_created": "Fri, 09 Jul 2021 15:58:57 +0000",
  "date_updated": "Fri, 09 Jul 2021 15:58:57 +0000",
  "date_sent": null,
  "account_sid": "AC73b0fd840079f623791424bcff9bcc03",
  "to": "+1xxxxxxxxxx",
  "from": "+1xxxxxxxxxx",
  "messaging_service_sid": null,
  "body": "Visit us at https://www.redpointglobal.com!",
  "status": "queued",
  "num_segments": "1",
  "num_media": "0",
  "direction": "outbound-api",
  "api_version": "2010-04-01",
  "price": null,
  "price_unit": "USD",
  "error_code": null,
  "error_message": null,
  "uri": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages/SMf7b6fa0a4b564e41a336e494028ba566.json",
  "subresource_uris": {
    "media": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages/SMf7b6fa0a4b564e41a336e494028ba566/Media.json"
  }
}

7

This table is used to store the individual message IDs generated by Twilio at the time of send.    During the channel sync, RPI will check the status of these messages and load the delivery status to the Offer History table, e.g., Delivered.

These records will be deleted from the table once they've been processed to avoid redundant calls to the Twilio API.  

Multiple queries against the Twilio_MessageIDs table.

8

These tables are dropped as part of the tidy up process after the execution is complete.  

RPI_TwiSMSSupTemp_XXXXXXXX
New_Twilio_SMS_Channel_1_Dedupe_XXXXXXXX

State data synchronization

Inbound process

Step #

Step Description

APIs / SQL

1

Create Twilio_MessageIDs table if it does not exist.

SQL
IF NOT EXISTS (
    SELECT 1
    FROM INFORMATION_SCHEMA.TABLES WITH(NOLOCK)
    WHERE TABLE_SCHEMA = 'dbo'
    AND TABLE_NAME = 'Twilio_MessageIDs'
)
CREATE TABLE dbo.Twilio_MessageIDs (
    [MessageID] NVARCHAR(401) NOT NULL,
    [RPContactID] BIGINT NOT NULL
);

2

For each eligible execution associated with the channel, query the Twilio_MessageIDs table to retrieve the respective MessageIds.

If no results are returned, then check next eligible execution.  

SQL
SELECT 
    t1.[MessageID], 
    t1.[RPContactID] 
FROM 
    [dbo].[Twilio_MessageIDs] t1 
LEFT JOIN 
    [dbo].[OfferHistorySG] t2 
ON 
    t1.[RPContactID] = t2.[RPContactID] 
WHERE 
    t2.[ChannelExecutionID] = <channelexecutionid>;

3

For each message that was sent after the last channel sync, check the delivery status by calling the Messages endpoint.  

MethodGET

Endpointhttps://api.twilio.com/2010-04-01/Accounts/<account>/Messages/<message>.json 

Request Body

N/A

Response Body (Example):

JSON
{
  "body": "Visit us at https://www.redpointglobal.com!",
  "num_segments": "1",
  "direction": "outbound-api",
  "from": "+xxxxxxxxxx",
  "date_updated": "Fri, 09 Jul 2021 16:30:43 +0000",
  "price": null,
  "error_message": null,
  "uri": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages/SMb622e6344bb6474b8d8a73fafdf8fba9.json",
  "account_sid": "AC73b0fd840079f623791424bcff9bcc03",
  "num_media": "0",
  "to": "+xxxxxxxxxx",
  "date_created": "Fri, 09 Jul 2021 16:30:43 +0000",
  "status": "delivered",
  "sid": "SMb622e6344bb6474b8d8a73fafdf8fba9",
  "date_sent": "Fri, 09 Jul 2021 16:30:43 +0000",
  "messaging_service_sid": null,
  "error_code": null,
  "price_unit": "USD",
  "api_version": "2010-04-01",
  "subresource_uris": {
    "media": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages/SMb622e6344bb6474b8d8a73fafdf8fba9/Media.json",
    "feedback": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages/SMb622e6344bb6474b8d8a73fafdf8fba9/Feedback.json"
  }
}

4

Create RPI temp table for bulk loading the status event for all messages associated with the execution.

SQL
IF NOT EXISTS (
    SELECT 1
    FROM INFORMATION_SCHEMA.TABLES WITH(NOLOCK)
    WHERE TABLE_SCHEMA = 'dbo'
    AND TABLE_NAME = 'RPI_TwilioStates_New_Twilio_SMS_Channel_23'
)
CREATE TABLE dbo.RPI_TwilioStates_New_Twilio_SMS_Channel_23 (
    [AddressKey] NVARCHAR(100) NULL,
    [ChannelExecutionID] INT NULL,
    [FulfillmentState] NVARCHAR(100) NULL,
    [EventName] NVARCHAR(255) NULL,
    [Timestamp] DATETIME NULL,
    [ResultsTableName] NVARCHAR(50) NULL
);

5

Load the data from the temp table to the Offer History states table.

SQL
INSERT INTO [dbo].[OfferHistorySG_States] 
    ([RPContactID], [ChannelExecutionID], [FulfillmentState], [EventName], [Timestamp]) 
SELECT 
    a0.[RPContactID], 
    a0.[ChannelExecutionID], 
    a1.[FulfillmentState], 
    a1.[EventName], 
    a1.[Timestamp] 
FROM 
    [dbo].[OfferHistorySG] a0, 
    [dbo].[RPI_TwilioStates_New_Twilio_SMS_Channel_23] a1 
WHERE 
    a0.[ChannelExecutionID] = a1.[ChannelExecutionID] 
    AND a0.[AddressKey] = a1.[AddressKey] 
    AND NOT EXISTS (
        SELECT 1 
        FROM [dbo].[OfferHistorySG_States] b0 
        WHERE 
            b0.[ChannelExecutionID] = a0.[ChannelExecutionID] 
            AND b0.[RPContactID] = a0.[RPContactID] 
            AND b0.[FulfillmentState] = a1.[FulfillmentState] 
            AND (
                b0.[EventName] = a1.[EventName] 
                OR (b0.[EventName] IS NULL AND a1.[EventName] IS NULL)
            )
    );

6

Once the data is loaded for messages associated with the channel execution, delete the respective message(s) from the Twilio_MessageIDs table.

Repeat steps 2 to 6 until all eligible executions associated with the channel have been processed.

SQL
DELETE FROM [dbo].[Twilio_MessageIDs]
WHERE [MessageID] = 'SMb622e6344bb6474b8d8a73fafdf8fba9';

7

For each eligible execution, call the Messages endpoint to retrieve states information (including response keywords if configured), filtered on events that have occurred after the last channel sync.  

MethodGET

Endpointhttps://api.twilio.com/2010-04-01/Accounts/<account>/Messages.json?To=%2B18312267881&DateSent%3E=2021-07-09T16%3A26%3A05Z

Request Body

N/A

Response Body (Example):

JSON
{
  "first_page_uri": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages.json?To=%2B18312267881&DateSent%3E=2021-07-09T17%3A31%3A14Z&PageSize=50&Page=0",
  "end": 0,
  "previous_page_uri": null,
  "messages": [
    {
      "body": "Stop",
      "num_segments": "1",
      "direction": "inbound",
      "from": "+xxxxxxxxxx",
      "date_updated": "Fri, 09 Jul 2021 17:36:12 +0000",
      "price": null,
      "error_message": null,
      "uri": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages/SMc5cb13292b2cc6e885ccacf666f17adc.json",
      "account_sid": "AC73b0fd840079f623791424bcff9bcc03",
      "num_media": "0",
      "to": "+18312267881",
      "date_created": "Fri, 09 Jul 2021 17:36:11 +0000",
      "status": "received",
      "sid": "SMc5cb13292b2cc6e885ccacf666f17adc",
      "date_sent": "Fri, 09 Jul 2021 17:36:12 +0000",
      "messaging_service_sid": null,
      "error_code": null,
      "price_unit": "USD",
      "api_version": "2010-04-01",
      "subresource_uris": {
        "media": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages/SMc5cb13292b2cc6e885ccacf666f17adc/Media.json",
        "feedback": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages/SMc5cb13292b2cc6e885ccacf666f17adc/Feedback.json"
      }
    }
  ],
  "uri": "/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages.json?To=%2B18312267881&DateSent%3E=2021-07-09T17%3A31%3A14Z&PageSize=50&Page=0",
  "page_size": 50,
  "start": 0,
  "next_page_uri": null,
  "page": 0
}

8

Create RPI temp table for bulk loading states data.

SQL
IF NOT EXISTS (
    SELECT 1 
    FROM INFORMATION_SCHEMA.TABLES WITH(NOLOCK) 
    WHERE TABLE_SCHEMA = 'dbo' 
    AND TABLE_NAME = 'RPI_TwilioStates_New_Twilio_SMS_Channel_23'
)
CREATE TABLE dbo.RPI_TwilioStates_New_Twilio_SMS_Channel_23 (
    [AddressKey] NVARCHAR(100) NULL, 
    [ChannelExecutionID] INT NULL, 
    [FulfillmentState] NVARCHAR(100) NULL, 
    [EventName] NVARCHAR(255) NULL, 
    [Timestamp] DATETIME NULL, 
    [ResultsTableName] NVARCHAR(50) NULL
);

9

Create separate RPI temp table for loading messages from phone numbers that have unsubscribed.   

SQL
IF EXISTS (
    SELECT 1 
    FROM INFORMATION_SCHEMA.TABLES WITH(NOLOCK) 
    WHERE TABLE_SCHEMA = 'dbo' 
    AND TABLE_NAME = 'RPI_TwiSMSSupTemp_1d3c86b5cfdc'
)

DROP TABLE [dbo].[RPI_TwiSMSSupTemp_1d3c86b5cfdc];

CREATE TABLE dbo.RPI_TwiSMSSupTemp_1d3c86b5cfdc (
    [PhoneNumber] NVARCHAR(50) NULL, 
    [ActivityDate] DATETIME NULL, 
    [MessagingServiceID] NVARCHAR(100) NULL, 
    [TwilioNumber] NVARCHAR(50) NULL, 
    [Activity] NVARCHAR(50) NULL
);

10

If any records are inserted into the RPI_TwiSMSSupTemp_xxxxxxxxx table, then insert those records into the TwilioSMS_Suppression table as well.

SQL
INSERT INTO [dbo].[TwilioSMS_Suppression] 
    ([PhoneNumber], [ActivityDate], [MessagingServiceID], [TwilioNumber], [Activity]) 
SELECT 
    a1.[PhoneNumber], 
    a1.[ActivityDate], 
    a1.[MessagingServiceID], 
    a1.[TwilioNumber], 
    a1.[Activity] 
FROM 
    [dbo].[RPI_TwiSMSSupTemp_1d3c86b5cfdc] a1 
WHERE 
    NOT EXISTS (
        SELECT 1 
        FROM [dbo].[TwilioSMS_Suppression] s1 
        WHERE 
            a1.[PhoneNumber] = s1.[PhoneNumber] 
            AND a1.[ActivityDate] = s1.[ActivityDate] 
            AND a1.[TwilioNumber] = s1.[TwilioNumber] 
            AND a1.[Activity] = s1.[Activity]
    );

11

Check if the TwilioSMS_Suppression table exists and if not, create the table.  

SQL
IF NOT EXISTS (
    SELECT 1 
    FROM INFORMATION_SCHEMA.TABLES WITH(NOLOCK) 
    WHERE TABLE_SCHEMA = 'dbo' 
    AND TABLE_NAME = 'TwilioSMS_Suppression'
)
CREATE TABLE dbo.TwilioSMS_Suppression (
    [PhoneNumber] NVARCHAR(50) NULL, 
    [ActivityDate] DATETIME NULL, 
    [MessagingServiceID] NVARCHAR(100) NULL, 
    [TwilioNumber] NVARCHAR(50) NULL, 
    [Activity] NVARCHAR(50) NULL
);

12

Load the data from the temp table to the Offer History states table.

SQL
INSERT INTO [dbo].[OfferHistorySG_States] 
    ([RPContactID], [ChannelExecutionID], [FulfillmentState], [EventName], [Timestamp])
SELECT 
    r1.[RPContactID], 
    a1.[ChannelExecutionID], 
    a1.[FulfillmentState], 
    a1.[EventName], 
    a1.[Timestamp]
FROM 
    [dbo].[OfferHistorySG] r1, 
    [dbo].[RPI_TwilioStates_New_Twilio_SMS_Channel_23] a1
WHERE 
    r1.[ChannelExecutionID] = a1.[ChannelExecutionID] 
    AND r1.[AddressKey] = a1.[AddressKey]
    AND NOT EXISTS (
        SELECT * 
        FROM [dbo].[OfferHistorySG_States] s1 
        WHERE 
            s1.[ChannelExecutionID] = r1.[ChannelExecutionID] 
            AND s1.[RPContactID] = r1.[RPContactID] 
            AND s1.[FulfillmentState] = a1.[FulfillmentState] 
            AND s1.[Timestamp] = a1.[Timestamp]
    );

13

Query the TwilioSMS_Suppression table to determine the max activity date for each Twilio number and recipient phone number combination.    

The data from this query will be used to determine which records have already been processed, so that they're not picked up again during the next channel sync.

SQL
SELECT 
    ActivityDate = MAX([ActivityDate]), 
    [Activity], 
    [TwilioNumber], 
    [PhoneNumber]
FROM 
    [dbo].[TwilioSMS_Suppression]
WHERE 
    [Activity] IN ('STOP', 'STOPALL', 'UNSUBSCRIBE', 'CANCEL', 'END', 'QUIT', 'START', 'YES', 'UNSTOP', 'HELP', 'INFO')
    AND [TwilioNumber] = '+18312267881'
GROUP BY 
    [Activity], 
    [TwilioNumber], 
    [PhoneNumber];

14

Delete RPI temp table once processing is complete.

SQL
IF EXISTS (
    SELECT 1 
    FROM INFORMATION_SCHEMA.TABLES WITH(NOLOCK) 
    WHERE TABLE_SCHEMA = 'dbo' 
    AND TABLE_NAME = 'RPI_TwiSMSSupTemp_1d3c86b5cfdc'
)
DROP TABLE [dbo].[RPI_TwiSMSSupTemp_1d3c86b5cfdc];

15

Delete RPI temp table once processing is complete.

Repeat steps 7-15 for each eligible execution associated with the channel. 

SQL
IF EXISTS (
    SELECT 1 
    FROM INFORMATION_SCHEMA.TABLES WITH(NOLOCK) 
    WHERE TABLE_SCHEMA = 'dbo' 
    AND TABLE_NAME = 'RPI_TwilioStates_New_Twilio_SMS_Channel_23'
)
DROP TABLE [dbo].[RPI_TwilioStates_New_Twilio_SMS_Channel_23];

16

Aggregate results and write them back to the op_ChannelExecutionResults table in the operational databases.

N/A

Limitations

Limitation #

Limitation Detail

1

Twilio will split the offer into multiple messages if the content exceeds 160 characters.

2

Twilio does not support batching when sending messages. Each recipient will initiate a single API request which may extend processing time for larger sends.     

3

The Twilio API does have rate limitations, but the exact limits are not documented by Twilio. When limits are reached, the request will fail with error code 429 "Too Many Requests".  When this occurs, it's recommended to modify the following channel configuration options:

For sends larger than 500 recipients at one time, it's recommended that you increase the minimum and maximum API call retry delay thresholds, e.g., starting with 2/20 respectively. Continue to adjust until the failures are resolved.   

4

Twilio will throttle the actual delivery of the messages, depending on the type of phone number being used for sending. For example, if a standard phone number is configured, the messages will be sent to the carrier at a rate of one per second.     

More information is available on their support site: https://support.twilio.com/hc/en-us/articles/115002943027-Understanding-Twilio-Rate-Limits-and-Message-Queues

5

Opt-out messages are not automatically added to the offer during send and will need to be configured directly within the offer.

6

Twilio does not support the ability to match the response data to a specific send for a recipient. For example, if a recipient receives 5 messages over a period of 30 days, and they respond with STOP on the last message, then that STOP event will be loaded for each of the 5 messages.   

7

Short codes currently are not able to receive states data, whether used as standalone phone number or part of a messaging service. This feature is currently in public beta.
More information is available on their support site: https://www.twilio.com/docs/messaging/api/services-shortcode-resource#public-beta

Performance testing will be completed and published by the end of August 2021.

Logging

Below is an example of the Interaction log for an offer using the Twilio SMS channel:

Log

Log Entry Descriptions

2021/07/09 16:30:38 Fulfillment Action complete
2021/07/09 16:30:38 Generating any Fulfillment Action reports
2021/07/09 16:30:38 Tidying up Fulfillment Action
2021/07/09 16:30:38 Action: New Twilio SMS Channel 1 Activity: 0 unsubscribed seed SMS numbers
2021/07/09 16:30:38 Action: New Twilio SMS Channel 1 Activity: 0 invalid seed SMS numbers
2021/07/09 16:30:38 Action: New Twilio SMS Channel 1 Activity: 0 seed SMS(s) have been sent
2021/07/09 16:30:38 Action: New Twilio SMS Channel 1 Activity: 0 unsubscribed SMS numbers
2021/07/09 16:30:38 Action: New Twilio SMS Channel 1 Activity: 0 invalid SMS numbers
2021/07/09 16:30:38 Action: New Twilio SMS Channel 1 Activity: 2 SMS(s) have been sent
2021/07/09 16:30:38 Action: New Twilio SMS Channel 1 Activity: Sending first batch of SMS campaign: 2 messages
2021/07/09 16:30:38 Action: New Twilio SMS Channel 1 Activity: Preparing to send Twilio messages
2021/07/09 16:30:38 Action: New Twilio SMS Channel 1 Activity: Count before deduplication: 2
2021/07/09 16:30:37 Action: New Twilio SMS Channel 1 Activity: About to send SMS campaign
2021/07/09 16:30:37 Action: New Twilio SMS Channel 1 Activity: Retrieving SMS subscription data
2021/07/09 16:30:36 Action: New Twilio SMS Channel 1 Activity: Channel availability test completed successfully
2021/07/09 16:30:36 Action: New Twilio SMS Channel 1 Activity: Connect to Twilio: - Success
2021/07/09 16:30:36 Action: New Twilio SMS Channel 1 Activity: Channel availability test returned the following results:
2021/07/09 16:30:35 Action: New Twilio SMS Channel 1 Activity: Testing channel availability, attempt 1
2021/07/09 16:30:35 Action: New Twilio SMS Channel 1 Activity: Committing offer history data
2021/07/09 16:30:35 Action: New Twilio SMS Channel 1 Activity: Number of duplicates: 0
2021/07/09 16:30:35 Action: New Twilio SMS Channel 1 Activity: Count after deduplication: 2
2021/07/09 16:30:35 Action: New Twilio SMS Channel 1 Activity: Count before deduplication: 2
2021/07/09 16:30:35 Action: New Twilio SMS Channel 1 Activity: Deduplicating on contact key
2021/07/09 16:30:35 Starting action New Twilio SMS Channel 1
2021/07/09 16:30:35 Preparing to run any actions
2021/07/09 16:30:35 Completing Fulfillment Action execution
2021/07/09 16:30:34 Fulfillment Action preparing to start
2021/07/09 16:30:34 Preparing to execute

Sending first batch of SMS campaign: XX messages = the number of messages that will be attempted to send

XX SMS(s) have been sent = the actual number of messages that were sent to Twilio

XX invalid SMS numbers = the total number of invalid SMS numbers, eg not formatted correctly

XX unsubscribed SMS numbers = the total number of SMS numbers that had opted out and not eligible send.      Twilio will not send the message if the recipient has opted out but RPI will check before the message is sent, to avoid making the request and being charged the fee to send.   

XX seed SMS(s) have been sent = the total number of seed SMS messages that were sent

XX invalid seed SMS numbers = the total number of invalid seed SMS numbers

XX unsubscribed seed SMS numbers =  the total number of seed SMS numbers that had opted out and not eligible send.

Troubleshooting

When the Enable trace option is selected within the Advanced tab of the Twilio SMS channel configuration, the following samples of trace HTTP request/response log messages are being generated:

Description

HTTP Request

HTTP Response

Validate the account credentials are valid.

7/9/2021 4:05:33 PM
Trace HTTP Request
Request Endpoint: https://api.twilio.com/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/IncomingPhoneNumbers.json
Request Method: GET

Version :6.3.0.0
FileVersion :6.3.21180.1244
ProductVersion :6.3.20210629.21180 -- develop -- VSTS-Build
DateTime :2021-07-09T16:05:33
TypeName :HttpClientLoggingHandler
TypeFullName :RedPoint.Plugins.Extensions.HttpClientLoggingHandler

Category: Plugin Trace
Priority: 10
Severity: Information

NA - to be looked at

Check if any opt-outs are associated with the sending from number before sending the actual message. The retrieval period defaults to 13 months, but it can be configured within the channel.   

7/9/2021 4:05:34 PM
Trace HTTP Request
Request Endpoint: https://api.twilio.com/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages.json?To=%2B18312267881&DateSent>=2020-06-09T16%3A05%3A34Z
Request Method: GET

Version :6.3.0.0
FileVersion :6.3.21180.1244
ProductVersion :6.3.20210629.21180 -- develop -- VSTS-Build
DateTime :2021-07-09T16:05:34
TypeName :HttpClientLoggingHandler
TypeFullName :RedPoint.Plugins.Extensions.HttpClientLoggingHandler

Category: Plugin Trace
Priority: 10
Severity: Information

NA - to be looked at

Send the message to the recipient(s).

This request is made for each recipient being sent a message.


7/9/2021 4:05:35 PM
Trace HTTP Request
Request Endpoint: https://api.twilio.com/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages.json
Request Method: POST

Version :6.3.0.0
FileVersion :6.3.21180.1244
ProductVersion :6.3.20210629.21180 -- develop -- VSTS-Build
DateTime :2021-07-09T16:05:35
TypeName :HttpClientLoggingHandler
TypeFullName :RedPoint.Plugins.Extensions.HttpClientLoggingHandler

Category: Plugin Trace
Priority: 10
Severity: Information

NA - to be looked at

Check message status for any messages sent after the last channel sync.

7/9/2021 4:06:17 PM
Trace HTTP Request
Request Endpoint: https://api.twilio.com/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages/SM1c437e0e454a47fd9a9fd0d19783a2a0.json
Request Method: GET

Version :6.3.0.0
FileVersion :6.3.21180.1244
ProductVersion :6.3.20210629.21180 -- develop -- VSTS-Build
DateTime :2021-07-09T16:06:17
TypeName :HttpClientLoggingHandler
TypeFullName :RedPoint.Plugins.Extensions.HttpClientLoggingHandler

Category: Plugin Trace
Priority: 10
Severity: Information

NA - to be looked at

Retrieve states information for the sending number that have occurred since the last channel sync.

7/9/2021 4:06:17 PM
Trace HTTP Request
Request Endpoint: https://api.twilio.com/2010-04-01/Accounts/AC73b0fd840079f623791424bcff9bcc03/Messages.json?To=%2B18312267881&DateSent>=2021-07-09T16%3A03%3A19Z
Request Method: GET

Version :6.3.0.0
FileVersion :6.3.21180.1244
ProductVersion :6.3.20210629.21180 -- develop -- VSTS-Build
DateTime :2021-07-09T16:06:17
TypeName :HttpClientLoggingHandler
TypeFullName :RedPoint.Plugins.Extensions.HttpClientLoggingHandler

Category: Plugin Trace
Priority: 10
Severity: Information

NA - to be looked at

Common questions

Q

Can I use a URL shortening service like Bit.ly or Rebrandly within the content?

A

Yes, URL shorteners are supported within the offers, but per Twilio, this has potential to result in carriers blocking the message. It's recommended to monitor the delivery metrics for the sends and adjust the offer if necessary.   

Q

The offer is failing with an error code 429 "Too Many Requests" - what does this mean?

A

This error may occur when sending larger volumes at one time. For any sends larger than 500 recipients, it may be necessary to adjust the API retry thresholds in the channel configuration:

It's recommended to start by increasing the minimum and maximum API call retry delays to 2 and 20 respectively, and continue to increase those thresholds if failures are still occurring.

Q

Do the recipient and sending phone numbers need to be in a specific format?

A

Yes, the format of the recipient phone number must be stored in the database as "[+] [country code] [subscriber number including area code]", e.g., "+14155552671"

Likewise, the sending phone number must be formatted the same way, unless using a short code.

Q

In the Twilio console, we're seeing error code 30007 "Message Delivery - Message Filtered" after sending a message - what does this mean? 

A

This error occurs when the carrier filters or blocks the message being sent by Twilio. Twilio support has some recommendations for addressing this error, published here:

https://support.twilio.com/hc/en-us/articles/360008704834-Error-30007-Message-Delivery-Message-Filtered-when-Sending-SMS

We've also spoken to Twilio directly regarding this error, and they offered additional suggestions, including:

  • To prevent ALL filtering, the use of a short code is the gold standard, but it's also more expensive, and the application process is lengthy, with an 8-12 week provisioning period.   

  • If using a short code is not a viable option, the next best option is to apply for a high-throughput Toll Free Number. Marketing messages are permitted but still require organizations to get consent from the recipient.

  • The last option to consider is using Twilio messaging service called Copilot, which allows multiple numbers to be “pooled” when sending messages. This feature is supported within the Twilio SMS connector.  More information is available here:  https://www.twilio.com/blog/2017/03/introducing-the-copilot-api-for-programmable-sms.html


JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.