WhatsApp templates
List templates
Newest first. Filter by status.
Required scope: whatsapp:read.
query Parameters
limitcursorThe nextCursor of the previous page, with the same filters.
statusHeaders
Lelemon-Subaccount^sub_[0-9A-Za-z]{22}…The subaccount (sub_…) this request acts on. Only for the keys of a platform account; without it the request acts on the account itself.
List templates › Responses
objecthasMorenextCursorCreate a template
Sends it to WhatsApp review (in_review). You get template.status_changed when WhatsApp decides. Marketing templates always get an opt-out button, written in the language of the template ("No recibir más" in Spanish, "Stop messages" by default). To word it yourself, send a quick_reply with payload lelemon_stop_messages and your text. A template can have a document header: send header.exampleUrl, and the document itself when you send the message. Use buttons for quick replies (the tap comes back as a message with reply {id, title}, so a reminder can offer Confirm and Cancel) and for fixed links (type url, https, no variables yet). It is not idempotent: repeating it with the same name and language is a 409.
Required scope: whatsapp:write.
Headers
Lelemon-Subaccount^sub_[0-9A-Za-z]{22}…The subaccount (sub_…) this request acts on. Only for the keys of a platform account; without it the request acts on the account itself.
Idempotency-KeyMakes the request safe to retry. Once it starts running, its final response (2xx, 4xx or 5xx) is kept for 24 hours and the same key gets it back, without repeating the effect. A request rejected before it runs leaves the key free. A replayed create omits the secret. The same key with a different request is rejected with 409 idempotency_key_reused.
Create a template › Request Body
name^[a-z][a-z0-9_]{0,51… · requiredlowercase_with_underscores.
languagecategorybodyWith named variables: {{name}}.
A sample value for each variable.
footerUp to 10 buttons, at most 2 of type url. Marketing templates also get the opt-out button, which counts toward the 10: in the language of the template, or your own text if you send a quick_reply with payload lelemon_stop_messages. Quick replies are kept together before the links.
Swipeable cards under the body, with media or with catalog products. WhatsApp checks the combination with the other parts when it reviews the template.
Create a template › Responses
objectidnamelanguagecategorystatusrejectionReasonbodyfooterbuttonsTexts of the buttons.
The buttons with their type, payload or link.
variablesThe variables of the body and of the links of the buttons.
createdAtupdatedAtSync template statuses
Asks WhatsApp for the current status of your templates and updates them. WhatsApp does not notify changes, so this also runs by itself while a template is in review.
Required scope: whatsapp:write.
Headers
Lelemon-Subaccount^sub_[0-9A-Za-z]{22}…The subaccount (sub_…) this request acts on. Only for the keys of a platform account; without it the request acts on the account itself.
Idempotency-KeyMakes the request safe to retry. Once it starts running, its final response (2xx, 4xx or 5xx) is kept for 24 hours and the same key gets it back, without repeating the effect. A request rejected before it runs leaves the key free. A replayed create omits the secret. The same key with a different request is rejected with 409 idempotency_key_reused.
Sync template statuses › Responses
objectcheckedTemplates checked against WhatsApp.
updatedTemplates whose status changed.
importedTemplates found on WhatsApp that were not here.
Retrieve a template
Returns one WhatsApp template by id. Use it to refresh a single record you already know; to find records, use the list route. It includes its review status. Read only. 404 not_found when the id does not exist or belongs to another organization. You can repeat it safely: it has no side effects.
Required scope: whatsapp:read.
path Parameters
id^tpl_[0-9A-Za-z]{22}… · requiredThe id of the template (tpl_…).
Headers
Lelemon-Subaccount^sub_[0-9A-Za-z]{22}…The subaccount (sub_…) this request acts on. Only for the keys of a platform account; without it the request acts on the account itself.
Retrieve a template › Responses
objectidnamelanguagecategorystatusrejectionReasonbodyfooterbuttonsTexts of the buttons.
The buttons with their type, payload or link.
variablesThe variables of the body and of the links of the buttons.
createdAtupdatedAtDelete a template
Also deletes it on WhatsApp. Answers 409 resource_in_use while a trigger or an active campaign uses it.
Required scope: whatsapp:write.
path Parameters
id^tpl_[0-9A-Za-z]{22}… · requiredThe id of the template (tpl_…).
Headers
Lelemon-Subaccount^sub_[0-9A-Za-z]{22}…The subaccount (sub_…) this request acts on. Only for the keys of a platform account; without it the request acts on the account itself.
Delete a template › Responses
Update a template
WhatsApp does not allow changing the text of an approved template. Here you can only change which numbers can send it.
Required scope: whatsapp:write.
path Parameters
id^tpl_[0-9A-Za-z]{22}… · requiredThe id of the template (tpl_…).
Headers
Lelemon-Subaccount^sub_[0-9A-Za-z]{22}…The subaccount (sub_…) this request acts on. Only for the keys of a platform account; without it the request acts on the account itself.
Update a template › Responses
objectidnamelanguagecategorystatusrejectionReasonbodyfooterbuttonsTexts of the buttons.
The buttons with their type, payload or link.
variablesThe variables of the body and of the links of the buttons.
createdAtupdatedAtRender a template
The final text with your variables, without sending.
Required scope: whatsapp:read.
path Parameters
id^tpl_[0-9A-Za-z]{22}… · requiredThe id of the template (tpl_…).
Headers
Lelemon-Subaccount^sub_[0-9A-Za-z]{22}…The subaccount (sub_…) this request acts on. Only for the keys of a platform account; without it the request acts on the account itself.
Idempotency-KeyMakes the request safe to retry. Once it starts running, its final response (2xx, 4xx or 5xx) is kept for 24 hours and the same key gets it back, without repeating the effect. A request rejected before it runs leaves the key free. A replayed create omits the secret. The same key with a different request is rejected with 409 idempotency_key_reused.
Render a template › Responses
objecttextbuttonsSend a test message
Sends the template to one phone with the sample values it was created with, or yours. It opens no case. A phone that belongs to a contact who opted out of WhatsApp answers 422 contact_opted_out and nothing is sent. It sends a real message: use dryRun=true first, which runs the same checks (template approved, recipient allowlist, opt-out, variables, document, WhatsApp number) and answers 200 with the message as it would be created, sending nothing; its id is not saved.
Required scope: whatsapp:write.
path Parameters
id^tpl_[0-9A-Za-z]{22}… · requiredThe id of the template (tpl_…).
query Parameters
dryRunWhen true, the request goes through the same validation as the real one and is answered with what would happen (always 200), and nothing is saved, sent or charged. The answer has the same shape as the real one plus dryRun: true; an id in it is not saved. It does not use the Idempotency-Key.
Headers
Lelemon-Subaccount^sub_[0-9A-Za-z]{22}…The subaccount (sub_…) this request acts on. Only for the keys of a platform account; without it the request acts on the account itself.
Idempotency-KeyMakes the request safe to retry. Once it starts running, its final response (2xx, 4xx or 5xx) is kept for 24 hours and the same key gets it back, without repeating the effect. A request rejected before it runs leaves the key free. A replayed create omits the secret. The same key with a different request is rejected with 409 idempotency_key_reused.
Send a test message › Request Body
toBy default, the sample values the template was created with.
What the template needs besides its variables: image or video header, products, Flow data, cards.
Send a test message › Responses
dryRun=true: the message as it would be created; nothing is sent.
objectidstatustemplateIdcontactIdcaseIdsendAtskipReasonWhy it was skipped: opted_out, no_phone, template_not_approved, human_in_control, cooldown, not_allowed or canceled.
createdAtdryRunPresent and true when the request had dryRun=true.