Send WhatsApp Business API with Different Types of Template
WhatsApp Business API is designed with powerful messaging experiences to meet your business needs. Beyond the inbound message from multiple WhatsApp channels that you can handle with Qiscus Omnichannel, don’t have to worry about losing any chances to have more interactions with your customers by sending outbound messages. Have your own flow? Just send it through API! In this article, we give you some API samples with various templates.
We assume you have decided on your use cases (OTP, account update, ticket information, etc.) and have already submitted the outbound message template through the Qiscus Omnichannel dashboard.
Before we start, here are what you need:
Read the documentation here
Qiscus App ID and Qiscus Secret Key
Channel ID, Template Name, Language, & Namespace from your approved template
Ensure the components that you have submitted in the template. The template can handle these components:
Header (optional):
Text with 1 variable
Media (Image/Video/Document) variable
Body:
Text with up to 15 variable
Footer (optional):
Text
Buttons (optional):
Call To Action
Call Phone Number
Visit Website
Static
Dynamic with 1 variable
Quick Reply
Up to 3 text buttons
Code Delivery (only for Authentication category)
Copy Code
Auto-Fill
Phone number
Must include country code without + (e.g. 62xxxxx) and valid as a WhatsApp account.Additional notes
The maximum template content including variables:
Header 60 characters
Body 1024 characters
Make sure there is no unknown character like this to prevent errors
�, â, €, ¬, â, œ, “, etc.
1. Body only, no variable
This example is using a simple template that only has content in the body section, without headers, buttons, or variables. Below is the API request.
Example template:
Request:
curl --location -g --request POST 'https://omnichannel.qiscus.com/whatsapp/v1/{{app_id}}/{{channel_id}}/messages'
--header 'Qiscus-App-Id: {{app_id}}'
--header 'Qiscus-Secret-Key: {{secret_key}}'
--header 'Content-Type: application/json'
--data-raw '{
"to": "{{phone_number}}",
"type": "template",
"template": {
"namespace": "{{namespace}}",
"name": "noparam",
"language": {
"policy": "deterministic",
"code": "en"
}
}
}'
Note: The language code will be different for each language. Please refer here to see the codes.
Because this template only contains a body without variables, the text will be the same as you have submitted in the template.
Result:
2. Body with multiple text variables
The body is possible to handle up to 15 text variables. When you send with API, it will look like this.
Example template:
Request:
curl --location -g --request POST 'https://omnichannel.qiscus.com/whatsapp/v1/{{app_id}}/{{channel_id}}/messages'
--header 'Qiscus-App-Id: {{app_id}}'
--header 'Qiscus-Secret-Key: {{secret_key}}'
--header 'Content-Type: application/json'
--data-raw '{
"to": "{{phone_number}}",
"type": "template",
"template": {
"namespace": "{{namespace}}",
"name": "90daysfreetrial3",
"language": {
"policy": "deterministic",
"code": "id"
},
"components": [
{
"type" : "body",
"parameters": [
{
"type": "text",
"text": "{{body_var1}}"
},
{
"type": "text",
"text": "{{body_var2}}"
}
]
}
]
}
}'
Result:
3. Header with a text variable
Unlike the body section, the header only can contain 1 text variable.
Example template:
Request:
curl --location -g --request POST 'https://omnichannel.qiscus.com/whatsapp/v1/{{app_id}}/{{channel_id}}/messages'
--header 'Qiscus-App-Id: {{app_id}}'
--header 'Qiscus-Secret-Key: {{secret_key}}'
--header 'Content-Type: application/json'
--data-raw '{
"to": "{{phone_number}}",
"type": "template",
"template": {
"namespace": "{{namespace}}",
"name": "header_text_with_var",
"language": {
"policy": "deterministic",
"code": "id"
},
"components": [
{
"type" : "header",
"parameters": [
{
"type": "text",
"text": "{{header_var1}}"
}
]
},
{
"type" : "body",
"parameters": [
{
"type": "text",
"text": "{{body_var1}}"
},
{
"type": "text",
"text": "{{body_var2}}"
}
]
}
]
}
}'
Note: If your header doesn't have a variable, just remove the header component.
Result:
4. Header with an image variable
Example template:
Request:
curl --location -g --request POST 'https://omnichannel.qiscus.com/whatsapp/v1/{{app_id}}/{{channel_id}}/messages'
--header 'Qiscus-App-Id: {{app_id}}'
--header 'Qiscus-Secret-Key: {{secret_key}}'
--header 'Content-Type: application/json'
--data-raw '{
"to": "{{phone_number}}",
"type": "template",
"template": {
"namespace": "{{namespace}}",
"name": "image_demo",
"language": {
"policy": "deterministic",
"code": "id"
},
"components": [
{
"type" : "header",
"parameters": [
{
"type": "image",
"image": {
"link": "{{image_url}}"
}
}
]
},
{
"type" : "body",
"parameters": [
{
"type": "text",
"text": "{{body_var1}}"
}
]
}
]
}
}'
Note: The image URL must be direct, not shortened URL.
(e.g. https://d1edrlpyc25xu0.cloudfront.net/ramo-29lun8b1ulepsaio/image/upload/w_320,h_320,c_limit/zx64Ye2CA3/eae2beadacb892edac858b045b2c0d1c.png)
Result:
5. Header with a video variable
Example template:
Request:
curl --location -g --request POST 'https://omnichannel.qiscus.com/whatsapp/v1/{{app_id}}/{{channel_id}}/messages'
--header 'Qiscus-App-Id: {{app_id}}'
--header 'Qiscus-Secret-Key: {{secret_key}}'
--header 'Content-Type: application/json'
--data-raw '{
"to": "{{phone_number}}",
"type": "template",
"template": {
"namespace": "{{namespace}}",
"name": "penjelasanmultichannel",
"language": {
"policy": "deterministic",
"code": "id"
},
"components": [
{
"type" : "header",
"parameters": [
{
"type": "video",
"video": {
"link": "{{video_url}}"
}
}
]
},
{
"type" : "body",
"parameters": [
{
"type": "text",
"text": "{{body_var1}}"
}
]
}
]
}
}'
Note: The video URL must be direct, not shortened URL.
Result:
6. Header with a document variable
Example template:
Request:
curl --location -g --request POST 'https://omnichannel.qiscus.com/whatsapp/v1/{{app_id}}/{{channel_id}}/messages'
--header 'Qiscus-App-Id: {{app_id}}'
--header 'Qiscus-Secret-Key: {{secret_key}}'
--header 'Content-Type: application/json'
--data-raw '{
"to": "{{phone_number}}",
"type": "template",
"template": {
"namespace": "{{namespace}}",
"name": "information_update",
"language": {
"policy": "deterministic",
"code": "ms"
},
"components": [
{
"type" : "header",
"parameters": [
{
"type": "document",
"document": {
"link": "{{document_url}}",
"filename": "{{file_name}}"
}
}
]
},
{
"type" : "body",
"parameters": [
{
"type": "text",
"text": "{{body_var1}}"
}
]
}
]
}
}'
Note: The document URL must be direct, not shortened URL. If you want to change the document name, just put it on "filename".
(e.g. https://d1edrlpyc25xu0.cloudfront.net/hat-ppxmocchbbcbhopzk/docs/upload/e7h9vQdk3_/qiscus.pdf)
Result:
7. Button - Call To Action with dynamic URL
If you're using Call To Action button, there are 3 options of action type when creating the template:
Call phone number
Visit website (static URL)
Visit website (dynamic URL): only add a custom suffix of the URL
You can only have 2 Call To Action Buttons (Call phone number & Visit website static/dynamic).
In the API, call phone number and visit website (static URL) no need to be included. It will use the default from the template that you have already submitted. Below is an example of dynamic URL usage.
Example template:
Request:
curl --location -g --request POST 'https://omnichannel.qiscus.com/whatsapp/v1/{{app_id}}/{{channel_id}}/messages'
--header 'Qiscus-App-Id: {{app_id}}'
--header 'Qiscus-Secret-Key: {{secret_key}}'
--header 'Content-Type: application/json'
--data-raw '{
"to": "{{phone_number}}",
"type": "template",
"template": {
"namespace": "{{namespace}}",
"name": "ticket_resolved_123",
"language": {
"policy": "deterministic",
"code": "id"
},
"components": [
{
"type" : "header",
"parameters": [
{
"type": "text",
"text": "{{header_var1}}"
}
]
},
{
"type" : "body",
"parameters": [
{
"type": "text",
"text": "{{body_var1}}"
}
]
},
{
"type":"button",
"sub_type": "url",
"index": 1,
"parameters": [
{
"type": "text",
"text": "{{url_var1}}"
}
]
}
]
}
}'
Note: The value of "index" depends on the order of the Call To Action buttons you have in the template (0 - 1). In this example, the index is 1.
Result:
8. Button - Quick Reply
The template can contain max 3 Quick Reply buttons.
Example template:
Request:
curl --location -g --request POST 'https://omnichannel.qiscus.com/whatsapp/v1/{{app_id}}/{{channel_id}}/messages'
--header 'Qiscus-App-Id: {{app_id}}'
--header 'Qiscus-Secret-Key: {{secret_key}}'
--header 'Content-Type: application/json'
--data-raw '{
"to": "{{phone_number}}",
"type": "template",
"template": {
"namespace": "{{namespace}}",
"name": "ticket_resolved_123",
"language": {
"policy": "deterministic",
"code": "en"
},
"components": [
{
"type" : "header",
"parameters": [
{
"type": "text",
"text": "{{header_var1}}"
}
]
},
{
"type" : "body",
"parameters": [
{
"type": "text",
"text": "{{body_var1}}"
}
]
},
{
"type":"button",
"sub_type": "quick_reply",
"index": 0,
"parameters":[
{
"type": "payload",
"payload": "{{payload_var1}}"
}
]
},
{
"type":"button",
"sub_type": "quick_reply",
"index": 1,
"parameters":[
{
"type": "payload",
"payload": "{{payload_var2}}"
}
]
}
]
}
}'
Note: Parameters in button quick reply are optional. The payload will be sent back when customers click the quick reply button on their WhatsApp. To see it, you have to listen through a webhook. You can remove it if not needed.
{
"type":"button",
"sub_type": "quick_reply",
"index": 0,
"parameters":[]
}
Result:
9. Code Delivery - Copy Code (OTP)
Please read this for the full guideline.
Example template:
Request:
curl --location -g --request POST 'https://omnichannel.qiscus.com/whatsapp/v1/{{app_id}}/{{channel_id}}/messages'
--header 'Qiscus-App-Id: {{app_id}}'
--header 'Qiscus-Secret-Key: {{secret_key}}'
--header 'Content-Type: application/json'
--data-raw '{
"to": "{{phone_number}}",
"type": "template",
"template": {
"namespace": "{{namespace}}",
"name": "new_otp",
"language": {
"policy": "deterministic",
"code": "en"
},
"components": [
{
"type" : "body",
"parameters": [
{
"type": "text",
"text": "{{otp_number}}"
}
]
},
{
"type":"button",
"sub_type": "url",
"index": 0,
"parameters": [
{
"type": "text",
"text": "{{otp_number}}"
}
]
}
]
}
}'
10. Footer
No need to include the footer in your API payload (will automatically use the submitted footer text template).
If you find any errors, please see the following article Failed WhatsApp Broadcast Message with CSV or API