curl -X POST https://tawked.com/v1/whatsapp/templates \
-H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order_shipped_v1-ar" \
-d '{
"name": "order_shipped_v1",
"language": "ar",
"category": "UTILITY",
"header": "طلبك {{order}}",
"body": "طلبك {{order}} في الطريق، ويصلك خلال {{days}} أيام.",
"footer": "متجر الورد",
"buttons": [
{
"type": "URL",
"text": "تتبع الشحنة",
"url": "https://flowers.example/track/{{1}}"
}
],
"examples": {
"header:order": "1042",
"body:order": "1042",
"body:days": "3",
"button:0": "1042"
}
}'const res = await fetch("https://tawked.com/v1/whatsapp/templates", {
method: "POST",
headers: {
Authorization: "Bearer tk_live_xxxxxxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
"Idempotency-Key": "order_shipped_v1-ar",
},
body: JSON.stringify({
"name": "order_shipped_v1",
"language": "ar",
"category": "UTILITY",
"header": "طلبك {{order}}",
"body": "طلبك {{order}} في الطريق، ويصلك خلال {{days}} أيام.",
"footer": "متجر الورد",
"buttons": [
{
"type": "URL",
"text": "تتبع الشحنة",
"url": "https://flowers.example/track/{{1}}"
}
],
"examples": {
"header:order": "1042",
"body:order": "1042",
"body:days": "3",
"button:0": "1042"
}
}),
});
const data = await res.json();<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://tawked.com/v1/whatsapp/templates",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'language' => '<string>',
'category' => '<string>',
'body' => '<string>',
'header' => '<string>',
'footer' => '<string>',
'buttons' => '<array>',
'examples' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}import requests
res = requests.post(
"https://tawked.com/v1/whatsapp/templates",
headers={"Authorization": "Bearer tk_live_xxxxxxxxxxxxxxxxxxxx", "Idempotency-Key": "order_shipped_v1-ar"},
json={
"name": "order_shipped_v1",
"language": "ar",
"category": "UTILITY",
"header": "طلبك {{order}}",
"body": "طلبك {{order}} في الطريق، ويصلك خلال {{days}} أيام.",
"footer": "متجر الورد",
"buttons": [
{
"type": "URL",
"text": "تتبع الشحنة",
"url": "https://flowers.example/track/{{1}}"
}
],
"examples": {
"header:order": "1042",
"body:order": "1042",
"body:days": "3",
"button:0": "1042"
}
},
)
data = res.json(){
"id": "7100",
"name": "order_shipped_v1",
"language": "ar",
"category": "UTILITY",
"status": "PENDING"
}{
"error": "invalid_request",
"fields": [
"body",
"examples.header:order"
],
"errors": {
"body": [
"placeholderEdges"
],
"examples.header:order": [
"exampleRequired"
]
}
}{
"error": "unauthorized"
}{
"error": "account_not_active"
}{
"error": "no_whatsapp_number"
}{
"error": "template_refused",
"message": "Meta error 100: Template name already exists"
}{
"error": "too_many_requests"
}{
"error": "internal_error"
}{
"error": "templates_unavailable"
}Create a template
For a connected app’s key alone: an application’s own key, full access included, answers 403 insufficient_scope, and writes its templates in the console. Submits a text template to Meta’s review under the rules of the console’s editor, and answers Meta’s id, the category as Meta filed it and the status (PENDING at first, usually). Text only: any field outside the ones below is ignored, so a template that opens with an image is created in the console. A refused field answers 400 invalid_request with fields naming it and errors giving each field’s reasons; what Meta refuses after that answers 422 template_refused with Meta’s own sentence.
curl -X POST https://tawked.com/v1/whatsapp/templates \
-H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order_shipped_v1-ar" \
-d '{
"name": "order_shipped_v1",
"language": "ar",
"category": "UTILITY",
"header": "طلبك {{order}}",
"body": "طلبك {{order}} في الطريق، ويصلك خلال {{days}} أيام.",
"footer": "متجر الورد",
"buttons": [
{
"type": "URL",
"text": "تتبع الشحنة",
"url": "https://flowers.example/track/{{1}}"
}
],
"examples": {
"header:order": "1042",
"body:order": "1042",
"body:days": "3",
"button:0": "1042"
}
}'const res = await fetch("https://tawked.com/v1/whatsapp/templates", {
method: "POST",
headers: {
Authorization: "Bearer tk_live_xxxxxxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
"Idempotency-Key": "order_shipped_v1-ar",
},
body: JSON.stringify({
"name": "order_shipped_v1",
"language": "ar",
"category": "UTILITY",
"header": "طلبك {{order}}",
"body": "طلبك {{order}} في الطريق، ويصلك خلال {{days}} أيام.",
"footer": "متجر الورد",
"buttons": [
{
"type": "URL",
"text": "تتبع الشحنة",
"url": "https://flowers.example/track/{{1}}"
}
],
"examples": {
"header:order": "1042",
"body:order": "1042",
"body:days": "3",
"button:0": "1042"
}
}),
});
const data = await res.json();<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://tawked.com/v1/whatsapp/templates",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'language' => '<string>',
'category' => '<string>',
'body' => '<string>',
'header' => '<string>',
'footer' => '<string>',
'buttons' => '<array>',
'examples' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}import requests
res = requests.post(
"https://tawked.com/v1/whatsapp/templates",
headers={"Authorization": "Bearer tk_live_xxxxxxxxxxxxxxxxxxxx", "Idempotency-Key": "order_shipped_v1-ar"},
json={
"name": "order_shipped_v1",
"language": "ar",
"category": "UTILITY",
"header": "طلبك {{order}}",
"body": "طلبك {{order}} في الطريق، ويصلك خلال {{days}} أيام.",
"footer": "متجر الورد",
"buttons": [
{
"type": "URL",
"text": "تتبع الشحنة",
"url": "https://flowers.example/track/{{1}}"
}
],
"examples": {
"header:order": "1042",
"body:order": "1042",
"body:days": "3",
"button:0": "1042"
}
},
)
data = res.json(){
"id": "7100",
"name": "order_shipped_v1",
"language": "ar",
"category": "UTILITY",
"status": "PENDING"
}{
"error": "invalid_request",
"fields": [
"body",
"examples.header:order"
],
"errors": {
"body": [
"placeholderEdges"
],
"examples.header:order": [
"exampleRequired"
]
}
}{
"error": "unauthorized"
}{
"error": "account_not_active"
}{
"error": "no_whatsapp_number"
}{
"error": "template_refused",
"message": "Meta error 100: Template name already exists"
}{
"error": "too_many_requests"
}{
"error": "internal_error"
}{
"error": "templates_unavailable"
}Authorizations
Authorization: Bearer . An application key (tk_live_, tk_test_) has full access, which covers every product and any product added later, or custom access, chosen when the key is created: one or more of the scopes verify:check, verify:send (includes verify:check), notifications:read, notifications:send (includes notifications:read), notifications:templates (includes notifications:read). No key made on the API keys page holds notifications:templates, full access included: the three template writes answer such a key 403 insufficient_scope. A connected app's key holds it. A call outside the key's access answers 403 insufficient_scope and names the scope it needs in the WWW-Authenticate response header. A partner key (tk_partner_) always has full access. Whatever its access, a key is a server-side secret.
Headers
A 1 to 128 printable-ASCII-character key you generate, scoped to your API key. Replaying it with the same request answers the original 2xx unchanged, with the response header Idempotent-Replayed: true, and runs nothing again; the same key with another request answers 409 idempotency_key_reused, and a request still in flight 409 idempotency_in_progress. A refused request is never stored, so a corrected retry under the same key runs. Keys expire after 24 hours.
Body
Lowercase letters, digits and underscores, up to 512 characters. Meta fixes it at creation. A connected app's key may not take a name that starts salla_, zid_ or wf_, or one of Tawked's own template names: errors.name is then nameReserved.
One of ar, en, en_US, en_GB, ur, hi, bn, tl, id, fr. Fixed at creation.
UTILITY. A connected app's key writes utility templates only: MARKETING is refused with 422 template_category_not_allowed. An authentication template is created in the console.
Up to 1024 characters. Placeholders are all named ({{name}}, lowercase) or all numbered ({{1}}, {{2}} in order), never at the very start or end of the text.
A text header: one line, up to 60 characters, no emoji and no asterisk, at most one placeholder.
One line, up to 60 characters, no placeholders.
Up to 10 objects, each with a text of up to 25 characters: { "type": "QUICK_REPLY", "text" }, { "type": "URL", "text", "url" } (https, optionally ending in {{1}}; two at most) or { "type": "PHONE_NUMBER", "text", "phone_number" } (E.164; one at most). Quick replies sit together, before or after the other buttons.
One sample value per placeholder, keyed header:<key>, body:<key> and button:<index>. Required whenever the template has placeholders: Meta reviews with them.