Please understand that this feature is currently in Beta and it’s important to note that certain capabilities, such as Reports and Analytics are not yet available on the dashboard. We will be working on this and is part of our next phase launch.
Currently, the creation of Templates with Flow via API or the Template Management Exotel dashboard is not supported. We plan to enable this feature in the future. Until then, you need to create Templates with Flow button using the Meta dashboard on the WhatsApp Manager. (Other types of template creation are supported via API and Exotel Dashboard.)
You can now send the Template message with the Flow button using the Exotel APIs. To start sending the Template message with the Flow button, you need to follow the below steps:
To send messages to a single number with configured Template message content via Exotel API, make an HTTP POST request to:
https://<your_api_key>:<your_api_token><subdomain>/v2/accounts/<your_sid>/messages
<your_api_key>
and <your_api_token>
with the API key and token created by you.<your_sid>
with your “Account sid".<subdomain>
with the region of your account
<your_api_key>
, <your_api_token>
and <your_sid>
are available on the API settings page of your Exotel Dashboard
The following are the POST parameters -
Parameter Name |
Parameter Type |
Mandatory/ Optional |
Value |
custom_data |
String |
Optional |
This parameter can be used to send any custom data at the API request level. This will be passed back in the callback. |
status_callback |
String (URL) |
Optional |
Once the message reaches the terminal state, Exotel will do a POST callback to your endpoint if the URL is set as a parameter in the API. |
|
Channel Object |
Optional |
Information related to the messages to be sent out on WhatsApp. |
*The Whatsapp parameter mentioned here will be used to send messages through the Whatsapp communication channel. In the future, the API will be extended further to support other communication channels like SMS. Later, the SMS parameter can also be passed to send SMSes.
Parameter Name |
Parameter Type |
Mandatory/ Optional |
Value |
custom_data |
String |
Optional |
This parameter can be used to send any custom data at the API request level. This will be passed back in the callback. |
status_callback |
String (URL) |
Optional |
Once the message reaches the terminal state, Exotel will do a POST callback to your endpoint if the URL is set as a parameter in the API. |
from |
String |
Mandatory |
From number from which the message has to be sent |
to |
String |
Mandatory |
Phone number of the user to whom a message needs to be sent. The number must be in e.164 format. Here are some examples of supported phone number formats: "+10000000000" "+919888888888" "+919876543210" |
content |
Whatsapp Message Object |
Mandatory |
Whatsapp message body |
This will be similar to Whatsapp Native API contracts:
Parameter Name |
Parameter Type |
Mandatory/ Optional |
Value |
template |
Template Object |
Mandatory/ |
Mandatory when type is template |
Parameter |
Type |
Mandatory/ Optional |
Value |
namespace |
String |
Mandatory |
The namespace of the template |
name |
String |
Mandatory |
Name of the template |
language |
Language Object |
Mandatory |
Specifies the language the template may be rendered in. |
components |
[]Component Object |
Mandatory |
Components of the template, containing the parameters of the message. |
Parameter |
Type |
Mandatory/ Optional |
Value |
policy |
String |
Mandatory |
The language policy the message should follow. The only supported option is deterministic. |
code |
String |
Mandatory |
The code of the language or locale to use. Accepts both language and language_locale formats (e.g., en and en_US). |
Parameter |
Type |
Mandatory/ Optional |
Value |
type |
String |
Mandatory |
Type of the component. Supported types are - Header Body Button |
text |
String |
Optional |
Text for the component |
sub_type |
String |
Mandatory |
Required when type=button. Not used for the other types. Type of button to create - form: Set this to 'form' for sending the template message with the flow button. quick_reply & url. |
index |
String |
Mandatory/ Optional |
Required when type=button. Not used for the other types. Position the index of the button. You can have up to 3 buttons using index values of 0 to 2. |
footer |
String |
Optional |
The footer of the component |
parameters |
[]Parameter Object |
Mandatory/ Optional |
Required when type=button. An array of parameter objects with the content of the message. |
Parameter |
Type |
Mandatory/ Optional |
Value |
type |
String |
Mandatory |
Type of the parameter. Describes the parameter type. Supported values: action: Set this to 'action' for sending the template message with the flow button. |
action (object) |
String |
Mandatory |
Required when type is 'action' |
flow_token |
String |
Optional |
flow_token: 0000, default is "unused". |
flow_action_data |
String |
Optional |
flow_action_data optional, JSON object with the data payload for the first screen |
Please refer to Exotel's sample Postman collection to try out the APIs, we have also shared some examples here for your reference.
curl --location 'https://{{AuthKey}}:{{AuthToken}}@{{SubDomain}}/v2/accounts/{{AccountSid}}/messages' \ --header 'Content-Type: application/json' \ --data '{ "custom_data": "ORXXXXXXX", "status_callback": "https://webhook.site", "whatsapp": { "messages": [ { "from": "+911XXXXXXXX", "to": "+9199XXXXXXXX", "content": { "type": "template", "template": { "name": "flow_template", "language": { "code": "en_US" }, "components": [ { "type": "button", "sub_type": "flow", "index": "0", "parameters": [ { "type": "action", "action": { "flow_token": "0000", "flow_action_data": { "product_name": "test", "product_description": "test", "product_price": 1 } } } ] } ] } } } ] } }'
import requests import json url = "https://{{AuthKey}}:{{AuthToken}}@{{SubDomain}}/v2/accounts/{{AccountSid}}/messages" payload = json.dumps({ "custom_data": "ORXXXXXXX", "status_callback": "https://webhook.site", "whatsapp": { "messages": [ { "from": "+911XXXXXXXX", "to": "+9199XXXXXXXX", "content": { "type": "template", "template": { "name": "flow_template", "language": { "code": "en_US" }, "components": [ { "type": "button", "sub_type": "flow", "index": "0", "parameters": [ { "type": "action", "action": { "flow_token": "0000", "flow_action_data": { "product_name": "test", "product_description": "test", "product_price": 1 } } } ] } ] } } } ] } }) headers = { 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text)
curl --location --globoff 'https://{{AuthKey}}:{{AuthToken}}@{{SubDomain}}/v2/accounts/{{AccountSid}}/messages' \ --header 'Content-Type: application/json' \ --data '{ "custom_data": "ORDXXXXX", "status_callback": "https://webhook.site", "whatsapp": { "messages": [ { "from": "{{FromNumber}}", "to": "{{ToNumber}}", "content": { "type": "template", "template": { "name": "template_flow_text_header", "language": { "code": "en" }, "components": [ { "type": "header", "parameters": [ { "type": "text", "text": "Exotel" } ] }, { "type": "body", "parameters": [ { "type": "text", "text": "John" } ] }, { "type": "button", "sub_type": "flow", "index": "0", "parameters": [ { "type": "action", "action": { "flow_token": "0000", "flow_action_data": { "product_name": "test", "product_description": "test", "product_price": 1 } } } ] } ] } } } ] } }'
import requests import json url = "https://{{AuthKey}}:{{AuthToken}}@{{SubDomain}}/v2/accounts/{{AccountSid}}/messages" payload = json.dumps({ "custom_data": "ORDER123456", "status_callback": "https://webhook.site", "whatsapp": { "messages": [ { "from": "{{FromNumber}}", "to": "{{ToNumber}}", "content": { "type": "template", "template": { "name": "template_flow_text_header", "language": { "code": "en", "policy": "deterministic" //Only for On-Premise APIs }, "components": [ { "type": "header", "parameters": [ { "type": "text", "text": "Exotel" } ] }, { "type": "body", "parameters": [ { "type": "text", "text": "Javed" } ] }, { "type": "button", "sub_type": "flow", "index": "0", "parameters": [ { "type": "action", "action": { "flow_token": "0000", "flow_action_data": { "product_name": "test", "product_description": "test", "product_price": 1 } } } ] } ] } } } ] } }) headers = { 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text)
curl --location --globoff 'https://{{AuthKey}}:{{AuthToken}}@{{SubDomain}}/v2/accounts/{{AccountSid}}/messages' \ --header 'Content-Type: application/json' \ --data '{ "custom_data": "ORDXXXXX", "status_callback": "https://webhook.site", "whatsapp": { "messages": [ { "from": "{{FromNumber}}", "to": "{{ToNumber}}", "content": { "type": "template", "template": { "name": "flow_template_header_image", "language": { "code": "en" }, "components": [ { "type": "header", "parameters": [ { "type": "image", "image": { "link": "https://image.shutterstock.com/image-photo/happy-XXXXXXXXX.jpg" } } ] }, { "type": "body", "parameters": [ { "type": "text", "text": "John" } ] }, { "type": "button", "sub_type": "flow", "index": "0", "parameters": [ { "type": "action", "action": { "flow_token": "0000", "flow_action_data": { "product_name": "test", "product_description": "test", "product_price": 1 } } } ] } ] } } } ] } }'
import requests import json url = "https://{{AuthKey}}:{{AuthToken}}@{{SubDomain}}/v2/accounts/{{AccountSid}}/messages" payload = json.dumps({ "custom_data": "ORDXXXXX", "status_callback": "https://webhook.site", "whatsapp": { "messages": [ { "from": "{{FromNumber}}", "to": "{{ToNumber}}", "content": { "type": "template", "template": { "name": "flow_template_header_image", "language": { "policy": "deterministic", //Only for On-Premise APIs "code": "en" }, "components": [ { "type": "header", "parameters": [ { "type": "image", "image": { "link": "https://image.shutterstock.com/image-photo/happy-puppy-dog-smiling-on-260nw-1799966587.jpg" } } ] }, { "type": "body", "parameters": [ { "type": "text", "text": "Javed" } ] }, { "type": "button", "sub_type": "flow", "index": "0", "parameters": [ { "type": "action", "action": { "flow_token": "0000", "flow_action_data": { "product_name": "test", "product_description": "test", "product_price": 1 } } } ] } ] } } } ] } }) headers = { 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text)
HTTP Response:
{ "request_id": "210bd1cda8004a2e913eac7a580eb159", "method": "POST", "http_code": 202, "metadata": { "failed": 0, "total": 1, "success": 1 }, "response": { "whatsapp": { "messages": [ { "code": 202, "error_data": null, "status": "success", "data": { "sid": "f65047444e5c782a56f76f40e06717b9" } } ] } } }
The following are the response parameters -
Parameter |
Type |
Mandatory/Optional |
Notes |
request_id |
String |
Mandatory |
This indicates the unique id of the request. Useful for debugging and tracing purposes. |
method |
String |
Mandatory |
This indicates the HTTP method for the request such as POST |
http_code |
Integer |
Mandatory |
This indicates the HTTP code for the request such as 202, 400, 500 etc. |
metadata |
Metadata Object |
Mandatory |
Metadata pertaining to the request. Count of failed, total and success records. |
response |
Response Object |
Mandatory |
Response for the request |
Parameter |
Type |
Mandatory/Optional |
Notes |
total |
Integer |
Mandatory |
Total number of the messages in the request |
success |
Integer |
Mandatory |
Number of messages successfully accepted |
failed |
Integer |
Mandatory |
Number of messages that couldn’t be accepted (failed) |
Parameter |
Type |
Mandatory/Optional |
Notes |
|
Channel Response Object |
Mandatory |
Response for Whatsapp messages specified in the request |
Parameter |
Type |
Mandatory/Optional |
Notes |
messages |
[]Create Message Response Object |
Mandatory |
Array of messages response for each message |
Parameter |
Type |
Mandatory/Optional |
Notes |
code |
Integer |
Mandatory |
Response code for the individual message |
error_data |
ErrorResponseObject |
Optional |
Error related to a single message |
status |
String |
Mandatory |
Status of the single message |
data |
Message Response Object |
Optional |
Data pertaining to a single message |
Parameter |
Type |
Mandatory/Optional |
Notes |
code |
Numeric |
Mandatory |
Numeric HTTP code for a Single message |
message |
String |
Mandatory |
Brief description of the error |
description |
String |
Mandatory |
Detailed explanation of error |
Parameter |
Type |
Mandatory/Optional |
Notes |
sid |
String |
Mandatory |
SID (Unique identifier) of the single message |
HTTP Error Codes |
Error Message |
202 |
Accepted - Request accepted. |
400 |
Bad Request - Something in your header or request body was malformed/missing. More than 100 messages specified in a request |
401 |
Unauthorized - Necessary credentials were either missing or invalid. |
402 |
Payment Required - The action is not available on your plan, or you have exceeded usage limits for your current plan. |
403 |
Your credentials are valid, but you don’t have access to the requested resource. |
404 |
Not Found - The object you’re requesting doesn’t exist. |
5xx |
Server Errors - Something went wrong at our end. Please try again. |
Status callback URL can be passed in the status_callback parameter in send message/template message APIs and it can also be configured as default to receive the responses. The Exotel team will help you configure the default URL while onboarding.
*NOTE: Any callback can be received only in one status callback URL at any time
What is different for Flow Template?
"whatsapp": { "messages": [ { "callback_type": "dlr", "sid": "1234XXXXX", "to": "2365XXXXXX", "exo_status_code": 25001, "exo_detailed_status": "EX_MESSAGE_DELIVERED", "description": "Message delivered", "timestamp": "2022-12-07T17:00:00.000+05:30", "custom_data": "custom" } ] } }