Message Webhook Format

Please enable webhooks from your Interakt Account’s Developer Settings: https://app.interakt.ai/settings/developer-setting.

  • – You can use Webhooks only if you are subscribed to Interakt’s Growth / Advanced Plans.
  • – While configuring the webhook, you will be required to provide us a Webhook URL & Secret Key.
  • – You would also have to specify the type of webhooks you require for your account (read below to understand the different types)

Note that you can consume message webhooks for:

1. Delivery statuses (Sent / Delivered / Read / Failed) of Templates (HSMs) sent via the above Template Sending APIs

2. Delivery statuses (Sent / Delivered / Read / Failed) of Templates (HSMs) sent by setting Campaigns on Interakt

3. Incoming customer messages on your WhatsApp API number, connected with your Interakt account – Note that this webhook will only be available on higher plans.

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

1. Check for the type of webhook

 For delivery status webhooks of templates sent via APIs, the types will be as follows:

  1. “message_api_sent”
  2. “message_api_delivered”
  3. “message_api_read”
  4. “message_api_failed”

 For delivery status webhooks of templates sent via Interakt Campaigns, the types will be as follows:

  1. “message_campaign_sent”
  2. “message_campaign_delivered”
  3. “message_campaign_read”
  4. “message_campaign_failed”

 For incoming customer message webhooks, the type will be as follows:

  1. “message_received”

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

– Any non-200 status will be considered as failure

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

– 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.

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

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

Webhook Body – message_api_sent:

(note – data sent in the “traits” object depends on the customer traits present in your Interakt account. The traits given in the example below corresponds to a test account)

{

“version”: “1.0”,

“timestamp”: “2022-06-03T05:43:33.237499”,

“type”: “message_api_sent”,

“data”: {

“customer”: {

“id”: “52918eb3-bd00-4331-a51d-c4dcffee48d6”,

“channel_phone_number”: “917003705584”,

“traits”: {

“name”: “SKGG”,

“amount”: 7000,

“total_orders_count”: 0,

“last_order_id”: null,

“last_order_name”: null,

“total_spent”: “0.00”,

“whatsapp_opted_in”: false,

“created_at”: “2021-06-23T06:46:11”,

“User Id”: “111”,

“email”: “[email protected]”,

}

},

“message”: {

“id”: “dfc668a2-c06c-4e9a-a4fd-7b65bc1fdc84”,

“chat_message_type”: “PublicApiMessage”,

“channel_failure_reason”: null,

“message_status”: “Sent”,

“received_at_utc”: “2022-06-03T05:43:33.133000”,

“delivered_at_utc”: null,

“seen_at_utc”: null,

“campaign_id”: null,

“is_template_message”: true,

“raw_template”: “{\”id\”: \”281a5a78-f2b2-46c9-b9bb-d620d3b2894c\”, \”created_at_utc\”: \”2022-03-30T07:04:04.078\”, \”modified_at_utc\”: \”2022-03-31T05:41:09.61\”, \”created_by_user_id\”: \”37088e03-3633-4aa4-b4d8-99edbc56d4fc\”, \”is_deleted\”: false, \”name\”: \”test_template_lp\”, \”language\”: \”en\”, \”category\”: \”ALERT_UPDATE\”, \”header_format\”: null, \”header\”: null, \”header_handle\”: null, \”header_handle_file_url\”: null, \”header_handle_file_name\”: null, \”header_text\”: null, \”body\”: \”Hi  {{1}} \\nWelcome to interakt, my name is  {{2}} . I hope your 14 day free trial was helpful. For any queries please reach to us.\”, \”body_text\”: \”[\\\”Clients\\\”, \\\”Sender\\\”]\”, \”footer\”: \”Team interakt\”, \”buttons\”: \”[{\\\”type\\\”: \\\”QUICK_REPLY\\\”, \\\”text\\\”: \\\”Thank you\\\”}, {\\\”type\\\”: \\\”QUICK_REPLY\\\”, \\\”text\\\”: \\\”What is qralink?\\\”}, {\\\”type\\\”: \\\”QUICK_REPLY\\\”, \\\”text\\\”: \\\”Speak to an agent\\\”}]\”, \”button_text\”: null, \”display_name\”: \”Test template\”, \”organization_id\”: \”ba4308f1-a506-44d2-a8c3-17380216cf91\”, \”approval_status\”: \”APPROVED\”, \”wa_template_id\”: \”3224400424546364\”, \”is_archived\”: false}”,

“channel_error_code”: null,

“message_content_type”: “Template”,

“media_url”: null,

“message”: “[{\”type\”: \”body\”, \”parameters\”: [{\”type\”: \”text\”, \”text\”: \”Saandhy\”}, {\”type\”: \”text\”, \”text\”: \”Varun\”}]}]”,

“meta_data”: {

“source”: “PublicInterakt”,

“source_data”: {

“callback_data”: “some text here”

}

}

}

}

}

Webhook Body – message_api_delivered:

(note – data sent in the “traits” object depends on the customer traits present in your Interakt account. The traits given in the example below corresponds to a test account)

{

“version”: “1.0”,

“timestamp”: “2022-06-03T05:43:33.930227”,

“type”: “message_api_delivered”,

“data”: {

“customer”: {

“id”: “52918eb3-bd00-4331-a51d-c4dcffee48d6”,

“channel_phone_number”: “917003705584”,

“traits”: {

“name”: “SKGG”,

“amount”: 7000,

“total_orders_count”: 0,

“last_order_id”: null,

“last_order_name”: null,

“total_spent”: “0.00”,

“whatsapp_opted_in”: false,

“created_at”: “2021-06-23T06:46:11”,

“User Id”: “111”,

“email”: “[email protected]”,

}

},

“message”: {

“id”: “dfc668a2-c06c-4e9a-a4fd-7b65bc1fdc84”,

“chat_message_type”: “PublicApiMessage”,

“channel_failure_reason”: null,

“message_status”: “Delivered”,

“received_at_utc”: “2022-06-03T05:43:33.133000”,

“delivered_at_utc”: “2022-06-03T05:43:33.848000”,

“seen_at_utc”: null,

“campaign_id”: null,

“is_template_message”: true,

“raw_template”: “{\”id\”: \”281a5a78-f2b2-46c9-b9bb-d620d3b2894c\”, \”created_at_utc\”: \”2022-03-30T07:04:04.078\”, \”modified_at_utc\”: \”2022-03-31T05:41:09.61\”, \”created_by_user_id\”: \”37088e03-3633-4aa4-b4d8-99edbc56d4fc\”, \”is_deleted\”: false, \”name\”: \”test_template_lp\”, \”language\”: \”en\”, \”category\”: \”ALERT_UPDATE\”, \”header_format\”: null, \”header\”: null, \”header_handle\”: null, \”header_handle_file_url\”: null, \”header_handle_file_name\”: null, \”header_text\”: null, \”body\”: \”Hi  {{1}} \\nWelcome to interakt, my name is  {{2}} . I hope your 14 day free trial was helpful. For any queries please reach to us.\”, \”body_text\”: \”[\\\”Clients\\\”, \\\”Sender\\\”]\”, \”footer\”: \”Team interakt\”, \”buttons\”: \”[{\\\”type\\\”: \\\”QUICK_REPLY\\\”, \\\”text\\\”: \\\”Thank you\\\”}, {\\\”type\\\”: \\\”QUICK_REPLY\\\”, \\\”text\\\”: \\\”What is qralink?\\\”}, {\\\”type\\\”: \\\”QUICK_REPLY\\\”, \\\”text\\\”: \\\”Speak to an agent\\\”}]\”, \”button_text\”: null, \”display_name\”: \”Test template\”, \”organization_id\”: \”ba4308f1-a506-44d2-a8c3-17380216cf91\”, \”approval_status\”: \”APPROVED\”, \”wa_template_id\”: \”3224400424546364\”, \”is_archived\”: false}”,

“channel_error_code”: null,

“message_content_type”: “Template”,

“media_url”: null,

“message”: “[{\”type\”: \”body\”, \”parameters\”: [{\”type\”: \”text\”, \”text\”: \”Saandhy\”}, {\”type\”: \”text\”, \”text\”: \”Varun\”}]}]”,

“meta_data”: {

“source”: “PublicInterakt”,

“source_data”: {

“callback_data”: “some text here”

}

}

}

}

}

Webhook Body – message_api_read:

(note – data sent in the “traits” object depends on the customer traits present in your Interakt account. The traits given in the example below corresponds to a test account)

{

“version”: “1.0”,

“timestamp”: “2022-06-03T05:43:33.930227”,

“type”: “message_api_read”,

“data”: {

“customer”: {

“id”: “52918eb3-bd00-4331-a51d-c4dcffee48d6”,

“channel_phone_number”: “917003705584”,

“traits”: {

“name”: “SKGG”,

“amount”: 7000,

“total_orders_count”: 0,

“last_order_id”: null,

“last_order_name”: null,

“total_spent”: “0.00”,

“whatsapp_opted_in”: false,

“created_at”: “2021-06-23T06:46:11”,

“User Id”: “111”,

“email”: “[email protected]”,

}

},

“message”: {

“id”: “dfc668a2-c06c-4e9a-a4fd-7b65bc1fdc84”,

“chat_message_type”: “PublicApiMessage”,

“channel_failure_reason”: null,

“message_status”: “Read”,

“received_at_utc”: “2022-06-03T05:43:33.133000”,

“delivered_at_utc”: “2022-06-03T05:43:33.848000”,

“seen_at_utc”: “2022-06-03T05:43:34.257000”,

“campaign_id”: null,

“is_template_message”: true,

“raw_template”: “{\”id\”: \”281a5a78-f2b2-46c9-b9bb-d620d3b2894c\”, \”created_at_utc\”: \”2022-03-30T07:04:04.078\”, \”modified_at_utc\”: \”2022-03-31T05:41:09.61\”, \”created_by_user_id\”: \”37088e03-3633-4aa4-b4d8-99edbc56d4fc\”, \”is_deleted\”: false, \”name\”: \”test_template_lp\”, \”language\”: \”en\”, \”category\”: \”ALERT_UPDATE\”, \”header_format\”: null, \”header\”: null, \”header_handle\”: null, \”header_handle_file_url\”: null, \”header_handle_file_name\”: null, \”header_text\”: null, \”body\”: \”Hi  {{1}} \\nWelcome to interakt, my name is  {{2}} . I hope your 14 day free trial was helpful. For any queries please reach to us.\”, \”body_text\”: \”[\\\”Clients\\\”, \\\”Sender\\\”]\”, \”footer\”: \”Team interakt\”, \”buttons\”: \”[{\\\”type\\\”: \\\”QUICK_REPLY\\\”, \\\”text\\\”: \\\”Thank you\\\”}, {\\\”type\\\”: \\\”QUICK_REPLY\\\”, \\\”text\\\”: \\\”What is qralink?\\\”}, {\\\”type\\\”: \\\”QUICK_REPLY\\\”, \\\”text\\\”: \\\”Speak to an agent\\\”}]\”, \”button_text\”: null, \”display_name\”: \”Test template\”, \”organization_id\”: \”ba4308f1-a506-44d2-a8c3-17380216cf91\”, \”approval_status\”: \”APPROVED\”, \”wa_template_id\”: \”3224400424546364\”, \”is_archived\”: false}”,

“channel_error_code”: null,

“message_content_type”: “Template”,

“media_url”: null,

“message”: “[{\”type\”: \”body\”, \”parameters\”: [{\”type\”: \”text\”, \”text\”: \”Saandhy\”}, {\”type\”: \”text\”, \”text\”: \”Varun\”}]}]”,

“meta_data”: {

“source”: “PublicInterakt”,

“source_data”: {

“callback_data”: “some text here”

}

}

}

}

 

Webhook Body – message_api_failed:

(note – data sent in the “traits” object depends on the customer traits present in your Interakt account. The traits given in the example below corresponds to a test account)

{

“version”: “1.0”,

“timestamp”: “2022-06-03T05:56:10.699936”,

“type”: “message_api_failed”,

“data”: {

“customer”: {

“id”: “82a5b5bc-5509-4225-a9e9-bbe4c150516b”,

“channel_phone_number”: “919831”,

“traits”: {

“name”: “”,

“whatsapp_opted_in”: true

}

},

“message”: {

“id”: “80b4b1f1-dc39-46dc-a133-bf09a12c3d4e”,

“chat_message_type”: “PublicApiMessage”,

“channel_failure_reason”: “Recipient is not a valid WhatsApp user”,

“message_status”: “Failed”,

“received_at_utc”: “2022-06-03T05:56:10.502000”,

“delivered_at_utc”: null,

“seen_at_utc”: null,

“campaign_id”: null,

“is_template_message”: true,

“raw_template”: “{\”id\”: \”281a5a78-f2b2-46c9-b9bb-d620d3b2894c\”, \”created_at_utc\”: \”2022-03-30T07:04:04.078\”, \”modified_at_utc\”: \”2022-03-31T05:41:09.61\”, \”created_by_user_id\”: \”37088e03-3633-4aa4-b4d8-99edbc56d4fc\”, \”is_deleted\”: false, \”name\”: \”test_template_lp\”, \”language\”: \”en\”, \”category\”: \”ALERT_UPDATE\”, \”header_format\”: null, \”header\”: null, \”header_handle\”: null, \”header_handle_file_url\”: null, \”header_handle_file_name\”: null, \”header_text\”: null, \”body\”: \”Hi  {{1}} \\nWelcome to interakt, my name is  {{2}} . I hope your 14 day free trial was helpful. For any queries please reach to us.\”, \”body_text\”: \”[\\\”Clients\\\”, \\\”Sender\\\”]\”, \”footer\”: \”Team interakt\”, \”buttons\”: \”[{\\\”type\\\”: \\\”QUICK_REPLY\\\”, \\\”text\\\”: \\\”Thank you\\\”}, {\\\”type\\\”: \\\”QUICK_REPLY\\\”, \\\”text\\\”: \\\”What is qralink?\\\”}, {\\\”type\\\”: \\\”QUICK_REPLY\\\”, \\\”text\\\”: \\\”Speak to an agent\\\”}]\”, \”button_text\”: null, \”display_name\”: \”Test template\”, \”organization_id\”: \”ba4308f1-a506-44d2-a8c3-17380216cf91\”, \”approval_status\”: \”APPROVED\”, \”wa_template_id\”: \”3224400424546364\”, \”is_archived\”: false}”,

“channel_error_code”: “1013”,

“message_content_type”: “Template”,

“media_url”: null,

“message”: “[{\”type\”: \”body\”, \”parameters\”: [{\”type\”: \”text\”, \”text\”: \”Saandhy\”}, {\”type\”: \”text\”, \”text\”: \”Varun\”}]}]”,

“meta_data”: {

“source”: “PublicInterakt”,

“source_data”: {

“callback_data”: “some text here”

}

}

}

}

}

 

Webhook Body – message_received:

(note – data sent in the “traits” object depends on the customer traits present in your Interakt account. The traits given in the example below corresponds to a test account)

{

“version”: “1.0”,

“timestamp”: “2022-06-03T05:57:57.496889”,

“type”: “message_received”,

“data”: {

“customer”: {

“id”: “52918eb3-bd00-4331-a51d-c4dcffee48d6”,

“channel_phone_number”: “917003705584”,

“traits”: {

“name”: “SKGG”,

“amount”: 7000,

“total_orders_count”: 0,

“last_order_id”: null,

“last_order_name”: null,

“total_spent”: “0.00”,

“whatsapp_opted_in”: false,

“created_at”: “2021-06-23T06:46:11”,

“User Id”: “111”,

“email”: “[email protected]”,

}

},

“message”: {

“id”: “60076f05-da52-4dd1-b813-36223c1eded7”,

“chat_message_type”: “CustomerMessage”,

“channel_failure_reason”: null,

“message_status”: “Sent”,

“received_at_utc”: “2022-06-03T05:57:57.359000”,

“delivered_at_utc”: null,

“seen_at_utc”: null,

“campaign_id”: null,

“is_template_message”: false,

“raw_template”: null,

“channel_error_code”: null,

“message_content_type”: “Text”,

“media_url”: null,

“message”: “Thank you”,

“meta_data”: {}

}

}

}

Field & Description

type

Value will change depending on type of webhooks

Possible values:

1. For delivery status of templates (HSMs) sent via the above template sending APIs:

“message_api_sent”

“message_api_delivered”

“message_api_read”

“message_api_failed”

2. For delivery status of templates (HSMs) sent via campaigns on Interakt:

“message_campaign_sent”

“message_campaign_delivered”

“message_campaign_read”

“message_campaign_failed”

3. For incoming customer messages:

“message_received”

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 

Meta_data will contain any callbackData that might have been sent in the Template Send API call

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 :