Atualizado em 29/10/2026
Para enviar um template pela API do WhatsApp, faça um POST em /{phone-number-id}/messages com "type": "template", o name exato do template aprovado, o language.code em que ele foi criado e um array components com os valores das variáveis do cabeçalho, do corpo e dos botões. O texto fixo não vai no envio: você manda só os parâmetros, e eles precisam bater em quantidade, formato e ordem com o que foi aprovado.
Este guia traz um payload pronto para cada caso: só texto com variáveis posicionais e nomeadas, cabeçalho com imagem, vídeo ou documento (por link e por id), botão de URL dinâmica, quick reply com payload, código de cupom e um exemplo combinado. No fim, a tabela de erros de parâmetro mais comuns e como fazer o mesmo envio pela Vectalk.
Anatomia de um envio de template
Todo envio de template usa o mesmo endpoint da Cloud API que as outras mensagens:
POST https://graph.facebook.com/v26.0/{PHONE_NUMBER_ID}/messages
Authorization: Bearer {ACCESS_TOKEN}
Content-Type: application/json
O corpo tem sempre a mesma casca:
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "template",
"template": {
"name": "nome_do_template",
"language": { "code": "pt_BR" },
"components": []
}
}
Dentro de components, cada objeto tem um type que aponta para uma parte do template:
type do componente | Quando incluir | O que vai em parameters |
|---|---|---|
header | Cabeçalho com variável de texto ou com mídia | text, image, video, document ou location |
body | Corpo com variáveis | text (e também currency e date_time) |
button | Botão com valor dinâmico | Depende do sub_type: url, quick_reply, copy_code |
Se o template não tem variável nenhuma, components pode ficar de fora. O rodapé (footer) nunca aparece no envio, porque não aceita variáveis. Se você está começando e ainda não mandou nenhuma mensagem pela API, veja antes como enviar mensagem pela API do WhatsApp com cURL, Node.js e Python.
1. Template só texto com variáveis posicionais
É o formato padrão: se ninguém escolheu outro formato na criação, o template usa variáveis posicionais, {{1}}, {{2}} e assim por diante. Segundo a documentação de templates da Meta, os valores precisam vir na mesma ordem em que os placeholders aparecem no texto.
Template aprovado (corpo):
Olá {{1}}! Seu pedido {{2}} foi confirmado e chega em {{3}} dias úteis.
Envio:
curl -X POST "https://graph.facebook.com/v26.0/$PHONE_NUMBER_ID/messages" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "template",
"template": {
"name": "pedido_confirmado",
"language": { "code": "pt_BR" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Mariana" },
{ "type": "text", "text": "#48213" },
{ "type": "text", "text": "3" }
]
}
]
}
}'
Três placeholders, três objetos text, na ordem. Faltou um, sobrou um ou trocou o tipo: o envio falha (veja a tabela de erros mais abaixo).
Quer testar enquanto lê? Crie sua conta na Vectalk e envie a primeira mensagem pela API oficial. Criar conta grátis →
2. Template com variáveis nomeadas (parameter_name)
Na criação, o template pode declarar "parameter_format": "named". Aí as variáveis viram nomes como {{first_name}}, que precisam ser únicos e usar só letras minúsculas e sublinhado. No envio, cada parâmetro leva um parameter_name e, segundo a Meta, a ordem deixa de importar.
Template aprovado (corpo):
Obrigado, {{first_name}}! O número do seu pedido é {{order_number}}.
Envio:
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "template",
"template": {
"name": "confirmacao_pedido",
"language": { "code": "pt_BR" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "parameter_name": "order_number", "text": "SKBUP2-4CPIG9" },
{ "type": "text", "parameter_name": "first_name", "text": "Jéssica" }
]
}
]
}
}
Variáveis nomeadas deixam o código mais legível e evitam o erro clássico de trocar a ordem de dois valores. O formato é definido na criação e não no envio: mandar parameter_name para um template posicional (ou o contrário) é um erro de parâmetro. Como definir o formato na criação está no guia de criar, editar e excluir templates pela API.
Variáveis de moeda e data
Além de text, o corpo aceita parâmetros currency (com fallback_value, code e amount_1000, o valor multiplicado por 1.000) e date_time (com fallback_value), como mostra a página de mídia em templates. Mandar o valor já formatado como text também funciona.
3. Cabeçalho com imagem, vídeo ou documento
Se o template foi aprovado com cabeçalho de mídia, o envio precisa trazer a mídia em um componente header. A imagem de exemplo usada na criação serve só para a revisão; ela não é enviada ao cliente. O type do parâmetro é image, video ou document, e o objeto com o mesmo nome aceita link ou id:
| Opção | Como funciona | Quando usar |
|---|---|---|
link | URL HTTPS pública do arquivo no seu servidor | Arquivos que mudam a cada envio (boleto, nota fiscal) |
id | Media ID obtido no upload para os servidores da Meta | Mesma mídia para muitos destinatários (campanha) |
A Meta recomenda id, para reduzir erros e chamadas ao seu servidor, e avisa que o link precisa estar em servidor público, senão a mensagem falha. Quando você usa link, a Cloud API guarda o arquivo em cache por 10 minutos e reaproveita se a mesma URL aparecer de novo nesse intervalo; para forçar outro download, acrescente uma query string aleatória à URL, conforme a documentação de envio.
Imagem por link
{
"messaging_product": "whatsapp",
"to": "5511999999999",
"type": "template",
"template": {
"name": "promo_imagem",
"language": { "code": "pt_BR" },
"components": [
{
"type": "header",
"parameters": [
{ "type": "image", "image": { "link": "https://cdn.minhaloja.com.br/promo/outubro.jpg" } }
]
},
{
"type": "body",
"parameters": [
{ "type": "text", "text": "20%" }
]
}
]
}
}
Documento (PDF) por media ID
{
"messaging_product": "whatsapp",
"to": "5511999999999",
"type": "template",
"template": {
"name": "boleto_disponivel",
"language": { "code": "pt_BR" },
"components": [
{
"type": "header",
"parameters": [
{
"type": "document",
"document": { "id": "1013859600285441", "filename": "boleto-outubro.pdf" }
}
]
},
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Carlos" },
{ "type": "text", "text": "10/11/2026" }
]
}
]
}
}
O filename é opcional e vem do objeto de documento das mensagens de documento: o app usa a extensão para mostrar o ícone certo.
Para vídeo, a estrutura é a mesma: "type": "video" e um objeto video com link ou id.
Para gerar o media ID, faça o upload em POST /{PHONE_NUMBER_ID}/media. Limites de tamanho, formatos aceitos e o passo a passo do upload estão em como enviar imagem, PDF, áudio e vídeo pela API do WhatsApp.
4. Botão de URL dinâmica
Um botão de URL pode ter uma variável, sempre no fim da URL. Na criação, algo como https://minhaloja.com.br/pedido/{{1}}. No envio, você manda só o sufixo:
{
"messaging_product": "whatsapp",
"to": "5511999999999",
"type": "template",
"template": {
"name": "rastreio_pedido",
"language": { "code": "pt_BR" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "#48213" }
]
},
{
"type": "button",
"sub_type": "url",
"index": "0",
"parameters": [
{ "type": "text", "text": "48213?utm_source=whatsapp" }
]
}
]
}
}
Três regras que derrubam muita integração:
indexé a posição do botão no template, começando em 0. Se o botão de URL é o segundo botão aprovado, oindexé1. A Meta explica que, quando há botões com variável, tipo e ordem precisam bater com o template; mandar o índice errado gera um erro do tipo “Parameter value for URL was expected but was not found”.- Codifique caracteres especiais antes de enviar. A página de componentes cita espaço (
%20), dois-pontos (%3A), barra vertical (%7C) e letras acentuadas:GonçalvesviraGon%C3%A7alves. Valor sem codificação pode invalidar a URL e falhar o envio. - Botão de URL sem variável não entra no envio. Só inclua o componente
buttonse aquele botão tiver parte dinâmica.
Os exemplos da Meta usam index às vezes como string ("0") e às vezes como número (0). Escolha um e padronize no seu código. Se quiser medir o clique no GA4 com UTM nesse sufixo, veja o guia de botão de URL dinâmica com UTM.
5. Quick reply com payload
Botões de resposta rápida são definidos na criação com um texto fixo (até 25 caracteres) e não precisam de nada no envio. O que você pode mandar é um payload próprio, devolvido no webhook quando o cliente toca no botão. Isso permite saber exatamente qual campanha, pedido ou oferta gerou a resposta.
A sintaxe aparece na documentação de templates de carrossel, onde a Meta descreve o payload como opcional e entregue em messages.button.payload:
{
"messaging_product": "whatsapp",
"to": "5511999999999",
"type": "template",
"template": {
"name": "confirmar_consulta",
"language": { "code": "pt_BR" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Ana" },
{ "type": "text", "text": "05/11 às 14h" }
]
},
{
"type": "button",
"sub_type": "quick_reply",
"index": 0,
"parameters": [
{ "type": "payload", "payload": "confirmar:consulta:98765" }
]
},
{
"type": "button",
"sub_type": "quick_reply",
"index": 1,
"parameters": [
{ "type": "payload", "payload": "remarcar:consulta:98765" }
]
}
]
}
}
Quando a cliente toca em “Confirmar”, chega no webhook uma mensagem com "type": "button":
{
"context": { "from": "5511988880000", "id": "wamid.HBgLNTUx..." },
"from": "5511999999999",
"id": "wamid.HBgLNTUy...",
"timestamp": "1761750000",
"type": "button",
"button": { "payload": "confirmar:consulta:98765", "text": "Confirmar" }
}
O context.id é o wamid do template enviado, e o button.payload traz a sua chave. No exemplo da referência do webhook de botão, sem payload próprio, payload e text trazem o mesmo rótulo do botão. Lembre que, na criação, os botões de resposta rápida precisam ficar agrupados (todos antes ou todos depois dos outros tipos), e o template aceita até 10 deles.
6. Código de cupom (copy_code)
Templates de marketing podem ter um botão “copiar código”, que copia uma string de até 20 caracteres para a área de transferência do celular. No envio, o botão leva sub_type: "copy_code" e um parâmetro coupon_code, conforme a página de templates de cupom:
{
"messaging_product": "whatsapp",
"to": "5511999999999",
"type": "template",
"template": {
"name": "cupom_black_friday",
"language": { "code": "pt_BR" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "parameter_name": "coupon_code", "text": "BLACK25" },
{ "type": "text", "parameter_name": "discount", "text": "25%" }
]
},
{
"type": "button",
"sub_type": "copy_code",
"index": 0,
"parameters": [
{ "type": "coupon_code", "coupon_code": "BLACK25" }
]
}
]
}
}
Como na página da Meta, o exemplo usa um template com variáveis nomeadas no corpo; num template posicional, tire o parameter_name. Note que o código aparece duas vezes: uma no corpo (para o cliente ler) e outra no botão (para copiar). São campos independentes; se você gerar cupons únicos por cliente, preencha os dois com o mesmo valor. O template aceita um botão de copiar código.
7. Exemplo combinado: imagem, variáveis nomeadas, URL e quick reply
Na vida real, um template de marketing costuma juntar várias peças. Suponha um template aprovado com cabeçalho de imagem, corpo Oi {{first_name}}, a coleção {{collection}} chegou!, botão 0 de URL dinâmica e botão 1 de quick reply “Não quero receber”:
curl -X POST "https://graph.facebook.com/v26.0/$PHONE_NUMBER_ID/messages" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "5511999999999",
"type": "template",
"template": {
"name": "colecao_nova",
"language": { "code": "pt_BR" },
"components": [
{
"type": "header",
"parameters": [
{ "type": "image", "image": { "id": "1339522734477770" } }
]
},
{
"type": "body",
"parameters": [
{ "type": "text", "parameter_name": "first_name", "text": "Bruna" },
{ "type": "text", "parameter_name": "collection", "text": "Verão 2027" }
]
},
{
"type": "button",
"sub_type": "url",
"index": "0",
"parameters": [
{ "type": "text", "parameter_name": "slug", "text": "verao-2027" }
]
},
{
"type": "button",
"sub_type": "quick_reply",
"index": "1",
"parameters": [
{ "type": "payload", "payload": "optout:campanha_verao" }
]
}
]
}
}'
O parameter_name no botão de URL só se aplica se o template for nomeado e a URL usar {{slug}}; num template posicional, tire essa chave. Para cards com imagem e botão por card, a estrutura muda (componente carousel), e está no guia de template carrossel.
O campo language
language.code precisa ser exatamente o código com que o template foi criado. Um template chamado pedido_confirmado em pt_BR e outro de mesmo nome em en_US são dois templates diferentes. Alguns códigos da lista de idiomas suportados:
| Idioma | Código |
|---|---|
| Português (Brasil) | pt_BR |
| Português (Portugal) | pt_PT |
| Inglês (EUA) | en_US |
| Inglês (Reino Unido) | en_GB |
| Espanhol | es |
| Espanhol (México) | es_MX |
| Espanhol (Argentina) | es_AR |
| Espanhol (Espanha) | es_ES |
Mandou pt para um template criado em pt_BR? O resultado é o erro 132001, como se o template não existisse.
A resposta da API
Quando o envio é aceito, a API devolve:
{
"messaging_product": "whatsapp",
"contacts": [{ "input": "5511999999999", "wa_id": "5511999999999" }],
"messages": [{ "id": "wamid.HBgLMTY1MDM4Nzk0MzkVAgARGBJBRkJENzEx...", "message_status": "accepted" }]
}
Guarde o id (o wamid): é ele que aparece nos webhooks de status (sent, delivered, read, failed). O campo message_status só aparece quando o template está sob pacing. Resposta 200 significa “aceito”, não “entregue”; alguns erros de template só aparecem depois, no webhook com status: failed.
Erros comuns de parâmetro
Estes são os códigos que mais aparecem ao enviar templates, com a descrição da tabela de erros da Meta:
| Código | O que significa | Causa típica |
|---|---|---|
132000 | Quantidade de parâmetros diferente da definida no template | Faltou ou sobrou um text no corpo; esqueceu o componente do botão de URL dinâmica |
132001 | Template não existe no idioma informado ou não foi aprovado | language.code errado, nome com erro de digitação, template ainda PENDING |
132005 | Texto traduzido longo demais | Confira no WhatsApp Manager se a tradução do template está completa |
132007 | Conteúdo do template viola uma política do WhatsApp | Revise o conteúdo conforme as regras de revisão |
132012 | Parâmetros em formato diferente do especificado no template | parameter_name em template posicional (ou o inverso); text onde se esperava image |
132015 | Template pausado por baixa qualidade | Edite o template e aguarde nova aprovação |
132016 | Template pausado vezes demais e desativado de vez | Crie um template novo, com outro conteúdo |
131008 | Falta um parâmetro obrigatório | Campo obrigatório ausente, como language ou name |
131009 | Valor de parâmetro inválido | Valor fora do formato aceito em algum campo |
100 | Parâmetro não suportado ou escrito errado | Chave com erro de digitação (paramters, lenguage) |
A investigação detalhada de 132000 e 132012 tem um artigo próprio: erros 132000 e 132012. Para os demais códigos da API, veja o guia de erros da API do WhatsApp.
Um checklist rápido antes de abrir chamado:
- Abra o template no WhatsApp Manager (ou consulte pela API de templates) e confirme
status: APPROVED, idioma eparameter_format. - Conte os placeholders de cada componente e compare com os
parametersenviados. - Confira se cada botão com variável tem um componente
buttoncom oindexcerto. - Teste a URL de mídia em aba anônima e codifique os valores de URL dinâmica.
Quanto custa enviar um template
O preço depende da categoria do template e do país do destinatário. Para destino Brasil, desde 1º/10/2026 a Meta cobra R$ 0,3217 por template de marketing e R$ 0,0350 por template de utilidade ou autenticação. Também desde 1º/10/2026, templates de utilidade enviados dentro da janela de atendimento passaram a ser cobrados. Como a Meta decide a categoria está em marketing, utilidade ou autenticação.
Como enviar template com a Vectalk
A Vectalk é um proxy da Cloud API oficial: o corpo da requisição é o mesmo da Meta, mudam só a URL e o token. Todos os payloads deste artigo funcionam em POST https://apis.vectalk.com.br/api/messages; basta salvar o JSON em um arquivo e enviar:
curl -X POST https://apis.vectalk.com.br/api/messages \
-H "Authorization: Bearer $VECTALK_TOKEN" \
-H "Content-Type: application/json" \
-d @template.json
Com um token de instância, o phone_number_id é resolvido automaticamente. Com um token de organização, inclua "phone_number_id" no corpo para dizer de qual número sair, conforme a documentação de autenticação. A referência do envio está em Template na API da Vectalk.
Os templates em si você cria e acompanha no painel (Templates, com a Biblioteca de Modelos) ou pela API de templates, com token de instância. Na cobrança, cada mensagem entregue desconta do saldo pré-pago da sua conta, e você não precisa cadastrar cartão na Meta. Crie sua conta em apps.vectalk.com.br/register.
Perguntas frequentes
Preciso mandar o texto do template no envio?
Não. O texto fixo já está aprovado na Meta. No envio vão só o nome, o idioma e os valores das variáveis, da mídia do cabeçalho e dos botões dinâmicos.
Qual a diferença entre variável posicional e nomeada?
Posicional usa {{1}}, {{2}} e exige os valores na ordem do texto. Nomeada usa {{first_name}} e cada valor leva parameter_name, em qualquer ordem. O formato é escolhido na criação do template; se ninguém escolher, vale o posicional.
Posso trocar a imagem do cabeçalho a cada envio?
Sim. A imagem aprovada é só um exemplo para a revisão. Em cada envio você manda a mídia que quiser no componente header, por link ou id, desde que seja do mesmo tipo definido no template (imagem, vídeo ou documento).
Por que recebo 200 e a mensagem não chega?
O 200 só confirma que a API aceitou a requisição. Erros de template, de número ou de limite podem chegar depois, no webhook de status com failed e o código do erro. Monitore os webhooks, não só a resposta HTTP.
Fontes oficiais consultadas em 29/10/2026: Template fundamentals (Meta), Template components (Meta), Template media (Meta), Utility templates (Meta), Custom marketing templates (Meta), Coupon code templates (Meta), Media card carousel templates (Meta), Supported languages (Meta), Send messages (Meta), Document messages (Meta), Button messages webhook (Meta), Error codes (Meta), Envio de template na API da Vectalk, Autenticação na API da Vectalk.
Coloque o WhatsApp oficial da sua empresa para funcionar
Crie sua conta, conecte seu número à API oficial (dá para manter o app com coexistência) e comece a atender e enviar mensagens.
