Generic WhatsApp

Overview

CleverTap supports any WhatsApp provider via integration. CleverTap has recently made its WhatsApp API and standard callback formats accessible to WhatsApp service providers globally. Now, BSPs and customers are no longer required to rely on CleverTap to build the native WhatsApp integration. Instead, they can utilize these APIs to build the integration themselves independently.

📘

For CleverTap Customers

This feature is helpful to customers in the following ways:

  • Customers can build middleware between CleverTap and BSP and create their own endpoint. They can start using WhatsApp functionality in CleverTap with the BSP of their choice.
  • Customers can request their BSPs to build the CleverTap integration. This will allow customers to use the provider with CleverTap without any development.

📘

For WhatsApp BSPs

Providers who wish to pursue the partnership must follow the integration steps outlined in this document and send an email to [email protected] or [email protected] to include their names in the supported provider's list.

Supported Business Service Providers

The following Business Service Providers have built ready-to-use WhatsApp integration with CleverTap using CleverTap's generic integration.

You can use this generic API documentation for other providers to establish an integration between CleverTap and your business service provider. Alternatively, you can ask your provider to create a ready-to-use integration with CleverTap based on this documentation.

Partner Acceptance Criteria

Any WhatsApp partner can integrate with our open APIs. However, to become a supported partner with CleverTap, they must share the following with CleverTap:

  • Production API endpoint for sending Template and Freeform notifications via a single endpoint.
  • Production API credentials for two test accounts so the CleverTap team can test the integration.
  • Providers must provide dashboard access so the CleverTap team can create or share approved templates to test the campaign flow.
  • Providers must add CleverTap's callback URL in the test accounts. This helps CleverTap to check if the callbacks are received in the correct format.
  • Providers are required to publish a CleverTap integration guide in their user documentation. This will enable CleverTap to cross-reference the integration guide from our documents.
  • Partners must provide the contact details of their dedicated support and product team so that CleverTap can reach out to them in case of any issues.
  • Providers must support a minimum of 1500 concurrent API requests for each customer using the integration.
  • Partners must test integration with a few customers at scale.
  • Partners are responsible for maintaining the integration and proactively resolving any issues in the integration.

Test Partner Integration

  • Any partner can request access to the CleverTap sandbox account by writing to our partnership teams.
  • Partners must develop the middleware connecting CleverTap and their platform. This should enable partners to receive message payloads (both freeform and template messages) from CleverTap and send the Delivery Receipts (DLRs) and Incoming Message Opt-Out (IMO)Callback per the payload structure published by CleverTap.
  • Partners must save their messaging endpoints in the CleverTap sandbox account and configure CleverTap DLR and incoming message callback URLs at their end. This requires partners accept our endpoint validation payload and return a [200 OK]success API response.
  • Partners must save the template and send a test notification to ensure template messages are delivered to the end user.
  • Once the messaging endpoints and templates have been saved and tested successfully, Partner can create a WhatsApp campaign. The campaigns must target a large user base to scale-test the integration.
  • Once the Campaign has been published and completed successfully, check the WhatsApp campaign stats and ensure the following:
    • Sent, Delivered, Viewed, and Replied counts are captured successfully and match your platform count.
    • The campaign error count is per expectation, and errors are categorized correctly.
  • Test campaigns for different combinations of templates, such as media headers, footers, CTA and quick replies, and so on. This test is needed to ensure that all templates are working as expected.
  • Once the campaign has been tested successfully, go to conversations and check whether incoming responses are being shown correctly for all the users who are replying.
  • Respond to users from agent chat with different combinations ( text, media, location, documents, etc) and check whether the messages are being delivered to end users correctly.
  • Similarly to the previous step, send different types of messages from end-user devices on WhatsApp and check whether all messages are being captured and shown in CleverTap conversations.

Troubleshooting and FAQs for Generic Integration

These are some of the frequent issues that partners usually face when testing the integration.

Q. Provider setting is not being saved in the CleverTap dashboard

Whenever a provider setting is saved in the CleverTap dashboard, we send out a dummy messaging payload to verify that your endpoint is up and returning a success response. If we do not receive the expected success response within one second, we display an error showing the API request and response received from your endpoint.

Failed API response

Failed API response

Partners can use the request shown in the above pop-up in Postman to debug the issue further.

Q. Why am I unable to save the templates in the CleverTap dashboard?

CleverTap validates the Template that is saved in the dashboard by trying to deliver the Template message to a dummy number. This is required to ensure that customers don't save the incorrect templates and run into issues later when creating an actual campaign. To validate the Templates, we send the payload according to the template saved to the message endpoint which is saved in provider settings. If we receive the success response from the partner's endpoint within a second, we save the templates else, we display an error showing the request body and the API response.

Partners can use the request body in Postman to debug the issue in detail at their end.

Q. Why is the Template Message not being delivered to the end user ?

CleverTap is only responsible for sending the messaging payloads to the partners. Final delivery is owned by partners. Check the messaging payload received at the partner's end & ask them to resolve the issue. Having mentioned this, there could be many issues for messaging not delivering to end users, such as Template mismatch, Template deleted, or paused by META, and so on. To eliminate this issue as a possible cause, try different templates.
If none of the templates are being delivered, then this might happen because of integration issues. Partners can get the template payload by testing the templates and comparing the payload to find the mismatch and resolve the issue.

Q. Getting lots of generic miscellaneous errors in the campaign

Generic miscellaneous errors in the campaign come primarily for three reasons.

  • We received the error code 2004 in response to the messaging API request.
  • We received the error code 1009 in the status callback.
  • Messaging API requests timed out because we didn't receive the API success response within the defined timeout limits(one second). This usually happens when Partner's API endpoint cannot support the concurrency limit at which CleverTap sends the messaging requests.

Q. Why is the incoming response not recorded?

Two issues can cause this:

  • The phone number used to send the WhatsApp message has never been targeted via CleverTap's WhatsApp campaigns. Create a sample campaign for the number that sends incoming messages.
  • Incoming message callbacks are not coming in expected callback formats. Test with our sample payload.

Q. Why is the WhatsApp campaign not live?

Check that the account is not dormant. A dormant account is an account that does not receive any data for more than 15 days. Upload a sample event to resume using the account.

CleverTap marks an account as dormant if the account does not receive any data in 15 days. Campaigns will not go live in the dormant account because there is no data to target. To activate the account, partners must Upload a sample event.

Q. Why don't I have access to WhatsApp campaigns & conversations?

Enable the WhatsApp Connect Add-on and contact us at [email protected].

Q. Why don't I have access to campaigns creation?

Before creating a campaign to target users, you must have a few users already added to your CleverTap project. If there are no users added to your project, you will see the following screen when you try to access the campaigns:

Campaigns First Time Screen

Campaigns First Time Screen

There are multiple ways to add users to a CleverTap project.

  1. Via CSV upload: CSV uploads are easy way to add test users in a CleverTap Project. The following are the conditions for updating the flags:

    1. The objectId or identity must be the first column in the uploaded CSV file.

    2. The Phone column is mandatory, and phone numbers must have the country code. For example, +14155551234.

      Following is a table that displays the CSV columns:

      IdentityEmailPhoneMSG-whatsappMSG-sms
      [email protected]+14155551234TRUETRUE
      14155551235TRUETRUE
      14155551234+14155551234TRUETRUE
      234853412[email protected]+14155551234TRUETRUE
  2. Via User upload APIs CleverTap offers APIs that enable you to send the values of subscription flags programmatically. This method is useful for automating the subscription management process and integrating CleverTap with your existing systems. For more information, see upload user profiles. Following is an example of subscribing a user for WhatsApp messaging:

    Base URLs
    Here is an example base URL for an account in the India region:
    https://in1.api.clevertap.com/1/upload

    RegionAPI Endpoint
    Indiain1.api.clevertap.com
    Singaporesg1.api.clevertap.com
    United Statesus1.api.clevertap.com
    Indonesiaaps3.api.clevertap.com
    Middle East (UAE)mec1.api.clevertap.com
    Europe (default region)api.clevertap.com

    Headers

    The API headers are used while processing the API request. The following headers are required when you use CleverTap APIs:

    The X-CleverTap-Account-Id and X-CleverTap-Passcode authenticate the request.

    HeaderDescriptionTypeExample Value
    X-CleverTap-Account-IdYour CleverTap Account IDstring"X-CleverTap-Account-Id: ACCOUNT_ID"
    X-CleverTap-PasscodeYour CleverTap Account Passcode.string"X-CleverTap-Passcode: PASSCODE"
    Content-TypeRequest content-type is always set to application/json.string"Content-Type: application/json"

    Refer to the API Authentication to obtain the header values. To understand the common queries and concerns related to CleverTap APIs, refer to API FAQs.

    Sample JSON Payload

Following is a sample JSON payload to upload a user profile:

 {
  "d": [
    {
      "identity": "1189549",       
      "type": "profile",
      "profileData": {
        "Name": "Jack Montana",
        "Email": "[email protected]",
        "Phone": "+14155551234",
        "Gender": "M",
        "MSG-sms": true,
        "MSG-email":true,//called when email must be subscribed  
        "MSG-whatsapp": true,
       "Customer Type": "internal test user"
      }
    }
  ]
}

To know more about user upload APIs, refer to Upload User Profiles.

Integration Steps for CleverTap Customers using Generic Integration

CleverTap Customers must get endpoint and authentication details from their WhatsApp providers before starting the integrations.

📘

Note

  1. BSPs might have a dedicated endpoint (different from their standard endpoint) for CleverTap integration. Given this, you must get the API details for CleverTap integration from your provider.
  2. Please note that your WhatsApp providers are responsible for final message delivery and sending DLR and IMOs back to Clevertap. In case of any issue with these, You will have to ask your providers to resolve these issues.

This process involves the following steps:

1. Set Up WhatsApp Provider In CleverTap Dashboard

To configure the CleverTap dashboard:

  1. Navigate to Settings > Channels > WhatsApp> WhatsApp Connect from the CleverTap dashboard.
  2. Click + Add Provider and select Generic (Other) from the dropdown.
Add a WhatsApp Provider

Add a WhatsApp Provider

  1. Enter the following details:
FieldDescription
ProviderSelect Other (Generic) from the dropdown list.
NicknameEnter the nickname <10-digit phone number> for easy reference.
Mobile NumberEnter your phone number onboarded to WhatsApp API by your BSP.
Request TypeEnsure the Request Type is Post.
HTTP EndpointEnter HTTP Endpoint as provided by your BSP.
AuthenticationSelect Basic Authentication and enter the Username and Password for the user.
Delivery Report Callback URLThis URL is generated automatically. Share the URL with your BSP account manager. It is your BSP's responsibility to integrate this URL in their dashboard.
Inbound Message Callback URLThis URL is generated automatically. Share the URL with your BSP account manager. It is your BSP's responsibility to integrate this URL in their dashboard.
  1. (Optional) Select Mark this as default to make this service provider the default provider to send a WhatsApp message.
  2. (Optional) Select Set auto-reply for users not tracked on CleverTap to automatically reply to users who message on WhatsApp but are not tracked on the CleverTap dashboard.
  3. (Optional) You can set the Maximum Concurrent API requests anywhere between 30 to 1000 requests. Consider your requirements and the provider's limitations to define this value.
  4. Send a Test WhatsApp notification:
Send a Test WhatsApp Message

Send a Test WhatsApp Message

  1. Click Save to save the details.

2. Set Up CleverTap Callbacks with Provider

You can find the Callback URLs on the CleverTap dashboard under the Provider Setup page. Naviagte to Settings > Channels > WhatsApp .

To set up the CleverTap callbacks, share the following with your BSP account manager:

  • Delivery Report Callback URL
  • Inbound Message Callback URL
  • The WhatsApp phone number that will be used in CleverTap
Callback URLs

Callback URLs

Adding Message Template

To create WhatsApp campaigns, you must have pre-approved WhatsApp message templates saved in the CleverTap dashboard. To add the message templates:

  1. Navigate to Settings > Channels > WhatsApp > WhatsApp Connect >Provider Nickname from the CleverTap dashboard.
  2. Select the Templates option, and click +Template.

For more information, refer to adding a generic message template

4. Create a Campaign

To create a WhatsApp campaign using your BSP as the provider, refer to Create a WhatsApp Campaign for detailed instructions. If your users reply to notifications sent from CleverTap, incoming messages appear under the Conversation section of the dashboard. Businesses can reply to incoming messages by selecting the chat.

5. Creating a Journey

To create a WhatsApp journey using Infobip as the provider, refer to Create a WhatsApp Journey for detailed instructions.

Generic WhatsApp Integration Terminology

Messaging API Endpoint

BSPs are requested to create an endpoint where CleverTap can send the notification payload for campaigns and free-form messages. Customers must ask BSPs to share the API endpoint that can accept the CleverTap Payload to save the provider in CleverTap Dashboard.

API Authentication

The CleverTap's REST API supports basic authentication or custom headers for authentication. Providers must share these credentials with customers so that customers can save these credentials with an endpoint.

IMO(Incoming Message) & DLR (Status) Callbacks

CleverTap creates unique DLR callbacks for each customer. WhatsApp providers/customers have to configure the DLR and IMO callbacks at their end to send the Messages status and incoming messages to CleverTap. Status and incoming messages will only be captured if these are sent in CleverTap's expected payload structure.

Template Message Payload

CleverTap has published the Template Message payload formats that will be sent to messaging endpoint whenever a template message is sent from CleverTap Dashboard.

Freeform Message Payload

CleverTap has published the Freeform Messsage payload formats that will be sent to messaging endpoint whenever a freeform message is sent from CleverTap Dashboard.

Validation Payload

CleverTap sends a dummy message payload API endpoint, and credentials are configured in the CleverTap dashboard. This is required since at the time of saving provider in CleverTap doesn't have templates to test the credentials.

API Concurrency

By default, CleverTap hits the generic messaging API endpoint at 1500 concurrency ie. 1500 concurrent messaging requests are sent to messaging endpoint whenever a campaign is created in the CleverTap dashboard.

Messaging & Callback Payloads

Messaging API Specification

CleverTap sends outbound message payloads into two categories:

  • Templates messages: These are preapproved messages templates needed to initiate a conversation with conversation.
  • Freeform messages: These are free text messages that can be sent to end user in response to their incoming messages.

CleverTap sends either of the payloads depending on the type of message sent by the dashboard user. CleverTap sends theisTemplate key to helping BSPs understand whether this is a templatized message or a freeform message.

📘

Single Endpoint

CleverTap does not support different endpoints for different types of messages, so BSPs must provide just one endpoint to process freeform and template messages.

API Payload for Template Message

CleverTap sends this payload for sending the template message notification.
The outgoing template message payload can be broken down into the following three sections:

  • User & notification information
  • Template information includes template name, namespace, template language, and so on.
  • Content information

📘

Payload Essentials

The message payload is encoded into UTF-8 (Unicode Transformation Format) before being sent to the provider's endpoint.

Values with $$ ($$To,$$BusinessWabaNumber) are dynamic values and change for each request.

CleverTap does not support templates with contacts currently, so contact objects are not sent with payload.

CleverTap does not support Name, Address, or URL key in location object.

msg_id is a unique parameter for each message sent from CleverTap and must be present in callbacks sent by BSP to CleverTap.

{
    "payloadVersion": $$payloadVersion, // Sample: 0.1
    "to": "$$to", // support numbers with "+"" and without "+" (eg. 91 and +91)
    "wabaNumber": "$$businessWabaNumber", // WhatsApp mobile number saved in the Setup
    "isTemplate": true,
    "msgId": "i|campaignID|batchID|j|campaign_variant", // Notification identifier. This can be upto 60 characters long
    "template": {
        "namespace": "$$templateNamespace", // Template name saved in CleverTap Dashboard
        "languageCode": "$$BSPsr-language-and-locale-code"
    },
    "components": [
        { // available only in case of templates with text headers
            "type": "header",
            "header": {
                "type": "text",
                "text": {
                    "text": "$headertext",
                    "parameters": [
                        {
                            "type": "text",
                            "text": "$$PlaceholderText1"
                        }
                    ]
                }
            }
        },
        { // available only in case of templates with Video headers
            "type": "header",
            "header": {
                "type": "video",
                "video": {
                    "mediaURL": "$$mediaUrl" //URL to media File.
                }
            }
        },
        { // available only in case of templates with image headers
            "type": "header",
            "header": {
                "type": "image",
                "image": {
                    "mediaURL": "$$mediaUrl"
                }
            }
        },
        { // available only in case of templates with document headers
            "type": "header",
            "header": {
                "type": "file",
                "file": {
                    "mediaURL": "$$mediaUrl",
                    "filename": "$$filename"
                }
            }
        },
        { // optional location header
            "type": "header",
            "header": {
                "type": "location",
                "location": {
                    "longitude": "$$longitude",
                    "latitude": "$$latitude",
                    "name": "$$LocationName",
                    "address": "$$LocationAddress"
                }
            }
        },
        // Limited-time offer component - available only if user selects LTO template
        {
            "type": "limited_time_offer",
            "text": "$$LTO_Offer_Title",
        "parameters": [
                {
                    "type": "limited_time_offer",
                    "limited_time_offer": {
                        "expiration_time_ms": $$EXPIRATION_TIME // Offer Exipry Timestamp in MS in Epoch.
                    }
                }
            ]
        },
        {
            "type": "body",
            "body": {
                "text": "$$Body",
                "parameters": [
                    {
                        "type": "text",
                        "text": "$$PlaceholderText1"
                    },
                    {
                        "type": "text",
                        "text": "$$PlaceholderText2"
                    }
                ]
            }
        },
        {
            "type": "carousel",
            "cards": [
                {
                    "components": [
                        {
                            "type": "header",
                            "header": {
                                "type": "image/video",
                                "image": {
                                    "mediaURL": "$$MediaURL"
                                }
                            }
                        },
                        {
                            "type": "body",
                            "body": {
                                "text": "$$text",
                                "parameters": [
                                    {
                                        "type": "text",
                                        "text": "$$PlaceholderText1"
                                    },
                                    {
                                        "type": "text",
                                        "text": "$$PlaceholderText1"
                                    }
                                ]
                            }
                        },
                        {
                            "type": "button",
                            "index": $$buttonPosition,
                            "buttonText": "$$buttonText",
                            "subType": "dynamicUrl",
                            "parameters": [
                                {
                                    "type": "text",
                                    "text": "$$URLsuffix"
                                }
                            ]
                        },
                        {
                            "type": "button",
                            "index": $$buttonPosition,
                            "buttonText": "$$buttonText",
                            "subType": "dynamicUrl",
                            "parameters": [
                                {
                                    "type": "text",
                                    "text": "$$URLsuffix"
                                }
                            ]
                        }
                    ]
                },
                {
                    "components": [
                        {
                            "type": "header",
                            "header": {
                                "type": "image/video",
                                "image": {
                                    "mediaURL": "$$MediaURL"
                                }
                            }
                        },
                        {
                            "type": "body",
                            "body": {
                                "text": "$$text",
                                "parameters": [
                                    {
                                        "type": "text",
                                        "text": "$$PlaceholderText1"
                                    },
                                    {
                                        "type": "text",
                                        "text": "$$PlaceholderText1"
                                    }
                                ]
                            }
                        },
                        {
                            "type": "button",
                            "index": $$buttonPosition,
                            "buttonText": "$$buttonText",
                            "subType": "dynamicUrl",
                            "parameters": [
                                {
                                    "type": "text",
                                    "text": "$$URLsuffix"
                                }
                            ]
                        },
                        {
                            "type": "button",
                            "index": $$buttonPosition,
                            "buttonText": "$$buttonText",
                            "subType": "dynamicUrl",
                            "parameters": [
                                {
                                    "type": "text",
                                    "text": "$$URLsuffix"
                                }
                            ]
                        }
                    ]
                }
            ]
        }
        { // available only in case of templates with footers
            "type": "footer",
            "footer": "$$footertext"
        },
        // new copy code button for LTO 
        {
            "type": "button",
            "buttonText": "Copy offer code",
            "sub_type": "copy_code",
            "index": $$buttonPosition,
            "parameters": [
                {
                    "type": "coupon_code",
                    "coupon_code": "$$OfferCode"
                }
            ]
        },
        { // available only in case of templates with Dynamic CTA buttons
            "type": "button",
            "index": $$buttonPosition,
            "subType": "dynamicUrl",
            "buttonText": "$$cta_text",
            "parameters": [
                {
                    "type": "text",
                    "text": "$$URLsuffix" // Only the suffix of the URL
                }
            ]
        },
        { // available only in case of templates with Static CTA buttons
            "type": "button",
            "index": $$Buttonposition,
            "buttonText": "cta_text",
            "subType": "staticUrl",
            "parameters": [
                {
                    "type": "text",
                    "text": "$$ButtonURL"
                }
            ]
        },
        { // available only in case of templates with quick reply buttons
            "type": "button",
            "index": $$buttonPosition,
            "subType": "quickReply",
            "buttonText": "$$cta_text",
            "parameters": [
                {
                    "type": "payload",
                    "payload": "$$buttonPayload"
                }
            ]
        },
        { // available only in case of templates with Callphone CTA
            "type": "button",
            "index": $$buttonPosition,
            "subType": "callPhone",
            "buttonText": "$$cta_text",
            "parameters": [
                {
                    "type": "text",
                    "text": "$$phonenumber"
                }
            ]
        },
        {
            "customProps": [
                {
                    "key1": "Value1"
                },
                {
                    "Key2": "Value2"
                }
            ]
        }
    ]
}

Payload Description for Template Message

ParameterDescriptionData TypeExample Values
payloadVersionVersion of the payload being used.Float0.1
toRecipient's phone numberString"919876543210", "+919876543210"
wabaNumberWhatsApp Business Account numberString"1234567890"
isTemplateIndicates if the message is a templateBooleanTRUE
msgIdUnique identifier for the messageString"i|campaignID|batchID|j|campaign_variant"
template.namespaceIdentifier for the template in CleverTap DashboardString"my_template_namespace"
template.languageCodeLanguage and locale code for the templateString"en_US"
components.typeType of component, like header, body, button, and so on.String"header", "body", "button"
header.typeType of header like text, video, image, file, locationString"text", "video", "image", "file", "location"
header.text.textText content for text headerString"Hello, World!"
header.video.mediaURLURL to the video media fileStringhttp://example.com/video.mp4
header.image.mediaURLURL to the image media fileStringhttp://example.com/image.jpg
header.file.mediaURLURL to the file mediaStringhttp://example.com/document.pdf
header.file.filenameFilename for the fileString"document.pdf"
header.location.longitudeLongitude for location headerString"74.0060"
header.location.latitudeLatitude for location headerString"40.7128"
header.location.nameName for the locationString"Central Park"
header.location.addressAddress for the locationString"New York, NY 10024"
body.textBody text of the messageString"Your order is ready for pickup."
footerFooter text for the messageString"Thank you for choosing us!"
button.subTypeSpecific type of button like dynamicUrl, staticUrl, quickReply, callPhoneString"dynamicUrl", "staticUrl"
button.buttonTextText displayed on the buttonString"Click Here", "Copy Offer Code"
button.indexPosition of the buttonInteger1, 2
button.parametersParameters for the button, like URL suffix, phone number, and so on.ArrayDepends on button.type
customPropsCustom key-value pairs defined at the time of creating campaignsArray[
{
"key1": "Value1"
},
{
"Key2": "Value2"
}
]

Payload Samples for Template Message


{
"payloadVersion":0.1,
"to": "919999999999",
"wabaNumber": "91999999XXXX",
"isTemplate": true,
"msgId": "25596363|1639561857|20220227|25596363",
"template": {
             "namespace": "Namespace:sample",
             "languageCode":"en(uk)"
                         
                         },
"components": [

{
 "type": "body",
 "body": {
 "text":"This is sample body",
  "parameters": [
               {
                  "type": "text",
                   "text": "Sample"
               }
           ]}},
  {
  "type": "footer",
  "footertext":"this is footer"
        
       }
]}
{
    "payloadVersion": 0.1,
    "to": "919999999999",
    "wabaNumber": "919999999999",
    "isTemplate": true,
    "msgId": "i|campaignID|batchID|j",
    "template": {
        "namespace": "Namespace:sample",
        "languageCode": "en"
    },
    "components": [
        {
            "type": "header",
            "header": {
                "type": "image",
                "image": {
                    "mediaURL": "httpa://www.example.com/image.png"
                }
            }
        },
        {
            "type": "body",
            "body": {
                "text": "This is sample body",
                "parameters": [
                    {
                        "type": "text",
                        "text": "sample"
                    }
                ]
            }
        },
        {
            "type": "button",
            "index": 0,
            "subType": "dynamicUrl",
            "buttonText": "Sample CTA TEXT",
            "parameters": [
                {
                    "type": "text",
                    "text": "https://www.example.com"
                }
            ]
        }
    ]
}
{
    "payloadVersion": 0.1,
    "to": "+9199XXXXXXX", 
    "wabaNumber": "+91999999999",
     "isTemplate": true,
    "msgId": "1|2|3|4|5",
    "template": {
        "namespace": "Sample_Template",// Template name saved in CleverTap Dashboard
        "languageCode": "en(UK)"
    },
    "components": [
        
        {
            "type": "body",
            "body": {
                "text": "Hey User, This is Body",
                "parameters": [
                    {
                        "type": "text",
                        "text": "user"
                    }
                ]
            }
        }
    ]
}
{
    "payloadVersion": 0.1,
    "to": "+9199XXXXXXX", 
    "wabaNumber": "+91999999999",
     "isTemplate": true,
    "msgId": "1|2|3|4|5",
    "template": {
        "namespace": "Sample_Template",// Template name saved in CleverTap Dashboard
        "languageCode": "en(UK)"
    },
    "components": [
    {
    "type": "header",
    "header": {
                "type": "image",
                "image": {
                    "mediaURL": "example.com/image.png"
                }
            }
        
        {
            "type": "body",
            "body": {
                "text": "Hey User, This is Body",
                "parameters": [
                    {
                        "type": "text",
                        "text": "user" 
                    }
                ]
            }
        },
        { 
            "type": "button",
            "index": 0,
            "subType": "dynamicUrl",
            "buttonText": "Check-out cart",
            "parameters": [
                {
                    "type": "text",
                    "text": "cart"
                }
            ]
        },
        {
            "type": "button",
            "index": 0,
            "subType": "callPhone",
            "buttonText": "Call support",
            "parameters": [
                {
                    "type": "text",
                    "text": "+91994876856"
                }
            ]
        }
    ]
}
{
  "payloadVersion": 0.1,
  "wabaNumber": "919999999999",
  "to": "+919999999244",
  "isTemplate": true,
  "template": {
    "namespace": "Test_template",
    "languageCode": "en"
  },
  "components": [
    {
      "type": "header",
      "header": {
        "type": "image",
        "image": {
          "mediaURL": "https://hatrabbits.com/wp-content/uploads/2017/01/random.jpg"
        }
      }
    },
    {
      "type": "body",
      "body": {
        "text": "Hey 0, Welcome to CleverTap.",
        "parameters": [
          {
            "type": "text",
            "text": "0"
          }
        ]
      }
    },
    {
      "type": "limited_time_offer",
      "text": "Buy 1 Get 1 Free",
      "parameters": [
        {
          "type": "limited_time_offer",
          "limited_time_offer": {
            "expiration_time_ms": 1712081380237
          }
        }
      ]
    },
    {
      "type": "button",
      "index": 0,
      "buttonText": "Copy offer code",
      "subType": "copy_code",
      "parameters": [
        {
          "type": "coupon_code",
          "coupon_code": "SAMPLECODE"
        }
      ]
    },
    {
      "type": "button",
      "index": 1,
      "buttonText": "Check Out Now",
      "subType": "dynamicUrl",
      "parameters": [
        {
          "type": "text",
          "text": "0"
        }
      ]
    },
    {
      "type": "button",
      "index": 2,
      "buttonText": "Call support",
      "subType": "callPhone",
      "parameters": [
        {
          "type": "text",
          "text": "+91999999999"
        }
      ]
    },
    {
      "type": "button",
      "index": 3,
      "buttonText": "Yes",
      "subType": "quickReply"
    },
    {
      "type": "button",
      "index": 4,
      "buttonText": "No",
      "subType": "quickReply"
    },
    {
      "type": "button",
      "index": 5,
      "buttonText": "Show More",
      "subType": "quickReply"
    }
  ],
  "msgId": "0|0|0|0"
}
{
  "payloadVersion": 0.1,
  "wabaNumber": "9407178156",
  "to": "+9198574656",
  "isTemplate": true,
  "template": {
    "namespace": "Test_Template",
    "languageCode": "en"
  },
  "components": [
    {
      "type": "header",
      "header": {
        "type": "file",
        "file": {
          "mediaURL": "http://www.clevertap.com/~offer/pdf/new_offer.pdf",
          "filename": "New_offer"
        }
      }
    },
    {
      "type": "body",
      "body": {
        "text": "Hey 0, This is a test template",
        "parameters": [
          {
            "type": "text",
            "text": "0"
          }
        ]
      }
    },
    {
      "type": "footer",
      "footer": "Please reply \"stop\" to optout"
    },
    {
      "type": "button",
      "index": 0,
      "buttonText": "Copy offer code",
      "subType": "copy_code",
      "parameters": [
        {
          "type": "coupon_code",
          "coupon_code": "SAMPLECODE"
        }
      ]
    },
    {
      "type": "button",
      "index": 1,
      "buttonText": "Visit App",
      "subType": "dynamicUrl",
      "parameters": [
        {
          "type": "text",
          "text": "https://www.clevertap.com/{{1}}"
        }
      ]
    },
    {
      "type": "button",
      "index": 2,
      "buttonText": "Check Out Now",
      "subType": "staticUrl",
      "parameters": [
        {
          "type": "text",
          "text": "https://www.clevertap.com"
        }
      ]
    },
    {
      "type": "button",
      "index": 3,
      "buttonText": "Show more",
      "subType": "quickReply"
    },
    {
      "type": "button",
      "index": 4,
      "buttonText": "Not Now",
      "subType": "quickReply"
    },
    {
      "type": "button",
      "index": 5,
      "buttonText": "STOP",
      "subType": "quickReply"
    }
  ],
  "msgId": "0|0|0|0"
}
{
    "payloadVersion": 0.1,
    "wabaNumber": "+919930079420",
    "to": "+91999645754",
    "isTemplate": true,
    "template": {
      "namespace": "carousel_test_1",
      "languageCode": "en"
    },
    "components": [
      {
        "type": "body",
        "body": {
          "text": "hello main body 0",
          "parameters": [
            {
              "type": "text",
              "text": "0"
            }
          ]
        }
      },
      {
        "type": "carousel",
        "cards": [
          {
            "components": [
              {
                "type": "header",
                "header": {
                  "type": "image",
                  "image": {
                    "mediaURL": "https://hatrabbits.com/wp-content/uploads/2017/01/random.jpg"
                  }
                }
              },
              {
                "type": "body",
                "body": {
                  "text": "Hello card1 0, how are you?? 1",
                  "parameters": [
                    {
                      "type": "text",
                      "text": "0"
                    },
                    {
                      "type": "text",
                      "text": "1"
                    }
                  ]
                }
              },
              {
                "type": "button",
                "index": 0,
                "buttonText": "Shop Now",
                "subType": "dynamicUrl",
                "parameters": [
                  {
                    "type": "text",
                    "text": "wa/5xu5auQ"
                  }
                ]
              },
              {
                "type": "button",
                "index": 1,
                "buttonText": "Dynamic",
                "subType": "dynamicUrl",
                "parameters": [
                  {
                    "type": "text",
                    "text": "0"
                  }
                ]
              }
            ]
          },
          {
            "components": [
              {
                "type": "header",
                "header": {
                  "type": "image",
                  "image": {
                    "mediaURL": "https://hatrabbits.com/wp-content/uploads/2017/01/random.jpg"
                  }
                }
              },
              {
                "type": "body",
                "body": {
                  "text": "Hello card2 0, how are you?? 1",
                  "parameters": [
                    {
                      "type": "text",
                      "text": "0"
                    },
                    {
                      "type": "text",
                      "text": "1"
                    }
                  ]
                }
              },
              {
                "type": "button",
                "index": 0,
                "buttonText": "Shop Now",
                "subType": "staticUrl",
                "parameters": [
                  {
                    "type": "text",
                    "text": "https://www.clevertap.com"
                  }
                ]
              },
              {
                "type": "button",
                "index": 1,
                "buttonText": "Dynamic",
                "subType": "dynamicUrl",
                "parameters": [
                  {
                    "type": "text",
                    "text": "0"
                  }
                ]
              }
            ]
          }
        ]
      }
    ],
    "msgId": "0|0|0|0"
  }
{
  "payloadVersion": 0.1,
  "wabaNumber": "9407178156",
  "to": "7658734869",
  "isTemplate": true,
  "template": {
    "namespace": "sample_template",
    "languageCode": "en"
  },
  "components": [
    {
      "type": "header",
      "header": {
        "type": "file",
        "file": {
          "mediaURL": "https://d1510fwumr3byl.cloudfront.net/dist/1400000001/i/f90291d5c12140b1b36a9047c407ad75.pdf?v=1724156050",
          "filename": "OctoberCM2"
        }
      }
    },
    {
      "type": "body",
      "body": {
        "text": "Hey User, This test templates",
        "parameters": [
          {
            "type": "text",
            "text": "User"
          }
        ]
      }
    },
    {
      "type": "footer",
      "footer": "Please reply \"stop\" to optout"
    },
    {
      "type": "button",
      "index": 0,
      "buttonText": "Copy offer code",
      "subType": "copy_code",
      "parameters": [
        {
          "type": "coupon_code",
          "coupon_code": "BLACKFRIDAY20"
        }
      ]
    },
    {
      "type": "button",
      "index": 1,
      "buttonText": "Visit App",
      "subType": "staticUrl",
      "parameters": [
        {
          "type": "text",
          "text": "https://www.clevertap.com"
        }
      ]
    },
    {
      "type": "button",
      "index": 2,
      "buttonText": "Check Out Now",
      "subType": "staticUrl",
      "parameters": [
        {
          "type": "text",
          "text": "https://www.clevertap.com"
        }
      ]
    },
    {
      "type": "button",
      "index": 3,
      "buttonText": "Show more",
      "subType": "quickReply"
    },
    {
      "type": "button",
      "index": 4,
      "buttonText": "Not Now",
      "subType": "quickReply"
    },
    {
      "type": "button",
      "index": 5,
      "buttonText": "STOP",
      "subType": "quickReply"
    },
    {
      "customProps": [
        {
          "Key1": "$$Value1"
        },
        {
          "key2": "$$Value2"
        }
      ]
    }
  ],
  "msgId": "0|0|0|0"
}

API Payload for Freeform Message

CleverTap will send this payload for sending the Freeform message notification.
Freeform message API payload has the user information about the targetted users, media URLs, and text.

📘

Payload Essentials

  • Values with $$ (for example $$To,$$BusinessWabaNumber) are dynamic values and change for each request.

    • Dynamic Reply Button, interactive lists, and product catalog, contacts, and locations are not currently supported in the CleverTap platform. This is why these objects are not mentioned in the payload.

    • CleverTap does not support Name, Address, or URL key in location object.

    • msg_id is a unique parameter for each message sent from CleverTap and must be present in callbacks sent by BSP to CleverTap.

{
    "payloadVersion": $$payloadversion,
    "to": "$$To",
    "wabaNumber": "$$BusinessWabaNumber",
    "msgId": "i|campaignID|batchID|j",
    "type": "text/audio/file/image/location/video",
    "isTemplate": false,
    //Optional 
    "audio": {
        "mediaURL": "$$mediaUrl"
    },
    //OR
    "file": {
        "mediaURL": "$$mediaUrl",
        "caption": "$$body",
        "filename": "$$filename"
    },
    //OR
    "image": {
        "mediaURL": "$$mediaUrl",
        "caption": "$$body"
    },
    //OR
    "text": {
        "body": "$$Body"
    },
    //OR
    "video": {
        "mediaURL": "$$mediaUrl",
        "caption": "$$body"
    }
}

Payload Description for Freeform Message

ParameterDescriptionExample Value
toTargeted user’s phone number9199XXXXXXXX
"payloadversion"Version of the payload being sent to CleverTap0.1
wabaNumberBusiness’s WABA number9189XXXXXXXX
isTemplateUsed to highlight the whether the payload being sent is for templates or freeformtrue/false
msgIdUnique identifier for message being sent and expected to be present in callback payloads25596363|1639561857|20220227|25596363
audio.mediaURLMedia URL of the filewww.example.com/audio.mp3
file.mediaURLMedia URL of the filewww.example.com/document.pdf
file.captionMessage body“This is message body”
file.filenameTitle of the file“sample_document.pdf”
image.mediaURLMedia URL of the filewww.example.com/image.png
image.captionMessage body“This is message body”
video.mediaURLMedia URL of the filewww.example.com/video.mp4
video.captionMessage body“This is message body”

Payload Samples For Freeform Message

{
"payloadVersion":0.1,
"to": "919999999999",
“msg_id”:"25596363|1639561857|20220227|25596363",
"wabaNumber": "91999999XXXX",
"type": "audio",
"isTemplate": false,
"audio": {
        "mediaURL": "www.example.com/audio.mp3"
        }
        }
{
"payloadVersion":0.1,
"to": "919999999999",
"wabaNumber": "91999999XXXX",
“msg_id”:"25596363|1639561857|20220227|25596363",
"type": "image",
"isTemplate": false,
"image": {"mediaURL": "www.example.com/image.png","caption": "This is body"} }
{
"payloadVersion":0.1,
"to": "919999999999",
"wabaNumber": "91999999XXXX",
“msg_id”:"25596363|1639561857|20220227|25596363",
"type": "file",
"isTemplate": false,
"file": {
          "mediaURL": "www.example.com/document.pdf",
           "caption": "This is body",
          "filename": "sample.pdf"
          } }

Expected API Response

Validation Payload

CleverTap sends the following payload to validate the Messaging endpoint and API credentials saved in the dashboard. We expect success response within a second to save the endpoint.

{
  "payloadVersion": 0.1,
  "wabaNumber": "$$Mobilenumber",
  "to": "+919999999999",
  "isTemplate": true,
  "template": {
    "namespace": "whatsapp:hsm:technology:generic:verify",
    "languageCode": "en"
  },
  "components": [
    {
      "type": "body",
      "body": {
        "text": "1 code: 2.Valid for 3 minutes.",
        "parameters": [
          {
            "type": "text",
            "text": "1"
          },
          {
            "type": "text",
            "text": "2"
          },
          {
            "type": "text",
            "text": "3"
          }
        ]
      }
    }
  ],
  "msgId": "0|0|0|0"
}

If the format is incorrect, we throw an error showing the API request and response we received from the endpoint.

Error Objects

CleverTap expects partners to return any of the following responses depending on whether the request was successful. CleverTap will read the response body if the API request status code is 200 OK, so notification processing-related errors and codes can be sent in the response body. Read the following for expected error codes:

📘

Error Object

The error object for the following error code needs to be specified only if there are errors in the send message API request:

  • 2000 → Invalid credentials
  • 2001 → Invalid template parameters
  • 2002 → Invalid phone number
  • 2003 → Phone number not subscribed
  • 2004 → Other

HTTPS Codes

{ 
  "status": "success | failure",
}
{ 
  "status": "failure",
   "error" : {
              "code" : 2000,
              "message" : "Invalid Credentials"
              }
}
{
"status": "failure",
"error" : {
"message" : "Unable to process the request"
          }
}
{ "message" : "Too many requests to process"}
{ "message" : "Bad Request"}

WhatsApp Callbacks

CleverTap automatically creates unique callback URLs for each customer. These callback URLs are available under the Provider setup section. BSPs are expected to add these callbacks at their end and forward the incoming messages to CleverTap’s callback URL in the specified format. CleverTap creates separate callback URLs for message status and incoming messages. Both these callbacks must be configured at the BSP's end.

Callback Authentication

CleverTap creates unique callback URLs for each customer and does not need any authentication. CleverTap accepts the callbacks if the callbacks are sent in the expected format.

Incoming Message Callbacks

BSPs must add CleverTap's incoming message callback URL at their end and forward the incoming message in the following format.

{
    "payloadVersion": $$payloadversion,
    "from": "$$phone",
    "wabaNumber": "$$BusinessWabaNumber",
    "timestamp": "$$receivedTS",
    "type": "text/location/image/video/voice/file/button",
    //Optional(Needs to be sent if user replies to previously sent message)
    "context": {
        "id": "$$msg_ID"
    },
    //Optional (will be needed if message received is text)
    "text": {
        "body": "$$incomingMessage"
    },
    //Optional (will be needed if message received is loaction)
    "location": {
        "address": "$$address",
        "latitude": "$$latitude",
        "longitude": "$$latitude",
        "name": "$$addressTitle",
        "url": "$$addressUrls"
    },
    //Optional (will be needed if message received is image)
    "image": {
        "mediaURL": "$$mediaUrl",
        "mimeType": "$$mediaMimeType", // image/jpeg
        "caption": "$$incomingmessage"
    },
    //Optional (will be needed if message received is file)
    "file": {
        "mediaURL": "$$mediaUrl",
        "mimeType": "$$mediaMimeType",
        "caption": "$$incomingmessage"
    },
    //Optional (will be needed if message received is audio)
    "audio": {
        "mediaURL": "$$mediaUrl",
        "mimeType": "$$mediaMimeType"
    },
    //Optional (will be needed if message received is video)
    "video": {
        "mediaURL": "$$mediaUrl",
        "mimeType": "$$mediaMimeType",
        "caption": "$$incomingmessage"
    },
    //Optional (will be needed if the message received is video)
    "button": {
        "payload": "$$buttonPayload", // same as outgoing  message
        "text": "$$buttonText"
    }
}

Payload Description for Incoming Message Callbacks

ParameterDescriptionExample Value
fromSource number for incoming message“9199XXXXXXXX”
payloadVersionversion of the callback payload being sent to CleverTap“0.1“
wabaNumberDestination business WABA number to which message was sent“9199XXXXXXXX”
timestampTimestamp when the message was sent“1647441774”
typeType of incoming message“text/audio/video/image”
context.idMsg_id of the message to which the user has responded25596363|1639561857|20220227|25596363
text.bodyText received from end user“Hey, This is message”
location.lattitudeLatitude of the location shared2.457476548
location.LongitudeLongitude of the location shared1.565867657
location.nameName of the location sharedJoe’s House
location.addressAddress of the location shared102, Parker street, USA
location.urlAddress URLwww.example.com
image.mediaURLMedia File URLwww.example.com/image.png
image.mimetypeMedia file mime type.png/.jpeg
image.captionImage caption“This is caption”
file.mediaURLMedia File URLwww.example.com/file.pdf
file.mimetypeMedia file mime type.pdf
file.captionImage caption“This is caption”
audio.mediaURLMedia File URLwww.example.com/audio.mp3
video.mimetypeMedia file mime type.mp3
video.mediaURLMedia File URLwww.example.com/image.png
video.mimetypeMedia file mime type.mp4
video.captionImage caption“This is caption”

Sample Payload for Incoming Message Callbacks

{
              "payloadVersion":"0.1",
              "from": "919999999999",
              "wabaNumber": "9199999998888",
              "timestamp": "1647441774",
              "type": "file",
              "context": {
              "id": "25596363|1639561857|20220227|25596363"
              },
"document": {
            "mediaURL": "www.example.com/document.pdf",
             "caption": "This is body",
             "mimeType": ".pdf"
          } 
}
{
"payloadversion":"0.1",
"from": "919999999999",
"wabaNumber": "9199999998888",
"timestamp": "1647441774",
"type": "location",
"context": {
              "id": "25596363|1639561857|20220227|25596363"
              },
"location": {
            "address": "107, baker street",
            "latitude": "2.457476548",
            "longitude": "2.457476548",
            "name": "Johns office", //optional
            "url": "www.johnsoffice.com" // optional
            }
}

Message Status Callbacks

BSPs must add CleverTap's message status callback URL at their end and forward the message statuses (DLR callback) in the following format. CleverTap uses these callbacks to populate the campaign statistics.

{
    "payloadVersion": $$paypoadVersion,
    "statuses": [
        {
            "msgId": "$$customMessageID",
            "status": "sent/delivered/read/failed",
            "timestamp": "$$timestamp", //Event timestamp
            "error": {
                "code": "$$errorcode",
                "title": "$$errordescription"
            }
        }
    ]
}

Payload Description for Message Status Callbacks

ParameterDescriptionExample Value
payloadversionVersion of the payload being sent to CleverTap0.1
statuses[X].statusNotification status“sent/delivered/read/failed”
statuses[X].timestampTimestamp of the event“1647441774”
statuses[X].msgIdUnique identifier for message being sent and expected to be present in callback payloads25596363|1639561857|20220227|25596363
statuses[X].error.codeFailure Error code1001
statuses[X].error.titleDescription of errorMessage specified does not match with any template.

Sample Payload for Message Status Callbacks

{
"payloadVersion":"0.1",
"statuses": [{
               "msgId": "25596363|1639561857|20220227|25596363", // same as outbound message ID
               "status": "delivered",
               "timestamp": "1647441774", //Event timestamp
               }]
               }
{"payloadVersion":"0.1",
"statuses": [{
               "msgId": "25596363|1639561857|20220227|25596363",
               "status": "failed",
               "timestamp": "1647441774", //Event timestamp
               "error": {
               "code": 1004,
               "title": "Invalid phone number."
               }}]

}

Callback Error Codes

🚧

Callback Error Codes

Listed below are the expected callback error codes:

  • 1000 → Invalid credentials
  • 1001 → Invalid template parameters
  • 1002 → Invalid phone number
  • 1003 → The phone number is no longer active
  • 1004 → Too many send requests to phone numbers
  • 1005 → The phone number is temporarily unavailable or not in the provider network
  • 1006 → Phone number is blacklisted
  • 1007 → User device can’t receive the message
  • 1008 → This message is sent outside of the WhatsApp chat window
  • 1009 → Other

Creating/Uploading User Base

You can upload a CSV file to upload a set of internal users by going to Settings > CSV uploads. The following is the sample CSV format for uploading user data.

IdentityNameEmailPhoneGenderMSG-WhatsAppUpload Name
[email protected]John Doe+9199*420MTRUESample Upload

Accepted Message Formats

CleverTap currently has limitations on the types of WhatsApp messages supported on the dashboard. We are working on adding support for the new message types as soon as possible but for the time being, only the following message types are supported.

Freeform Messages
This message type supports the following format:

  • Simple text
  • Audio
  • Video
  • Images
  • Document

Template messages
The elements of the Template message include a header, footer, simple text, and buttons.
The header section supports the following formats:

  • Text
  • Image
  • Videos
  • Locations
  • Audios
  • Documents

FAQs

Q. My WhatsApp provider has shared the API credentials with me. Can I save the provider in the CleverTap dashboard and start creating WhatsApp campaigns?

Ans: Ensure that your WhatsApp service provider is there in the list of integrated partners. If yes, ensure that you are using the custom API endpoint that your partner has created for CleverTap integration.