curl --request PATCH \
--url https://app.thinnest.ai/api/v1/templates/{name} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"body": "Hello {{1}}, your Kesar Naturals order {{2}} has been packed and will reach you within 3 days.",
"samples": [
"Priya",
"#10432"
]
}
'const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
body: JSON.stringify('Hello {{1}}, your Kesar Naturals order {{2}} has been packed and will reach you within 3 days.'),
samples: ['Priya', '#10432']
})
};
fetch('https://app.thinnest.ai/api/v1/templates/{name}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://app.thinnest.ai/api/v1/templates/{name}"
payload = {
"body": "Hello {{1}}, your Kesar Naturals order {{2}} has been packed and will reach you within 3 days.",
"samples": ["Priya", "#10432"]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text){
"name": "order_ready",
"language": "en",
"category": "utility",
"status": "draft",
"agent": "ag_5c4a5f93-2b1e-4c0a-9d3f-7e8a1b2c3d4e",
"body": "Hello {{1}}, your Kesar Naturals order {{2}} has been packed and will reach you within 3 days.",
"variableCount": 2,
"variableLabels": [
{
"position": 1,
"sample": "Priya"
},
{
"position": 2,
"sample": "#10432"
}
],
"buttonVariableCount": 1,
"headerKind": "none",
"createdAt": "2026-10-06T10:00:01.874Z",
"headerText": null,
"footer": "Kesar Naturals, Jaipur",
"buttons": [
{
"kind": "url",
"label": "Track order",
"url": "https://kesarnaturals.in/track/{{1}}"
}
],
"reviewNote": null
}{
"error": "`footer` is text of up to 60 characters."
}{
"error": "Send a valid API key as `Authorization: Bearer <key>`."
}{
"error": "This API key is read-only: it can read everything but change nothing."
}{
"error": "That template was not found."
}{
"error": "Only a draft can be edited; this one is approved. Make a new template instead."
}{
"error": "Give an example for each placeholder — 1 of 2 filled in."
}{
"error": "Over 240 requests a minute. Slow down and retry."
}Update Template
Edits a draft template. Send only the fields that change; the result is checked against the same rules as Create Template. Once a template has been sent for review WhatsApp has its text, so it can no longer be edited — create a new template instead. Changing name or language renames it. A build key may do this.
curl --request PATCH \
--url https://app.thinnest.ai/api/v1/templates/{name} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"body": "Hello {{1}}, your Kesar Naturals order {{2}} has been packed and will reach you within 3 days.",
"samples": [
"Priya",
"#10432"
]
}
'const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
body: JSON.stringify('Hello {{1}}, your Kesar Naturals order {{2}} has been packed and will reach you within 3 days.'),
samples: ['Priya', '#10432']
})
};
fetch('https://app.thinnest.ai/api/v1/templates/{name}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://app.thinnest.ai/api/v1/templates/{name}"
payload = {
"body": "Hello {{1}}, your Kesar Naturals order {{2}} has been packed and will reach you within 3 days.",
"samples": ["Priya", "#10432"]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text){
"name": "order_ready",
"language": "en",
"category": "utility",
"status": "draft",
"agent": "ag_5c4a5f93-2b1e-4c0a-9d3f-7e8a1b2c3d4e",
"body": "Hello {{1}}, your Kesar Naturals order {{2}} has been packed and will reach you within 3 days.",
"variableCount": 2,
"variableLabels": [
{
"position": 1,
"sample": "Priya"
},
{
"position": 2,
"sample": "#10432"
}
],
"buttonVariableCount": 1,
"headerKind": "none",
"createdAt": "2026-10-06T10:00:01.874Z",
"headerText": null,
"footer": "Kesar Naturals, Jaipur",
"buttons": [
{
"kind": "url",
"label": "Track order",
"url": "https://kesarnaturals.in/track/{{1}}"
}
],
"reviewNote": null
}{
"error": "`footer` is text of up to 60 characters."
}{
"error": "Send a valid API key as `Authorization: Bearer <key>`."
}{
"error": "This API key is read-only: it can read everything but change nothing."
}{
"error": "That template was not found."
}{
"error": "Only a draft can be edited; this one is approved. Make a new template instead."
}{
"error": "Give an example for each placeholder — 1 of 2 filled in."
}{
"error": "Over 240 requests a minute. Slow down and retry."
}Authorizations
Your API key (ta_live_…) from Settings → API keys, sent as Authorization: Bearer <key>. Keep it on a server: it can message every customer you have. A key is full, build or read-only; a request its level does not allow is refused with 403.
Headers
Developers only: the customer workspace this request acts in — its org_… id from POST /customers. Leave it out to act in your own workspace.
"org_3fKq9TzQ1mN8vB2xR7cLpA"
Path Parameters
The template's name: lowercase letters, numbers and underscores.
^[a-z0-9_]{1,512}$Query Parameters
The template's language code. Needed only when the name exists in more than one language; without it such a name is a 409 that lists them.
Body
Only the fields sent change; the rest keep their current values. The result must pass the same rules as Create Template.
A new name: lowercase letters, numbers and underscores only.
^[a-z0-9_]{1,512}$A new language code WhatsApp templates support, such as en, en_US or hi.
A new category.
utility, marketing, authentication The new message, with {{1}}, {{2}} … for the blanks. Ignored for an authentication template.
1024One example per body blank, in order. Leave it out to keep the current examples.
20The line or media above the body. null means no header.
Show child attributes
Show child attributes
The new footer. null or "" removes it.
60The full new list of buttons, replacing the old one. null or [] removes them all.
10Show child attributes
Show child attributes
An authentication template's settings. WhatsApp writes the message itself ("123456 is your verification code."), so these are all you choose.
Show child attributes
Show child attributes
Response
Saved. The template as it now is.
A WhatsApp template with its parts and review note.
The template's name — what Send Message and Create Campaign take.
"order_ready"
Its language code.
"en"
WhatsApp's category, which decides its price and its rules.
utility, marketing, authentication draft until submitted, pending while WhatsApp reviews it, then approved or rejected. WhatsApp may later pause an approved template that recipients flag. Only approved can be sent.
draft, pending, approved, rejected, paused The agent the template belongs to (ag_…).
"ag_5c4a5f93-2b1e-4c0a-9d3f-7e8a1b2c3d4e"
The message, with {{1}}, {{2}} … for the blanks. For an authentication template, the sentence WhatsApp writes around the code.
How many body values a send must carry, in order: the highest {{n}} in the body.
x >= 0The example given for each body blank.
Show child attributes
Show child attributes
How many button values a send must carry: one per link button whose address ends in a blank.
x >= 0The header. image, video or document means a send must pass a media link for it.
none, text, image, video, document When it was created.
A text header's words. null for any other header.
The footer line. Empty when there is none.
The template's buttons, in order.
Show child attributes
Show child attributes
Why WhatsApp refused it, when it did. null otherwise.