/templates), pela API REST (/v1/templates) ou pelo servidor MCP (templates_create / templates_update / templates_delete). Ao enviar, referencie o modelo pelo templateId em POST /v1/messages/send e passe um objeto variables com chaves correspondentes.

A página de Templates — gere com IA, envie para a Meta e veja status de aprovação e categoria por template.
Categorias
A categoria é definida no momento da criação e não pode ser alterada depois:- MARKETING — mensagens promocionais (as mais sensíveis às políticas do WhatsApp).
- UTILITY — mensagens transacionais (atualizações de conta, alertas, lembretes).
- OTP — mensagens de código único / de verificação.
Aprovação da Meta vs. modelos locais
- Números oficiais (Meta): ao salvar um modelo com um número Meta selecionado, o painel pergunta se você deseja enviá-lo para revisão da Meta agora ou mantê-lo como rascunho e enviá-lo mais tarde. Uma vez enviado, categoria, idioma e status de aprovação seguem as regras da Meta. Um modelo só pode ser enviado em um número Meta depois de ter uma versão aprovada.
- Números não oficiais (Pilot Status web): os modelos são criados localmente e são imediatamente utilizáveis — não há etapa de aprovação.
GET /v1/templates trazem um campo source (de onde o modelo veio), um campo metaStatus (status de revisão da Meta, por exemplo PENDING, APPROVED, REJECTED) e uma flag sendable indicando se ele pode ser usado para envios agora.
Estrutura do modelo

O editor de template — nome, mídia, corpo com {{variáveis}}, botões, categoria (OTP/Utilidade/Marketing), idioma e geração por IA.
Valores de header de mídia: via REST passe
header.url (URL http(s) pública) ou header.base64 (data URI, re-hospedado automaticamente no servidor). Via MCP apenas header.url é aceito.
Não existe header
LOCATION. Também não são suportados: CATALOG/MPM, LIMITED_TIME_OFFER, preenchimento automático/one-tap/zero-tap de OTP e botões VOICE_CALL.Templates de carrossel são suportados em números Meta — categoria MARKETING, 2 a 10 cartões de mídia; veja Templates de carrossel.Botões FLOW são suportados em números Meta — eles abrem um Flow dentro da conversa. O botão amarra por flow_id, flow_name ou flow_json embutido. O ORDER_DETAILS (card de pedido itemizado) pode ser montado, pré-visualizado e salvo; a submissão à Meta é tentada na versão atual da Graph API e, quando a conta ainda não está elegível ao WhatsApp Pay, a recusa volta como um erro claro de elegibilidade em vez de um 400 críptico da Meta.Em números não oficiais (web) os templates suportam até 3 botões no total, e o preview do editor mostra exatamente como a mensagem é entregue para o número selecionado — incluindo a substituição ao vivo das {{variáveis}} com seus valores de exemplo.O parameter_format NAMED é suportado: um template criado no painel da Meta com variáveis nomeadas ({{nome_do_cliente}}) é importado com as variáveis certas e enviado com parameter_name em cada parâmetro.Botão de pagamento PIX (PAYMENT_REQUEST)
Entrega um código PIX copia-e-cola (BR Code). É o jeito certo de mandar PIX — o COPY_CODE limita em 15 caracteres alfanuméricos, enquanto um BR Code real tem 100-400 caracteres com pontuação. O botão funciona nos dois tipos de número, com renderização diferente:
- Números Meta (oficiais) — o card de pagamento do WhatsApp Pay (linha “Pagar com” + ícone do meio de pagamento), quando a conta tem pagamentos habilitados. Sem a habilitação, a Meta recusa o template com
100/ subcode2388128— a habilitação é gradual e por conta, e não há campo de API para consultar. - Números não oficiais (web) — entregue como um botão “Copiar código Pix” com o BR Code completo (sem limite de tamanho; validado em aparelhos reais). Ele combina normalmente com os demais botões do template, e o preview do editor mostra exatamente essa forma.
example do botão e passe o código real em variables na hora do envio, como qualquer outra variável.
Card de pedido itemizado (orderDetails)
Um template pode carregar um card de pedido itemizado — PEDIDO #referência, itens com quantidade, a linha “Pagar com” e o total — gravado como um bloco orderDetails (order com itens/subtotal/impostos em centavos inteiros, mais paymentSettings com o meio de pagamento). Comportamento por tipo de número:
- Meta (oficial) — o card é montado, pré-visualizado e salvo; a submissão à Meta é tentada na versão atual da Graph API e retorna um erro claro de elegibilidade quando a conta não tem WhatsApp Pay.
- Não oficial EVO_V2 — o card é entregável hoje (
review_and_pay). Quando o template também tem texto, botões ou mídia no header, eles são entregues primeiro como mensagem normal e o card de pedido vem numa segunda mensagem; se o card falhar depois da primeira mensagem entregue, o envio é marcado como falho (sem retry, pra não duplicar o texto). - Não oficial EVO_GO — não há card itemizado; quando o pedido tem trilho PIX, degrada para um botão “Copiar código Pix” anexado aos demais botões do template.
{{variáveis}} como qualquer outro campo. Campos numéricos — preço do item, quantidade, subtotal, impostos, total — também aceitam um único token {{variável}}: o exemplo precisa ser um inteiro não-negativo (em centavos), o valor real é substituído no envio, e um envio com valor numérico corrompido é recusado em vez de entregue com o valor errado.
Regras de variáveis
- Escreva variáveis como
{{name}}no body, no header de texto e em botões de URL dinâmica (por exemplohttps://shop.com/promo/{{link}}— uma variável, no fim da URL, nunca no domínio). - O body não pode começar nem terminar com uma variável — sempre inclua texto literal em ambas as extremidades.
- Ao criar/atualizar via API ou MCP, um objeto
examplesmapeando todas as variáveis a um valor de exemplo real é obrigatório. Amostras ausentes retornam400 TEMPLATE_EXAMPLES_REQUIREDcom as chaves faltantes emdetails.missing. - O valor do copy-code é a única exceção: ele vai no botão como
example(por exemplo["PROMO10"]), não emexamplesde nível superior. Em um número oficial esseexampleé só uma amostra — o código que o cliente copia vai emvariablescomobutton_<N>a cada envio (veja abaixo). - Ao enviar, todo marcador — incluindo chaves usadas apenas em botões — deve ser fornecido em
variables, e cada valor deve ser uma string não vazia. - Marcadores numerados em botões (modelos criados no painel da Meta). Um modelo criado no WhatsApp Manager da Meta e sincronizado no Pilot Status (
source: "META") com marcadores posicionais numera a variável de um botão de URL dinâmica por conta própria: emhttps://ctlnk.io/{{1}}, esse{{1}}não é o{{1}}do body. Forneça-o comovariables["button_<N>"], em queNé a posição do botão na lista de botões do modelo, começando em 1 — todos os botões contam, inclusive os estáticos. Passe só a parte variável (o sufixo da URL), não a URL inteira. Um envio sem essa chave, ou com valor vazio, é recusado com400 MISSING_TEMPLATE_VARIABLES(ouINVALID_TEMPLATE_VARIABLE_VALUE) nomeando a chave.
{{1}}, {{2}}, {{3}} no body e um único botão de URL https://ctlnk.io/{{1}}:
https://shop.com/promo/{{link}} é preenchido por variables.link.
Botões de copiar código em números oficiais. Para a Meta, o código digitado num botão de copiar código na criação é só um exemplo; o código que o cliente copia é um parâmetro obrigatório de todo envio. Por isso, num modelo aprovado pela Meta (source: "META" — todo modelo de um número oficial, criado no painel da Meta ou no Pilot Status), um botão de copiar código cujo valor não tem {{variável}} (um exemplo fixo como PROMO10) recebe o código como variables["button_<N>"], com a mesma regra de N. Para os botões [QUICK_REPLY, COPY_CODE] com o exemplo PROMO10:
400 MISSING_TEMPLATE_VARIABLES (ou INVALID_TEMPLATE_VARIABLE_VALUE) nomeando a chave. Um botão de copiar código cujo exemplo é uma variável nomeada (["{{cupom}}"]) continua sendo preenchido por variables.cupom, e o botão de código de um modelo de autenticação (OTP) continua recebendo o código do body. Em números não oficiais (web/QR) o código também é por envio: escreva-o no botão como {{variável}} e preencha em variables.
Formatação de texto
Marcadores de formatação do WhatsApp funcionam no body:*bold*, _italic_, ~strikethrough~, monospace. O header de texto não permite marcadores de formatação, emojis nem quebras de linha.
API de Modelos
201:
GET /v1/templates/{id} retorna todas as chaves de variáveis detectadas no array variables de nível superior (plano). Para um modelo criado no painel da Meta com marcador numerado em botão, o array também lista a chave button_<N> do botão (ex.: ["1", "2", "3", "button_1"]), e num número oficial lista a chave de um botão de copiar código sem {{variável}} — button_3 para o promo_coupon acima — forneça no envio todas as chaves que ele lista.
Erros comuns de envio e submissão
Um
404 ao enviar significa que o modelo não existe para a chave ou — em um número Meta — ainda não tem uma versão aprovada.