Templates
Gerencie templates do WhatsApp Business: listar, criar, editar, remover e sincronizar da Meta.
Templates são mensagens pré-aprovadas pela Meta. Use-os para iniciar conversas ou reengajar contatos fora da janela de 24h.
GET /v1/templates
Lista templates do usuário.
Query: account_id (opcional; sem ele, retorna de todas as conexões do usuário).
Resposta 200: array de templates. status ∈ PENDING | APPROVED | REJECTED | QUALITY_POOR. category ∈ AUTHENTICATION | MARKETING | UTILITY. Templates de conexões soft-deletadas são omitidos.
Resposta 200
[
{
"id": "tpl_ckv...",
"name": "boas_vindas",
"language": "pt_BR",
"category": "MARKETING",
"status": "APPROVED",
"components": { },
"metaId": "987654321",
"whatsAppAccountId": "ckv...",
"userId": "usr_...",
"syncedAt": "2026-06-20T10:00:00.000Z",
"deletedAt": null,
"createdAt": "2026-06-01T00:00:00.000Z",
"updatedAt": "2026-06-20T10:00:00.000Z"
}
] POST /v1/templates
Cria um template na Meta + banco.
Body (JSON):
{
"account_id": "ckv...",
"name": "boas_vindas",
"category": "MARKETING",
"language": "pt_BR",
"components": [
{ "type": "BODY", "text": "Olá {{1}}, bem-vindo!" }
],
"allow_category_change": false
}
| Campo | Tipo | Obrigatório | Regras |
|---|---|---|---|
name | string | Sim | 1–512 chars, regex ^[a-z][a-z0-9_]*$ (minúsculas, dígitos, underscore) |
category | enum | Sim | AUTHENTICATION | MARKETING | UTILITY |
language | string | Sim | ≥ 2 chars (ex.: pt_BR) |
components | array | Sim | ≥ 1 componente (HEADER/BODY/FOOTER/BUTTONS/CAROUSEL) |
account_id | string | Não | opcional |
allow_category_change | boolean | Não | opcional |
Botões (type: BUTTONS)
Cada botão do componente BUTTONS é um destes quatro subtipos:
| Subtipo | Campos |
|---|---|
QUICK_REPLY | text (1–25 chars) |
URL | text, url, example (opcional — obrigatório para URL com variável) |
PHONE_NUMBER | text, phone_number |
COPY_CODE | text (opcional), example (opcional) |
Limites que o validador aplica no array buttons:
- máx 10 botões no total;
- máx 2 do subtipo
URL, máx 1PHONE_NUMBER, máx 1COPY_CODE; - botões
QUICK_REPLYprecisam ficar contíguos (não pode intercalar com outro subtipo no meio do bloco); URLcom variável ({{n}}naurl) só é aceita com a variável no final da string, e exigeexamplepreenchido.
{
"name": "confirmacao_pedido",
"category": "UTILITY",
"language": "pt_BR",
"components": [
{ "type": "BODY", "text": "Pedido {{1}} confirmado!" },
{
"type": "BUTTONS",
"buttons": [
{ "type": "QUICK_REPLY", "text": "Rastrear pedido" },
{ "type": "URL", "text": "Ver no site", "url": "https://loja.com/pedido/{{1}}", "example": ["9F8D"] },
{ "type": "PHONE_NUMBER", "text": "Falar com suporte", "phone_number": "+551140028922" }
]
}
]
}
Carrossel (type: CAROUSEL)
Regras que o validador aplica:
- só é aceito em
category=MARKETING—UTILITY/AUTHENTICATIONsão rejeitados; - exige de 2 a 10 cards — 1 card ou 11+ é rejeitado;
- cada card exige 1 ou 2 botões (componente
BUTTONSdentro do card) — card sem nenhum botão é rejeitado pela Meta na criação (400); - todos os cards precisam usar o mesmo formato de mídia no
HEADER(todosIMAGEou todosVIDEO— não pode misturar); - os botões precisam ter a mesma assinatura em todos os cards (mesma sequência de subtipos — ex.: todo card com
[QUICK_REPLY, URL], não pode um card ter[QUICK_REPLY]e outro[URL, PHONE_NUMBER]).
{
"name": "promo_carousel",
"category": "MARKETING",
"language": "pt_BR",
"components": [
{ "type": "BODY", "text": "Confira as novidades!" },
{
"type": "CAROUSEL",
"cards": [
{
"components": [
{ "type": "HEADER", "format": "IMAGE", "example": { "header_handle": ["<handle da Resumable Upload API>"] } },
{ "type": "BODY", "text": "Produto A" },
{ "type": "BUTTONS", "buttons": [{ "type": "QUICK_REPLY", "text": "Quero esse" }] }
]
},
{
"components": [
{ "type": "HEADER", "format": "IMAGE", "example": { "header_handle": ["<handle da Resumable Upload API>"] } },
{ "type": "BODY", "text": "Produto B" },
{ "type": "BUTTONS", "buttons": [{ "type": "QUICK_REPLY", "text": "Quero esse" }] }
]
}
]
}
]
}
Para enviar o template carrossel, ver /docs/messages (campo carousel).
Resposta 201: o template criado (mesmo shape do GET), com metaId e status retornados pela Meta.
curl -X POST https://api.wablastmessage.com/v1/templates \
-H "Authorization: Bearer wak_sua_chave" \
-H "Content-Type: application/json" \
-d '{
"name": "boas_vindas",
"category": "MARKETING",
"language": "pt_BR",
"components": [{ "type": "BODY", "text": "Olá {{1}}, bem-vindo!" }]
}'const res = await fetch('https://api.wablastmessage.com/v1/templates', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + process.env.WABLAST_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'boas_vindas',
category: 'MARKETING',
language: 'pt_BR',
components: [{ type: 'BODY', text: 'Olá {{1}}, bem-vindo!' }],
}),
});
console.log(res.status, await res.json());import os, requests
res = requests.post(
'https://api.wablastmessage.com/v1/templates',
headers={'Authorization': 'Bearer ' + os.environ['WABLAST_API_KEY']},
json={
'name': 'boas_vindas',
'category': 'MARKETING',
'language': 'pt_BR',
'components': [{'type': 'BODY', 'text': 'Olá {{1}}, bem-vindo!'}],
},
)
print(res.status_code, res.json())<?php
$ch = curl_init('https://api.wablastmessage.com/v1/templates');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . getenv('WABLAST_API_KEY'),
'Content-Type: application/json',
]);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'name' => 'boas_vindas',
'category' => 'MARKETING',
'language' => 'pt_BR',
'components' => [['type' => 'BODY', 'text' => 'Olá {{1}}, bem-vindo!']],
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$res = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE) . " " . $res; PUT /v1/templates/{id}
Edita um template (não pode estar PENDING).
Path: id (obrig.).
Body (JSON): ao menos um de:
{ "category": "UTILITY", "components": [] }
Após editar, o status volta a PENDING (re-aprovação Meta).
Tentar editar template com status PENDING retorna 400 TEMPLATE_PENDING — aguarde a Meta aprovar/rejeitar antes.
DELETE /v1/templates/{id}
Remove um template (Meta + banco).
Resposta 200:
{ "success": true }
404 da Meta é tratado como idempotente (template já removido na Meta → trata como sucesso).
POST /v1/templates/sync
Puxa os templates aprovados da Meta para o banco (upsert/revive + prune dos que sumiram).
Body (JSON):
{ "account_id": "ckv..." }
account_id opcional (default = conexão padrão).
Resposta 200:
{ "synced": 3, "updated": 5, "pruned": 1 }
| Campo | Significado |
|---|---|
synced | criados no banco |
updated | já existiam, atualizados |
pruned | soft-deletados (sumiram da Meta) |