Como Criar e Gerenciar Templates na WhatsApp Business API: Guia Completo
Guia end-to-end sobre o ciclo de vida de templates na WhatsApp Business API: criação via API, estrutura JSON, variáveis, categorias, aprovação do Meta e boas práticas para aprovar de primeira.
Templates são a espinha dorsal de qualquer integração séria com a WhatsApp Business API. Eles são obrigatórios para iniciar conversas com usuários (janela de 24h fechada), e qualquer mensagem proativa — cobrança, notificação de pedido, lembrete de agendamento — precisa passar por eles.
Este guia cobre o ciclo completo: criar, estruturar, submeter para aprovação e gerenciar templates, com exemplos de código prontos para produção.
O Que São Templates e Quando Usar
Templates (oficialmente Message Templates) são mensagens pré-aprovadas pelo Meta que você pode enviar fora da janela de 24 horas de atendimento. Quando uma conversa ativa existe (usuário respondeu nos últimos 24h), você pode enviar texto livre. Fora desse período, só templates aprovados funcionam.
Casos de uso comuns:
- Notificações de pedido — confirmação, envio, entrega
- Lembretes de agendamento — confirmação de consulta, follow-up
- Cobranças e faturas — vencimento de boleto, fatura disponível
- Autenticação OTP — código de verificação em dois fatores
- Marketing e promoções — ofertas, cupons, lançamentos (categoria Marketing)
Categorias de Templates
O Meta classifica todos os templates em três categorias. A categoria afeta o custo por conversa e as regras de conteúdo:
| Categoria | Uso | Custo |
|---|---|---|
| MARKETING | Promoções, ofertas, upsell | Mais alto |
| UTILITY | Transacionais: pedidos, cobranças, atualizações de conta | Médio |
| AUTHENTICATION | OTP, códigos de verificação | Mais baixo |
Atenção: O Meta pode reclassificar automaticamente seu template se o conteúdo não corresponder à categoria declarada. Declare corretamente desde o início.
Estrutura JSON de um Template
Todo template é composto por componentes. Os componentes disponíveis são:
{
"name": "notificacao_pedido",
"language": "pt_BR",
"category": "UTILITY",
"components": [
{
"type": "HEADER",
"format": "TEXT",
"text": "Pedido #{{1}} atualizado"
},
{
"type": "BODY",
"text": "Olá, {{1}}! Seu pedido #{{2}} foi {{3}} e chegará até {{4}}. Acompanhe em tempo real pelo link abaixo."
},
{
"type": "FOOTER",
"text": "Responda PARAR para cancelar notificações."
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "URL",
"text": "Rastrear Pedido",
"url": "https://seusite.com.br/rastrear/{{1}}"
}
]
}
]
}
Componente HEADER
O header é opcional, mas aumenta muito a taxa de abertura. Pode ser:
TEXT— Texto puro (suporta uma variável{{1}})IMAGE— URL pública de imagem (JPEG/PNG, até 5MB)VIDEO— URL pública de vídeo (MP4, até 16MB)DOCUMENT— URL pública de PDF
Para headers com mídia, você não fornece a URL no template em si — ela é passada dinamicamente ao enviar a mensagem.
Componente BODY
O body é o único componente obrigatório. Limite de 1024 caracteres. Suporta:
- Variáveis dinâmicas:
{{1}},{{2}},{{3}}... (indexadas a partir de 1) - Formatação básica:
*negrito*,_itálico_,~tachado~,``código``
Componente FOOTER
Texto estático (sem variáveis), máximo 60 caracteres. Ideal para aviso de opt-out.
Componente BUTTONS
Até 10 botões por template. Tipos disponíveis:
| Tipo | Descrição | Variável dinâmica |
|---|---|---|
| QUICK_REPLY | Resposta rápida (payload de texto) | Não |
| URL | Abre link no browser | Sim (sufixo da URL) |
| PHONE_NUMBER | Inicia ligação | Não |
| COPY_CODE | Copia código para área de transferência | Não (apenas autenticação) |
Regras de Variáveis
As variáveis seguem o padrão {{N}} onde N é um número inteiro sequencial começando em 1.
Regras críticas:
- Sem pulos de índice — Se você usa
{{1}}e{{3}}, o{{2}}também deve existir - Exemplos obrigatórios — Toda variável precisa de um exemplo no campo
example - Sem variáveis em footers — Footers são sempre estáticos
- URLs com variável — Só o sufixo pode ser variável:
https://seusite.com/{{1}}✅ |https://{{1}}.com❌
Exemplo correto com example:
{
"type": "BODY",
"text": "Olá, {{1}}! Seu pedido #{{2}} foi confirmado.",
"example": {
"body_text": [["João Silva", "BR-456789"]]
}
}
Criando um Template via API
Endpoint
POST https://graph.facebook.com/v21.0/{WABA_ID}/message_templates
Autenticação
Use um System User Token com permissão whatsapp_business_management. O token de teste temporário do painel não serve para produção.
curl -X POST \
"https://graph.facebook.com/v21.0/SEU_WABA_ID/message_templates" \
-H "Authorization: Bearer SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "confirmacao_agendamento",
"language": "pt_BR",
"category": "UTILITY",
"components": [
{
"type": "BODY",
"text": "Olá, {{1}}! Seu agendamento para {{2}} às {{3}} foi confirmado. Para cancelar, responda CANCELAR.",
"example": {
"body_text": [["Maria Souza", "consulta médica", "14:30"]]
}
},
{
"type": "FOOTER",
"text": "Responda PARAR para não receber mais."
}
]
}'
Resposta de Sucesso
{
"id": "123456789012345",
"status": "PENDING",
"category": "UTILITY"
}
O status inicial é sempre PENDING. Após a revisão do Meta, muda para APPROVED ou REJECTED.
Exemplos Práticos
Template com Header de Imagem
{
"name": "promocao_semana",
"language": "pt_BR",
"category": "MARKETING",
"components": [
{
"type": "HEADER",
"format": "IMAGE",
"example": {
"header_handle": ["https://seusite.com/banner-promo.jpg"]
}
},
{
"type": "BODY",
"text": "🔥 *Oferta exclusiva para {{1}}!*\n\nSó hoje: {{2}}% de desconto em toda a loja. Use o cupom *{{3}}* no checkout.",
"example": {
"body_text": [["você", "30", "FLASH30"]]
}
},
{
"type": "FOOTER",
"text": "Válido apenas hoje."
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "URL",
"text": "Aproveitar Oferta",
"url": "https://loja.seusite.com.br/promo/{{1}}",
"example": ["flash-sale"]
},
{
"type": "QUICK_REPLY",
"text": "Não tenho interesse"
}
]
}
]
}
Template com Botões Quick Reply e CTA
{
"name": "pesquisa_satisfacao",
"language": "pt_BR",
"category": "UTILITY",
"components": [
{
"type": "BODY",
"text": "Olá, {{1}}! Como foi sua experiência com o atendimento de {{2}}?\n\nSua opinião nos ajuda a melhorar. 🙏",
"example": {
"body_text": [["Carlos", "hoje"]]
}
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "QUICK_REPLY",
"text": "😊 Ótimo"
},
{
"type": "QUICK_REPLY",
"text": "😐 Regular"
},
{
"type": "QUICK_REPLY",
"text": "😞 Ruim"
}
]
}
]
}
Template de Autenticação OTP
{
"name": "codigo_verificacao",
"language": "pt_BR",
"category": "AUTHENTICATION",
"components": [
{
"type": "BODY",
"text": "Seu código de verificação é *{{1}}*. Válido por 10 minutos. Não compartilhe com ninguém.",
"example": {
"body_text": [["483920"]]
}
},
{
"type": "BUTTONS",
"buttons": [
{
"type": "COPY_CODE",
"example": "483920"
}
]
}
]
}
Para templates de autenticação com botão
COPY_CODE, o Meta exige que o body siga um formato específico. Usar a estrutura acima garante aprovação.
Processo de Aprovação do Meta
Após submeter, o template passa por revisão automatizada (e eventualmente humana):
- PENDING — Aguardando revisão (0–24h normalmente, pode chegar a 72h)
- APPROVED — Aprovado e pronto para uso
- REJECTED — Rejeitado com motivo (
rejection_reason) - PAUSED — Pausado por baixa qualidade (taxa de bloqueio elevada dos usuários)
- DISABLED — Desativado permanentemente por violações graves
Tempos médios de aprovação:
- Templates de
AUTHENTICATIONeUTILITYsimples: geralmente < 1 hora - Templates de
MARKETING: 2–24 horas - Templates com mídia ou botões de URL: pode levar mais
Consultando Status via API
curl "https://graph.facebook.com/v21.0/SEU_WABA_ID/message_templates?name=codigo_verificacao" \
-H "Authorization: Bearer SEU_TOKEN"
{
"data": [
{
"name": "codigo_verificacao",
"status": "APPROVED",
"id": "123456789012345",
"language": "pt_BR",
"category": "AUTHENTICATION"
}
]
}
Editando Templates Existentes
Você pode editar o conteúdo de um template aprovado, mas não pode alterar o nome, idioma ou categoria. A edição recoloca o template em PENDING.
curl -X POST \
"https://graph.facebook.com/v21.0/ID_DO_TEMPLATE" \
-H "Authorization: Bearer SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"components": [
{
"type": "BODY",
"text": "Olá, {{1}}! Seu agendamento para {{2}} às {{3}} está confirmado. Chegue 10 minutos antes. Para cancelar, responda CANCELAR.",
"example": {
"body_text": [["Ana Lima", "fisioterapia", "09:00"]]
}
}
]
}'
Excluindo Templates
Templates só podem ser excluídos se não estiverem sendo usados em conversas ativas. Após exclusão, o nome fica bloqueado por 30 dias.
curl -X DELETE \
"https://graph.facebook.com/v21.0/SEU_WABA_ID/message_templates?name=codigo_verificacao&hsm_id=ID_DO_TEMPLATE" \
-H "Authorization: Bearer SEU_TOKEN"
Boas Práticas para Aprovação Rápida
O Que o Meta Rejeita
Esses padrões causam rejeição imediata:
- Variáveis sem exemplo — Nunca submita um template sem o campo
examplepreenchido - Conteúdo ambíguo —
"Sua atualização chegou"sem contexto → rejeitado. Seja específico:"Seu pedido #{{1}} foi enviado" - URLs suspeitas ou encurtadas —
bit.ly/xpto→ rejeitado. Use sempre o domínio real - Mistura de idiomas no texto — Template declarado como
pt_BRcom trechos em inglês → inconsistência - Promoções disfarçadas de utility — Template
UTILITYcom linguagem claramente promocional → reclassificado e potencialmente rejeitado - Dados sensíveis explícitos — Não peça CPF, senha ou número de cartão no body
- Urgência excessiva —
"ÚLTIMO DIA!!!","CORRA!!!"— levanta flags de spam
O Que Garante Aprovação
- Exemplos realistas — Use dados de exemplo que realmente fazem sentido para o template
- Opt-out claro — Para marketing, inclua instrução de cancelamento no footer
- CTA específico —
"Ver meu pedido"é melhor que"Clique aqui" - Categoria correta — Não tente economizar colocando marketing como utility
- Texto natural — Escreva como um humano. Evite texto que pareça gerado por robô ou spam
Monitorando Qualidade Pós-Aprovação
Após aprovado, o Meta monitora se os usuários estão bloqueando mensagens enviadas pelo seu template. Se a taxa de bloqueio ultrapassar o threshold, o template vai para PAUSED e pode ser DISABLED.
Para manter a qualidade:
- Envie apenas para usuários que optaram em receber
- Não sobrecarregue com mensagens diárias de marketing
- Personalize as variáveis — mensagens genéricas têm mais bloqueios
Fluxo Completo em Node.js
const axios = require('axios')
const WABA_ID = process.env.WHATSAPP_WABA_ID
const TOKEN = process.env.WHATSAPP_TOKEN
async function createTemplate(templateData) {
try {
const response = await axios.post(
`https://graph.facebook.com/v21.0/${WABA_ID}/message_templates`,
templateData,
{
headers: {
Authorization: `Bearer ${TOKEN}`,
'Content-Type': 'application/json',
},
}
)
console.log('Template criado:', response.data)
return response.data
} catch (error) {
const errorData = error.response?.data?.error
console.error('Erro ao criar template:', errorData)
throw error
}
}
async function getTemplateStatus(templateName) {
const response = await axios.get(
`https://graph.facebook.com/v21.0/${WABA_ID}/message_templates`,
{
params: { name: templateName },
headers: { Authorization: `Bearer ${TOKEN}` },
}
)
return response.data.data[0]
}
// Exemplo de uso
const template = {
name: 'notificacao_entrega',
language: 'pt_BR',
category: 'UTILITY',
components: [
{
type: 'BODY',
text: 'Seu pedido #{{1}} foi entregue em {{2}}. Avalie sua experiência em: {{3}}',
example: {
body_text: [['BR-12345', '15/02/2026', 'https://avalie.seusite.com.br']],
},
},
],
}
createTemplate(template).then(async (created) => {
// Aguarda aprovação (polling simples)
let status = 'PENDING'
while (status === 'PENDING') {
await new Promise((r) => setTimeout(r, 30000)) // 30s
const info = await getTemplateStatus(template.name)
status = info.status
console.log(`Status: ${status}`)
}
console.log(`Template ${status === 'APPROVED' ? '✅ aprovado!' : '❌ rejeitado.'}`)
})
Resumo
Templates são o ponto de entrada para comunicação proativa no WhatsApp. Dominar a criação e o gerenciamento deles é fundamental para qualquer integração em produção.
Os pontos mais críticos:
- Preencha sempre o campo
example— é o erro mais comum de rejeição - Use a categoria correta — o Meta reclassifica e pode penalizar
- Monitore a qualidade — templates pausados afetam toda a conta
- Nomes e idiomas são imutáveis — planeje bem antes de criar
Com esses fundamentos, você tem tudo para criar templates que passam de primeira e funcionam de forma confiável em produção.