← Blog

·

Como enviar template pela API do WhatsApp: variáveis, mídia no cabeçalho e botões (JSON completo)

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 componenteQuando incluirO que vai em parameters
headerCabeçalho com variável de texto ou com mídiatext, image, video, document ou location
bodyCorpo com variáveistext (e também currency e date_time)
buttonBotão com valor dinâmicoDepende 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çãoComo funcionaQuando usar
linkURL HTTPS pública do arquivo no seu servidorArquivos que mudam a cada envio (boleto, nota fiscal)
idMedia ID obtido no upload para os servidores da MetaMesma 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, o index é 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çalves vira Gon%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 button se 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:

IdiomaCódigo
Português (Brasil)pt_BR
Português (Portugal)pt_PT
Inglês (EUA)en_US
Inglês (Reino Unido)en_GB
Espanholes
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ódigoO que significaCausa típica
132000Quantidade de parâmetros diferente da definida no templateFaltou ou sobrou um text no corpo; esqueceu o componente do botão de URL dinâmica
132001Template não existe no idioma informado ou não foi aprovadolanguage.code errado, nome com erro de digitação, template ainda PENDING
132005Texto traduzido longo demaisConfira no WhatsApp Manager se a tradução do template está completa
132007Conteúdo do template viola uma política do WhatsAppRevise o conteúdo conforme as regras de revisão
132012Parâmetros em formato diferente do especificado no templateparameter_name em template posicional (ou o inverso); text onde se esperava image
132015Template pausado por baixa qualidadeEdite o template e aguarde nova aprovação
132016Template pausado vezes demais e desativado de vezCrie um template novo, com outro conteúdo
131008Falta um parâmetro obrigatórioCampo obrigatório ausente, como language ou name
131009Valor de parâmetro inválidoValor fora do formato aceito em algum campo
100Parâmetro não suportado ou escrito erradoChave 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:

  1. Abra o template no WhatsApp Manager (ou consulte pela API de templates) e confirme status: APPROVED, idioma e parameter_format.
  2. Conte os placeholders de cada componente e compare com os parameters enviados.
  3. Confira se cada botão com variável tem um componente button com o index certo.
  4. 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.