WhatsApp lets you start a conversation, or write after the 24-hour window has closed, only with a template Meta has approved. These endpoints manage the templates on a WhatsApp channel line, and you send them in campaigns or from the Inbox.
Every call takes channelConfigId — the line — because templates belong to that line’s WhatsApp Business account. There is no endpoint to edit a template or read its performance: create a new one instead.
Endpoints
GET/whatsapp/templatesList templatesGET/whatsapp/templates/{templateName}Retrieve a templatePOST/whatsapp/templatesCreate a templateDELETE/whatsapp/templates/{templateName}Delete a templateThe template object
A subset of what Meta returns: the fields below are the ones Natiq passes through.
Attributes
idstringThe template’s ID.namestringTemplate name. Together withlanguageit identifies the template.languagestringLanguage code, e.g.aroren.categorystringThe template category Meta bills and reviews it under.One of:MARKETINGUTILITYAUTHENTICATIONstatusstringWhere the template is in Meta’s review. A template can be sent only once it isAPPROVED.One of:APPROVEDPENDINGREJECTEDPAUSEDDISABLEDIN_APPEALcomponentsarray<object>The template’s parts, in the Meta component format.
{
"id": "1493820471920384",
"name": "order_shipped",
"language": "ar",
"category": "UTILITY",
"status": "APPROVED",
"components": [
{
"type": "BODY",
"text": "مرحباً {{1}}، تم شحن طلبك رقم {{2}}.",
"example": {
"body_text": [
[
"ليلى",
"A-1001"
]
]
}
},
{
"type": "FOOTER",
"text": "شكراً لاختيارك النور"
}
]
}
List templates
Returns the templates on a line, one page at a time. This list is cursor paginated rather than offset or keyset: pass the response’s nextCursor as after to get the next page, and stop when a page comes back with fewer items than limit or empty. nextCursor may still be set on the last page.
campaigns.templates:readQuery parameters
channelConfigIdintegerrequiredThe WhatsApp channel line. The business account and token are read server-side from that line’s settings.namestringOnly templates with this name.statusstringOnly templates in this review status, e.g.APPROVED.languagestringOnly templates in this language.limitintegerTemplates per page. No default is set here, so Meta’s default applies.afterstringThenextCursorof the previous page.
Returns
200The template object.
Errors
- 404
CHANNEL_CONFIG_NOT_FOUNDNo channel line with this `channelConfigId` in your organisation. - 400
INVALID_REQUESTThe line is not a WhatsApp line. - 502
WHATSAPP_API_NOT_CONFIGUREDThe line has no WhatsApp Business account ID or access token.
curl -X GET "https://api.cx.na6iq.com/api/v1/whatsapp/templates?channelConfigId=42" \
-H "Authorization: Bearer $NATIQ_TOKEN"
const res = await fetch('https://api.cx.na6iq.com/api/v1/whatsapp/templates?channelConfigId=42', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.NATIQ_TOKEN}`,
},
})
if (!res.ok) throw new Error((await res.json().catch(() => ({}))).error?.message ?? `HTTP ${res.status}`)
const data = await res.json()
import os, requests
res = requests.get(
"https://api.cx.na6iq.com/api/v1/whatsapp/templates?channelConfigId=42",
headers={"Authorization": f"Bearer {os.environ['NATIQ_TOKEN']}"},
)
res.raise_for_status()
data = res.json()
{
"data": [
{
"id": "1493820471920384",
"name": "order_shipped",
"language": "ar",
"category": "UTILITY",
"status": "APPROVED",
"components": [
{
"type": "BODY",
"text": "مرحباً {{1}}، تم شحن طلبك رقم {{2}}.",
"example": {
"body_text": [
[
"ليلى",
"A-1001"
]
]
}
},
{
"type": "FOOTER",
"text": "شكراً لاختيارك النور"
}
]
}
],
"nextCursor": null
}
Retrieve a template
Returns one template by name. A name can exist in several languages: pass language to pick one.
campaigns.templates:readPath parameters
templateNamestringrequiredThe template’sname.
Query parameters
channelConfigIdintegerrequiredThe WhatsApp channel line. The business account and token are read server-side from that line’s settings.languagestringThe language version to return.
Returns
200The template object.
Errors
- 404
WHATSAPP_TEMPLATE_NOT_FOUNDNo template with this name on the line. - 404
CHANNEL_CONFIG_NOT_FOUNDNo channel line with this `channelConfigId` in your organisation. - 400
INVALID_REQUESTThe line is not a WhatsApp line. - 502
WHATSAPP_API_NOT_CONFIGUREDThe line has no WhatsApp Business account ID or access token.
curl -X GET "https://api.cx.na6iq.com/api/v1/whatsapp/templates/value?channelConfigId=42" \
-H "Authorization: Bearer $NATIQ_TOKEN"
const res = await fetch('https://api.cx.na6iq.com/api/v1/whatsapp/templates/value?channelConfigId=42', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.NATIQ_TOKEN}`,
},
})
if (!res.ok) throw new Error((await res.json().catch(() => ({}))).error?.message ?? `HTTP ${res.status}`)
const data = await res.json()
import os, requests
res = requests.get(
"https://api.cx.na6iq.com/api/v1/whatsapp/templates/value?channelConfigId=42",
headers={"Authorization": f"Bearer {os.environ['NATIQ_TOKEN']}"},
)
res.raise_for_status()
data = res.json()
{
"id": "1493820471920384",
"name": "order_shipped",
"language": "ar",
"category": "UTILITY",
"status": "APPROVED",
"components": [
{
"type": "BODY",
"text": "مرحباً {{1}}، تم شحن طلبك رقم {{2}}.",
"example": {
"body_text": [
[
"ليلى",
"A-1001"
]
]
}
},
{
"type": "FOOTER",
"text": "شكراً لاختيارك النور"
}
]
}
Create a template
Submits a new template to Meta for review. Poll Retrieve a template to follow its review status. There is no endpoint to edit a template, so a change means creating a new one.
campaigns.templates:writeRequest body
channelConfigIdintegerrequiredThe WhatsApp channel line to create the template on.namestringrequiredTemplate name.languagestringrequiredLanguage code, e.g.ar.categorystringrequiredThe template category.One of:MARKETINGUTILITYAUTHENTICATIONcomponentsarray<object>requiredThe template’s parts, in the Meta component format.
Returns
201Natiq returns Meta’s create reply as it is. Only `id`, `status` and `category` are filled in; fetch the template to see it in full.
Errors
- 400
VALIDATION_FAILEDA required field is missing or a component is malformed — see `error.details`. - 400
INVALID_REQUESTMeta rejected the template (the message is Meta’s), or the line is not a WhatsApp line. - 502
WHATSAPP_API_ERRORThe call to Meta failed. - 404
CHANNEL_CONFIG_NOT_FOUNDNo channel line with this `channelConfigId` in your organisation. - 502
WHATSAPP_API_NOT_CONFIGUREDThe line has no WhatsApp Business account ID or access token.
curl -X POST "https://api.cx.na6iq.com/api/v1/whatsapp/templates" \
-H "Authorization: Bearer $NATIQ_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"channelConfigId": 22,
"name": "order_shipped",
"language": "ar",
"category": "UTILITY",
"components": [
{
"type": "BODY",
"text": "مرحباً {{1}}، تم شحن طلبك رقم {{2}}.",
"example": {
"body_text": [
[
"ليلى",
"A-1001"
]
]
}
},
{
"type": "FOOTER",
"text": "شكراً لاختيارك النور"
}
]
}'
const res = await fetch('https://api.cx.na6iq.com/api/v1/whatsapp/templates', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.NATIQ_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"channelConfigId": 22,
"name": "order_shipped",
"language": "ar",
"category": "UTILITY",
"components": [
{
"type": "BODY",
"text": "مرحباً {{1}}، تم شحن طلبك رقم {{2}}.",
"example": {
"body_text": [
[
"ليلى",
"A-1001"
]
]
}
},
{
"type": "FOOTER",
"text": "شكراً لاختيارك النور"
}
]
}),
})
if (!res.ok) throw new Error((await res.json().catch(() => ({}))).error?.message ?? `HTTP ${res.status}`)
const data = await res.json()
import os, requests
res = requests.post(
"https://api.cx.na6iq.com/api/v1/whatsapp/templates",
headers={"Authorization": f"Bearer {os.environ['NATIQ_TOKEN']}"},
json={
"channelConfigId": 22,
"name": "order_shipped",
"language": "ar",
"category": "UTILITY",
"components": [
{
"type": "BODY",
"text": "مرحباً {{1}}، تم شحن طلبك رقم {{2}}.",
"example": {
"body_text": [
[
"ليلى",
"A-1001"
]
]
}
},
{
"type": "FOOTER",
"text": "شكراً لاختيارك النور"
}
]
},
)
res.raise_for_status()
data = res.json()
{
"id": "1493820471920384",
"name": null,
"language": null,
"status": "PENDING",
"category": "UTILITY",
"components": []
}
Delete a template
Deletes the template by name on the line. Deleting by name removes every language version of it.
campaigns.templates:writePath parameters
templateNamestringrequiredThe template’sname.
Query parameters
channelConfigIdintegerrequiredThe WhatsApp channel line. The business account and token are read server-side from that line’s settings.
Returns
204The template is deleted.
Errors
- 400
INVALID_REQUESTMeta usually answers an unknown name with `400`, which comes through as `INVALID_REQUEST`. It is also the answer when the line is not a WhatsApp line. - 404
WHATSAPP_TEMPLATE_NOT_FOUNDOnly when Meta itself says the template was not found. - 404
CHANNEL_CONFIG_NOT_FOUNDNo channel line with this `channelConfigId` in your organisation. - 502
WHATSAPP_API_NOT_CONFIGUREDThe line has no WhatsApp Business account ID or access token.
curl -X DELETE "https://api.cx.na6iq.com/api/v1/whatsapp/templates/value?channelConfigId=42" \
-H "Authorization: Bearer $NATIQ_TOKEN"
const res = await fetch('https://api.cx.na6iq.com/api/v1/whatsapp/templates/value?channelConfigId=42', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.NATIQ_TOKEN}`,
},
})
if (!res.ok) throw new Error((await res.json().catch(() => ({}))).error?.message ?? `HTTP ${res.status}`)
import os, requests
res = requests.delete(
"https://api.cx.na6iq.com/api/v1/whatsapp/templates/value?channelConfigId=42",
headers={"Authorization": f"Bearer {os.environ['NATIQ_TOKEN']}"},
)
res.raise_for_status()