Resources
/
APIs & Integrations
/
How to send WhatsApp Templates using APIs & Webhooks

How to send WhatsApp Templates using APIs & Webhooks

As a business, you might be looking to send WhatsApp messages to your customers automatically when some event pertaining to the customer has occurred. 

One way of achieving this is by using Interakt’s Track APIs to send these events to Interakt & setting Ongoing Campaigns on Interakt. You should choose this method if:

You want to keep your coding effort to the minimum. 

In this method, you simply need to make API calls when an event occurs in your system (website / app / CRM etc.)

You don’t need to worry about changing the messages you want to send when that event occurs. 

If you have complex logics for when you want the message to go out, you won’t have to build those logics. For ex: 

Suppose you want the message to go out with some delay after an event , or, 

you want the message to go out after the event only if the user has certain attributes, or, 

you want the message to go out after the event only if the user doesn’t do another event in a few hours etc.

You want to easily see the results (delivery / read stats) of these campaigns without having to build a panel of your own for this.

A summary of your campaigns is easily available to you on Interakt’s campaign dashboard.

Your website is built using Shopify. We have a direct integration with Shopify! You don’t need to call any APIs to send out WhatsApp messages when your customer abandons cart / places order etc. 

The second way of achieving this is by using Interakt’s Template Sending APIs (given below) to send the messages (templates/HSMs) to WhatsApp directly & then consuming the webhooks sent by Interakt which contain information on whether the messages got sent, delivered, read, failed. You should choose this method if:

You have the coding bandwidth & resources to: 

build a process for enabling frequent changes of the messages which have to go out

build complex logics for when to send the message. 

You already have a panel where you track your campaigns (from other channels) and hence want to track your WhatsApp campaigns in that same panel. 

(or you might be using a marketing automation tool for both the above)

You could use this second way also if you want to trigger SMS / Emails if the WhatsApp message fails to go to the customer.

Details of Template Sending APIs:

Call /v1/public/message/ to send the Template as required

1. If you want to store any message level attributes, then you can use the callback_data parameter to send additional data. This will be returned to you in the corresponding webhooks.

2. We will send an id in response to your API call. This id can be stored for future reference. This id will be referred to when webhooks are returned later.

URL: https://api.interakt.ai/v1/public/message/

Method: POST

Headers: 

• Authentication:

• You can authenticate by sending the API Key along with the request data.

• Authentication mechanism uses HTTP Basic Auth which requires you to send the API Key with the ‘Basic’ string.

• The header key-pair will look like 'Authorization: Basic <API Key>'.

The API Key will be available in your Interakt Dashboard in Developer Settings: https://app.interakt.ai/settings/developer-setting

• Content-Type:

• You must set the content-type header to 'application/json' to be able to send data to our HTTP API endpoint.

• Rate Limit: 60 requests per minute

Request Body:

Example 1:

If template header is of type text and contains a variable as well

Body contains variables

Template has 1 CTA button which contains a dynamic URL

{

    "countryCode": "+xx", /* required */

    "phoneNumber": "xxxxxxxxxx", /* required */

    "type": "Template", /* required */

    "callbackData": "some_callback_data", /* optional string with max length 512 */

    "template": {

        "name": "delivered_alert_101", /* required */

        "languageCode": "en", /* required */

        "headerValues": [

            "Alert", /* value for variable {{1}} in header text*/

        ],

        "fileName": "dummy.pdf", /* optional, and only applicable with document header */

 

        "bodyValues": [

            "There", /* value for variable {{1}} in body text */

            "1234" /* value for variable {{2}} in body text */

        ],

        "buttonValues": {

            "0" /*button index */ :[

                "12344" /* value for {{1}} for dynamic url in button at index 

position 0*/

            ]

        }

    }

}

{

    "countryCode": "+xx", /* required */

    "phoneNumber": "xxxxxxxxxx", /* required */

    "type": "Template", /* required */

    "callbackData": "some_callback_data", /* optional string with max length 512 */

    "template": {

        "name": "delivered_alert_101", /* required */

        "languageCode": "en", /* required */

        "headerValues": [

            "Alert", /* value for variable {{1}} in header text*/

        ],

        "fileName": "dummy.pdf", /* optional, and only applicable with document header */

 

        "bodyValues": [

            "There", /* value for variable {{1}} in body text */

            "1234" /* value for variable {{2}} in body text */

        ],

        "buttonValues": {

            "0" /*button index */ :[

                "12344" /* value for {{1}} for dynamic url in button at index 

position 0*/

            ]

        }

    }

}

 

 

Example 2:

If template header is of type media (image / video / document) - headerValues list will have only an element with the value of the mediaUrl

Body contains variables

Template has 2 CTA buttons - 1st one contains a phone number & 2nd one contains a dynamic URL.

{

    "countryCode": "+xx", /* required */

    "phoneNumber": "xxxxxxxxxx", /* required */

    "type": "Template", /* required */

  "callbackData": "some_callback_data", /* optional string with max length 512 */

    "template": {

        "name": "delivered_alert_101", /* required */

        "languageCode": "en", /* required */

        "headerValues": [

          "https://interaktstorage.blob.core.windows.net/mediastoragecontainer/91e5634a-33b0-44b4-a075-884778f02feb/message_template_sample/tcITOHfOz6vy.png?se=2026-08-13T11%3A53%3A58Z&sp=rt&sv=2019-12-12&sr=b&sig=PDn3cPLmV%2BYu3D7Wd10JYmPLQeyGyytl013wAtmbL6g%3D" /* media url for the header's media file */

        ],

        "bodyValues": [

            "There", /* value for variable {{1}} in body text */

            "1234" /* value for variable {{2}} in body text */

        ],

        "buttonValues": {

            "1" /*button index */ :[

                "12344" /* value for {{1}} for dynamic url in button at index position 0*/

            ]

        }

    }

}

 

Response Body:

{

    "result": true,

    "message": "Message created successfully",

    "id": "6c2d7175-fddd-4fbf-b0eb-084f170dbe08"

}

The id returned is the message id. It can be used to refer to the message-webhooks.

Field

Description


phoneNumber

User’s phone number, make sure it does not contain country code or “0” (zero) in beginning of the number

-

countryCode

Country code of the user’s phone


type

Type of message to be sent

Supported Values: Template

Template name

Make sure that the template was created in Interakt. The template name to be used is the code name of the template. How to get the code name?

Go to https://app.interakt.ai/templates/list.

Click on the template you want to use

The page that opens will have the following URL: https://app.interakt.ai/template/codename/view

Code name = the portion of the URL between ‘template/’ and ‘/view’ 

OR, if you want to use a template which was created by you in Facebook Business Manager, please click on Sync in https://app.interakt.ai/templates/list and after Sync is completed you will see the template appear in the list.

languageCode

Language code should match the language in which you had created the template. you can find all language codes here: https://developers.facebook.com/docs/whatsapp/api/messages/message-templates/

headerValues / bodyValues / buttonValues 

Values of variables contained in the template’s 

Header (if header type is text & there is a variable in it OR if header type is media)

Body

button (only in case there is a dynamic URL in the button)


Example 3: How to send payload within the template’s Quick Reply Buttons

(This is relevant only if you are using an Interakt account to send out WhatsApp campaigns and you also have a live Haptik bot. The button payloads will be returned by WhatsApp in their webhooks, whenever a customer clicks on the respective button.)

The example below shows the payload to be used for a template having:

A document header 

1 Variable in Body

3 Quick Reply Buttons (and payloads for each button)

{

   "countryCode": "+91",

   "phoneNumber": "9999999999",

   "callbackData": "some text here",

   "type": "Template",

   "template": {

       "name": "temp_with_quick_reply_buttons",

       "languageCode": "en",

       "headerValues": [

           "https://interaktstorage.blob.core.windows.net/mediastoragecontainer/07ed4524-9549-481b-ad51-400200cabe0b/message_template_media/UkJYYpHdmCBc.pdf?se=2027-01-14T09%3A53%3A35Z&sp=rt&sv=2019-12-12&sr=b&sig=iJvIT6trhzcb81xg92HytxN2SH8p4YPX8xg5IItCUgQ%3D"

       ],

       "fileName": "Sample Document for testing.pdf",

       "bodyValues": [

           "some text here if any variable in message body"

       ],

       "buttonPayload": {

           "0": ["payload0"],

           "1": ["payload1"],

           "2": ["payload2"]

       }

   }

}

Parameter to be used

Description

buttonPayload

Data type supported - For the payload only string data type is allowed. Any character like @,%,* or space along with alphanumeric values are accepted but only within the string data type like

"12 345abc( ) ? ! . # % @ ^ = + - & * ` ~ ; : < > { }"

Payload character limit - The payload character limit is 128 characters.

Note: Numbering of the buttons starts with 0. There can be a max of 3 buttons. 

Message Webhook Format 

Please provide us a Webhook URL & Secret Key for configuring the webhooks for your Interakt account.

Note that you can consume message webhooks for:

Templates (HSMs) sent via the above Template Sending APIs

Templates (HSMs) sent by setting Campaigns on Interakt

When receiving the webhooks for Sent/Delivered/Read/Failed

1. Check for the type of webhook

2. Read the data.customer object to see customer’s phone number & the values of all customer attributes stored in Interakt for that particular customer

3. Read the data.message object to identify which message is being referred to

4. Process the payload and return a success 200 within 3 seconds

1. Any non-200 status will be considered as failure

2. No response within the expected timeout will be considered as a failure

3. 5 failures within a span of 10 minutes will disable the webhook and send an alert email. Post which the webhook will be re-enabled manually.

1. There won’t be any retries for failed webhooks

2. Events which triggered when the webhook was disabled will not be triggered later

Webhook Body:

{

   "version": "1.0",

   "timestamp": "2021-11-04T00:00:00.000+0000",

   "type": "message_sent",

   "data": {

       "customer": {

           "id": "0000-0000-00000-0000",

           "channel_phone_number": "910000000000",

           "traits": {

               ...

           }

       },

       "message": {

           "id": "a991c1f8-ef9c-4685-9e35-0000000000",

           "chat_message_type": "AgentMessage",

           "channel_failure_reason": null,

           "message_status": "Read",

           "received_at_utc": "2021-11-02T07:05:15.930+0000",

           "delivered_at_utc": "2021-11-02T07:05:17.899+0000",

           "seen_at_utc": "2021-11-02T07:05:22.352+0000",

           "campaign_id": null,

           "is_template_message": true,

           "raw_template": null,/* stringified JSON of template details*/

           "channel_error_code": null,

           "message_content_type": "Template",

           "metadata": {

                “source”: “PublicInterakt”,

     “source_data”: {"callback_data": "...500 characters...",}

             }

       }

   }

}

Field

Description


type

Value will change depending on type of webhooks

Possible values:


For templates (HSMs) sent via the above template sending APIs: 


"message_api_sent"

"message_api_delivered"

"message_api_read"

"message_api_failed"


For templates (HSMs) sent via campaigns on Interakt: 


"message_campaign_sent"

"message_campaign_delivered"

"message_campaign_read"

"message_campaign_failed"


data.customer

The customer’s information. 


channel_phone_number is the user’s complete phone number with ISD code.


traits are customer User Attributes that can be set via the User Track API. You can use this to log any Customer specific data.


data.message

This is the message payload.


id corresponds to the unique message identifier.


message_status indicates the current status of the message


received_at_utc = Timestamp for single tick (ie message getting sent) 


delivered_at_utc = timestamp for double tick


seen_at_utc = timestamp for blue tick on WA


raw_template is a stringified JSON of template details.


channel_error_code and channel_failure_reason will contain details in case of Failed message


media_url will contain public link to media file


message will contain stringified raw message data (which will have to be processed further depending on message_type and message_content_type)

Webhook Requirements

Your webhook should meet the following minimum performance requirements

Must be an HTTPS endpoint

• Respond to all webhook events with a 200 OK

• Respond to all webhook events in 3 seconds or less

Interakt Security Requirements

The HTTP request will contain an “Interakt-Signature” header which contains the Hex encoded SHA256 signature of the request payload computed using the HMAC algorithm and the secret_key shared in advance, and prefixed with sha256=.

Your callback endpoint should verify this signature to validate the integrity and origin of the payload.

For Eg: Sample Headers Received in Webhook:

Interakt-Signature:sha256=b84783d10ede5bd6ed771e8b16fbe5a7093340159d6e49ec4248350b6ec2c7b4

If your Payload is:

 

‘{"foo":1,"bar":2}’

 

And your Secret key is = examplekey

Sample Code given in Python and Node JS for your reference to verify webhooks

Sample Code For Verifying Webhooks

Python:

import hmac

from hashlib import sha256

from typing import Union

 

 

def generate_signature(secret_key: str, payload: Union[bytes, str]):

   """Generates SHA256 signature prepended with sha256=

   Args:

       secret_key [String] -> shared secret, known by your service

       payload [String or bytes] -> received in request body (stringified JSON)

   """

   if not payload:

       payload = None

 

   elif isinstance(payload, str):

       payload = payload.encode("utf-8")

   hash_value = hmac.new(secret_key.encode("utf-8"), payload, sha256).hexdigest()

   return "sha256=" + str(hash_value)

 

 

def verify_signature(secret_key: str, payload: Union[bytes, str], signature: str):

   """Verifies SHA256 signature prepended with sha256=

   Args:

       secret_key [String] -> shared secret, known by your service

       payload [String or bytes] -> received in request body (stringified JSON)

       signature [Signature] -> received in Interakt-Signature request header

   """

   sha256_signature = generate_signature(secret_key=secret_key, payload=payload)

   return sha256_signature == signature

 

 

# test the function

received_hmac = "sha256=b84783d10ede5bd6ed771e8b16fbe5a7093340159d6e49ec4248350b6ec2c7b4"

data_string = '{"foo":1,"bar":2}'

key = "examplekey"

 

if verify_signature(secret_key=key, payload=data_string, signature=received_hmac):

   print("Signature valid")

 

else:

   print("Signature Invalid")

Node JS:

We Can use crypto-js NPM Package

Ref: https://www.npmjs.com/package/crypto-js

 

const CryptoJS = require('crypto-js');

 

function verifyHmac(

  receivedHmac, // received in Interakt-Signature request header

  dataString, // received in request body (stringified JSON)

  key // shared secret, known by your service

) {

  const generatedHmac = CryptoJS.HmacSHA256(dataString, key);

  const generatedHmacBase64 = "sha256=" + CryptoJS.enc.Hex.stringify(generatedHmac);

  return generatedHmacBase64 === receivedHmac;

}

// test the function

const receivedHmac = "sha256=b84783d10ede5bd6ed771e8b16fbe5a7093340159d6e49ec4248350b6ec2c7b4";

const dataString = '{"foo":1,"bar":2}';

const key = "examplekey";

if (verifyHmac(receivedHmac, dataString, key)) {

  console.log("Signature Valid");

} else {

  console.log("Signature Invalid");

}

 

 

C#:

using System;

using System.Text;

using System.Security.Cryptography;

 

class Program

{

   public static string ComputeHash(string secret, string payload)

   {

       byte[] bytes = Encoding.UTF8.GetBytes(secret);

       HMAC hmac = new HMACSHA256(bytes);

       bytes = Encoding.UTF8.GetBytes(payload);

       return "sha256=" + BitConverter.ToString(hmac.ComputeHash(bytes)).Replace("-", "").ToLower();

   }

 

   public static bool HashIsValid(string secret, string payload, string verify)

   {

 

       string hashString = ComputeHash(secret, payload);

       return verify == hashString;

   }

 

   static void Main(string[] args)

   {

       // Testing our code

       string receivedHmac = "sha256=b84783d10ede5bd6ed771e8b16fbe5a7093340159d6e49ec4248350b6ec2c7b4";

       string dataString = "{\"foo\":1,\"bar\":2}";

       string key = "examplekey";

       Console.WriteLine(HashIsValid(key, dataString, receivedHmac));

   }

}

PHP:

<?php

 

$secret = "examplekey";// your secret key

 

 

if (isset($_POST)) {

     $payload = file_get_contents('php://input');

     $headers = getallheaders();

     if (array_key_exists("Interakt-Signature", $headers)) {

        $signature = $headers["Interakt-Signature"];

        $result = hash_is_valid($secret, $payload, $signature);

        // if $result is true  

        // Hash is valid Api call is coming from interak

 

      }

   header("HTTP/1.1 200 OK");

}

function compute_hash($secret, $payload)

{  

   $prefix = "sha256=";

   $hexHash = hash_hmac('sha256', $payload, utf8_encode($secret));

   return $prefix.$hexHash;

}

function hash_is_valid($secret, $payload, $verify)

{

   $computed_hash = compute_hash($secret, $payload);

   return hash_equals($verify,$computed_hash);

}

?>

 

You can test your Endpoint Using Postman with a pre-request script:

 

var CryptoJS = require("crypto-js");

var keyString = 'examplekey';

function encrypt(data) {

   var val = CryptoJS.HmacSHA256(data, keyString);

return "sha256=" + CryptoJS.enc.Hex.stringify(val);

}

 

 

// Set local variables to postman

pm.variables.set(

   "hmac_sign", encrypt(request.data)

   );

 


This code will take your request body, create a HMAC signature using key “examplekey” (mentioned in line 2 of code) and set the env hmac_sign

Here is a Sample curl which is sending “Interakt-Signature” in headers
 

 

curl --location --request POST '<YOUR_ENDPOINT_HERE>' \

--header 'Interakt-Signature: {{hmac_sign}}' \

--header 'Content-Type: application/json' \

--data-raw '{"foo":1,"bar":2}'

 
Instead of '{"foo":1,"bar":2}'   test with any request body.
Refer Screenshots :

Get Started with Interakt Today

• Drive Sales & Customer Experience   • No Set-up Costs    No Surcharge on Notifications

Got More Questions?

Get A Live Demo
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Interakt is a Jio Haptik Product
Building Intelligent Virtual Assistants for Businesses

Download

Connect with us

Find Us On
Interakt is a Jio Haptik Product
Building Intelligent Virtual Assistants for Businesses
interakt.shop is a Haptik product.
Haptik is a WhatsApp Business Solution Provider

India | Singapore | Malaysia | UAE | Philippines | Africa

Copyright © Jio Haptik Technologies Limited 2022 | All rights reserved