Templates
Criar, listar, editar e sincronizar templates oficiais e seu ciclo de aprovação.
Templates são um conceito oficial (WABA): só existem para números oficiais. O broker é dono ponta a ponta — valida, submete à plataforma oficial, recebe o status. Um tenant só não-oficial recebe unsupported_capability ao tentar usá-los.
Ciclo de vida
Ao criar, o template fica pending (em revisão na plataforma oficial). A aprovação/rejeição chega de forma assíncrona pelo evento template.updated no seu webhook — não bloqueie esperando.
| status | significado |
|---|---|
pending | submetido, em revisão na plataforma oficial |
approved | aprovado — pode ser usado no envio |
rejected | rejeitado (veja rejectedReason) |
paused | pausado pela plataforma oficial |
disabled | desabilitado |
Criar
templates.create(input) recebe name, language, category (marketing / utility / authentication) e components agnósticos — o broker os valida e monta no formato da plataforma oficial. channelId é opcional com um único número oficial; obrigatório com mais de um.
const template = await wa.templates.create({
name: 'confirmacao_pedido',
language: 'pt_BR',
category: 'utility',
components: [
{ type: 'body', text: 'Pedido {{1}} confirmado, entrega {{2}}.', example: ['1234', 'amanhã'] },
{ type: 'footer', text: 'Sua Loja' },
],
})Resposta 201
{
"category": "utility",
"channelId": "ch_9f2c8a1b0d3e4f50",
"components": [
{
"example": {
"body_text": [
[
"John"
]
]
},
"text": "Hi {{1}}",
"type": "BODY"
}
],
"createdAt": "2026-08-04T12:00:00.000Z",
"id": "tpl_5a1c3e7f9b2d4068",
"language": "en_US",
"metaTemplateId": "meta-777",
"name": "welcome",
"rejectedReason": null,
"status": "pending",
"updatedAt": "2026-08-04T12:00:00.000Z"
}Listar e ler
// Paginado por cursor; filtro opcional por status
const page = await wa.templates.list({ status: 'approved', limit: 50 })
for (const t of page.items) console.log(t.name, t.language, t.status)
if (page.nextCursor) {
const next = await wa.templates.list({ cursor: page.nextCursor })
}
const one = await wa.templates.get(template.id)Resposta 200
{
"items": [
{
"category": "utility",
"channelId": "ch_9f2c8a1b0d3e4f50",
"components": [
{
"example": {
"body_text": [
[
"John"
]
]
},
"text": "Hi {{1}}",
"type": "BODY"
}
],
"createdAt": "2026-08-04T12:00:00.000Z",
"id": "tpl_5a1c3e7f9b2d4068",
"language": "en_US",
"metaTemplateId": "meta-777",
"name": "welcome",
"rejectedReason": null,
"status": "pending",
"updatedAt": "2026-08-04T12:00:00.000Z"
}
],
"nextCursor": null
}Resposta 200
{
"category": "utility",
"channelId": "ch_9f2c8a1b0d3e4f50",
"components": [
{
"example": {
"body_text": [
[
"John"
]
]
},
"text": "Hi {{1}}",
"type": "BODY"
}
],
"createdAt": "2026-08-04T12:00:00.000Z",
"id": "tpl_5a1c3e7f9b2d4068",
"language": "en_US",
"metaTemplateId": "meta-777",
"name": "welcome",
"rejectedReason": null,
"status": "pending",
"updatedAt": "2026-08-04T12:00:00.000Z"
}Editar
templates.update(id, input) edita de forma atômica (sem delete+create): novos components e, opcionalmente, category. name e language são imutáveis, então não entram. A edição devolve o template à revisão (volta a pending) e só vale para um template em estado editável.
await wa.templates.update(template.id, {
components: [
{ type: 'body', text: 'Pedido {{1}} confirmado. Entrega prevista: {{2}}.', example: ['1234', 'amanhã'] },
],
})Resposta 200
{
"category": "marketing",
"channelId": "ch_9f2c8a1b0d3e4f50",
"components": [
{
"example": {
"body_text": [
[
"Jane"
]
]
},
"text": "Hi again {{1}}",
"type": "BODY"
}
],
"createdAt": "2026-08-04T12:00:00.000Z",
"id": "tpl_5a1c3e7f9b2d4068",
"language": "en_US",
"metaTemplateId": "meta-777",
"name": "welcome",
"rejectedReason": null,
"status": "pending",
"updatedAt": "2026-08-04T12:00:00.000Z"
}Só approved ou rejected podem ser editados
approved ou rejected. Um pending (em revisão) ou nunca submetido responde template_not_editable (HTTP 409).Sincronizar e remover
templates.sync()reconcilia a partir da plataforma oficial sob demanda — devolve{ synced, created, updated }. Útil para alinhar mudanças feitas fora do broker.templates.delete(id)apaga na plataforma oficial e faz o soft-delete local. Resolvevoid.
const result = await wa.templates.sync()
await wa.templates.delete(template.id)Resposta 200
{
"created": 0,
"synced": 1,
"updated": 1
}Enviar um template aprovado
Com o template approved, envie por messages.send com content.kind: 'template'. Veja Enviar mensagens.