10DLC Callbacks

Registering your number with 10DLC requires you to interact with different Plivo APIs.

For every Brand, Campaign, Number Linking, and Number Unlinking request you send, Plivo sends a status update to a URL you configure as a callback. You can store this information on your server for delivery status analysis.

The webhooks you integrate with Plivo are triggered by changes in the status of Brand, Campaign, or Number requests (e.g. successful registration of your brand with TCR). Upon one of these events, Plivo makes an HTTP request (POST or GET) to the endpoint URL you’ve configured for the webhook. To handle a webhook, you must create a listener (web app) that can accept these HTTP requests from Plivo.

Create Brand

1
2
3
4
5
6
7
8
9
10
11
12
let plivo = require('plivo');

let client = new plivo.Client("<auth_id>", "<auth_token>");
var callback = {"url":"https://<yourdomain>.com/tendlc_status/", "method":"POST"}

client.brand.create("govt", "<profile_uuid>", "STANDARD", true, callback)
    .then(function (response) {
        console.log(JSON.stringify(response));
    }).catch(function (error) {
        console.log("err");
        console.log(error);
    });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

# Available in versions >= 4.29.0 (https://github.com/plivo/plivo-php/releases/tag/v4.29.0)

require '/etc/plivo-php/vendor/autoload.php';
use Plivo\RestClient;
$client = new RestClient("<auth_id>", "<auth_token>");
$client
    ->client
    ->setTimeout(60);
try
{
    $callback = array("url"=>"https://<yourdomain>.com/tendlc_status/", "method"=>"POST");
    $res = $client
        ->brand
        ->create("govt321", "<profile_uuid>", "STANDARD", true, $callback);
    print_r($res);
}
catch(PlivoRestException $ex)
{
    print_r($ex);
}
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Available in versions >= 5.9.0 (https://github.com/plivo/plivo-dotnet/releases/tag/v5.9.0)

using System;
using System.Collections.Generic;
using Plivo;
using Plivo.Exception;

namespace dotnet_project
{
    class Ten_dlc
    {
        static void Main(string[] args)
        {
 
                var api = new PlivoApi("<auth_id>","<auth_token>");

                // Create Brand
            try
            {
                var response = api.Brand.Create("brand_001", "201faedc-7df9-4840-9ab1-3997ce3f7cf4", "STANDARD", true, "https://<yourdomain>.com/tendlc_status/", "POST");
                Console.WriteLine(response);
            }
            catch (PlivoRestException e)
            {
                    Console.WriteLine("Exception: " + e.Message);
            }

                
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
curl -i --user auth_id:auth_token \
    -H "Content-Type: application/json" \
    -d '{
            "brand_alias": "gov234t",
            "profile_uuid": "d61eaaaa-18b1-4473-8810-0b9d80573aa9",
            "brand_type":"STANDARD",
            "secondary_vetting":true,
            "url": "https://<yourdomain>.com/tendlc_status/",
            "method": "POST"
        }' \
        https://api.plivo.com/v1/Account/{auth_id}/10dlc/Brand/

Create Campaign

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
let plivo = require('plivo');

let client = new plivo.Client("<auth_id>", "<auth_token>");
var optional = {"url":"https://<yourdomain>.com/tendlc_status/", "method":"POST"}
client.campaign.create(
        "<brand_id>", //brand_id
        "campaign name sample", //campaign_alias
        "INSURANCE", //vertical
        "MIXED", //usecase
        [
            "CUSTOMER_CARE", //sub_use cases
            "2FA" //sub_use cases
        ],
        "sample description text", //description
        false, //embedded_link
        false, //embedded_phone
        false, //age_gated
        false, //direct_lending 
        true, //subscriber_optin
        true, //subscriber_optout
        true, //subscriber_help
        "hey", //sample1
        "test", //sample2
        optional) //callback_url and method
    .then(function(response) {
        console.log(JSON.stringify(response));
    }).catch(function(error) {
        console.log("err");
        console.log(error);
    });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

# Available in versions >= 4.29.0 (https://github.com/plivo/plivo-php/releases/tag/v4.29.0)

require '/etc/plivo-php/vendor/autoload.php';
use Plivo\RestClient;
$client = new RestClient("<auth_id>", "<auth_token>");
$client
    ->client
    ->setTimeout(60);
try
{
    $callback = array("url"=>"https://<yourdomain>.com/tendlc_status/", "method"=>"POST");
    $res = $client
        ->campaign
        ->create("<brand_id>", "campaign name sssample", "INSURANCE", "MIXED", ["CUSTOMER_CARE", "2FA"], "sample description text", False, False, False, False, True, True, True, "test 1", "test 2", $callback);
    print_r($res);
}
catch(PlivoRestException $ex)
{
    print_r($ex);
}
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// Available in versions >= 5.9.0 (https://github.com/plivo/plivo-dotnet/releases/tag/v5.9.0)

using System;
using System.Collections.Generic;
using Plivo;
using Plivo.Exception;

namespace dotnet_project
{
    class Ten_dlc
    {
        static void Main(string[] args)
        {

            var api = new PlivoApi("<auth_id>", "<auth_token>");

            // Create Campaign
            Console.WriteLine("Create Campaign");
            try
            {
                var response = api.Campaign.Create(
                brand_id: "BMIORKY",
                vertical: "INSURANCE",
                usecase: "2FA",
                sub_usecases:  new List<string>() {"2FA","MARKETING"},
                description: "OTP Campaign",
                embedded_link: false,
                embedded_phone: false,
                direct_lending: true,
                age_gated: false,
                subscriber_optin: true,
                subscriber_optout: true,
                subscriber_help: true,
                sample1: "sample message 1",
                sample2: "sample message 2",
                url: "https://<yourdomain>.com/tendlc_status/",
                method: "POST"
        );
                Console.WriteLine(response);
            }
            catch (PlivoRestException e)
            {
                Console.WriteLine("Exception: " + e.Message);
            }

        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
curl -i --user auth_id:auth_token \
    -H "Content-Type: application/json" \
    -d '{
            "brand_id": "{brand_id}",
            "vertical": "INSURANCE",
            "usecase": "MIXED",
            "sub_usecases":["2FA","ACCOUNT_NOTIFICATION", "CUSTOMER_CARE", "DELIVERY_NOTIFICATION", "FRAUD_ALERT"],
            "description": "OTP registration",
            "direct_lending": true,
            "affiliate_marketing": false,
            "embedded_link": false,
            "embedded_phone": false,
            "age_gated": false,
            "subscriber_optin": true,
            "subscriber_optout": true,
            "subscriber_help": true,
            "sample1": "Your OTP is 1234.",
            "sample2": "Your order {ID} is out for delivery.",
            "url": "https://<yourdomain>.com/tendlc_status/",
            "method": "POST"
        }' \
    https://api.plivo.com/v1/Account/{auth_id}/10dlc/Campaign/

Handle callbacks in your web app

To handle callbacks in your application, your endpoint should capture HTTP requests and respond to them. When Plivo sends the HTTP request callbacks to the webhook during an event, you should capture the request (POST or GET based on the method you’ve defined for the URL) and respond with a 200 OK response. You can store the callback data in your database.

Note: Plivo automatically retries webhooks three times if an HTTP 200 status code is not returned:
  • First at 60 seconds after the original attempt.
  • Second at 120 seconds after the first retry attempt.
  • Third at 240 seconds after the second retry attempt.

Possible status values

Endpoint Status Explanation
brand created Brand creation request was submitted to TCR for processing.
  rejected Brand creation was rejected by TCR. Reach out to our support team to learn why.
  registered Brand was registered with TCR. You can now create campaigns using this brand.
campaign created Campaign creation request was submitted to TCR for processing.
  rejected Campaign creation request was rejected by TCR. Reach out to our support team to learn why.
  registered Campaign was registered with TCR. You can now link your Plivo long codes with this campaign.
number_linking created Request to link your Plivo long code with the campaign was submitted to operators.
  failed Request to link your Plivo long code with the campaign was rejected by operators. Retry the request; if the issue persists, contact our support team.
  success Request to link your Plivo long code with the campaign was processed by operators.
number_unlinking created Request to unlink your Plivo long code with the campaign was submitted to operators.
  failed Request to unlink your Plivo long code with the campaign was rejected by operators. Retry the request; if the issue persists, contact our support team.
  success Request to unlink your Plivo long code with the campaign was processed by operators. This number can now be linked to other campaigns.

Test and Validate

Let’s take a look at an example. Typically, you would include a URL that points to your web app, but we’ll use a URL from RequestBin, a service that lets you collect, analyze, and debug HTTP requests, so we can check the callbacks.

  • Create a new bin in RequestBin.
  • Replace the “url” placeholder with the URL of the new bin.
  • Run the code that appear above. You should see callback requests in RequestBin similar to the screenshots below for various callback events.

Brand created callback

Brand registered callback

Campaign created callback

Campaign registered callback

Number linking created callback

Number unlinking created callback

Validating callbacks

To avoid spoof attacks, you can validate the callbacks that your server URL receives. All requests made by Plivo to your server URLs include X-Plivo-Signature-V2, X-Plivo-Signature-Ma-V2, and X-Plivo-Signature-V2-Nonce HTTP headers. You can use them to validate that a request is from Plivo, as we discuss in our signature validation guide.