/templates) ou via API REST pública (/v1/templates) e o servidor MCP (templates_create / templates_update / templates_delete). Ao enviar, referencie o template pelo templateId e passe um objeto variables com chaves correspondentes.

Todo template tem uma chamada de API pronta — o modal Enviar via API do editor gera o curl exato com o templateId.
Todas as requisições usam o header
x-api-key: ps_... (ou x-api-key-id). URL base: https://pilotstatus.com.br/v1.Categoria
Definida no momento da criação; não pode ser alterada depois.- MARKETING — mensagens promocionais (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.
Estrutura do template
Apenas o body é obrigatório.Header
- API REST: passe
header.url(URL http(s) pública) ouheader.base64(data URI) — o base64 é re-hospedado no servidor automaticamente. - MCP:
header.urlapenas — base64 não é suportado via MCP.
Não existe header
LOCATION.Body
- Até 1024 caracteres.
- Variáveis escritas como
{{nome}}(estilo nomeado). - O body não pode começar nem terminar com uma variável.
- Emojis e múltiplas variáveis são permitidos.
Footer
Texto estático de até 60 caracteres. Sem variáveis.Buttons
Até 10 botões no total; botões de resposta rápida e CTA podem ser combinados.- Botão de URL dinâmica: a URL termina com uma variável (ex.:
https://loja.com/promo/{{link}}) — no máximo uma variável, nunca no domínio. O valor de exemplo vai emexamples. No envio, ela é preenchida pelo nome (variables.link). Um template criado no painel da Meta com placeholder numerado (https://ctlnk.io/{{1}}) é preenchido porbutton_<N>— veja Placeholders de botão em templates criados na Meta. - Copy-code: o valor vai no botão como
example(array, ex.:["PROMO10"]), somente alfanumérico, até 15 caracteres. Não serve para chave PIX ou e-mail — para PIX use o botãoPAYMENT_REQUESTabaixo. Em um número oficial esseexampleé só uma amostra: o código que o cliente copia vai emvariablescomobutton_<N>a cada envio — veja Botões de copiar código em números oficiais.
Botão de pagamento PIX (PAYMENT_REQUEST)
Botão de pagamento do WhatsApp Pay Brasil: o cliente toca e copia o código PIX. É o caminho certo para PIX copia-e-cola — o COPY_CODE trava em 15 caracteres alfanuméricos e um BR Code tem 100-400 caracteres com pontuação.
O código é por envio: escreva uma variável no example do botão e mande o valor real em variables no envio, como qualquer outra variável.
Esse botão depende de a Meta ter liberado pagamentos para a sua WhatsApp Business Account. A liberação é gradual e por conta — a própria Meta diz “this feature is rolling out and might not be available yet for your WhatsApp Business account”. Numa conta sem liberação, a Meta recusa a criação do template com
100 / subcode 2388128 (“Button at index 0 has unexpected type (PAYMENT_REQUEST)”). Não há como consultar essa permissão pela API — só tentando criar.ORDER_DETAILS (card de pedido itemizado) pode ser montado, pré-visualizado e salvo — veja Card de pedido itemizado.
- Botões são permitidos junto com um header de vídeo ou documento (PDF).
Variáveis & examples (obrigatório)
Ao criar/atualizar via REST ou MCP você deve incluir um objetoexamples mapeando cada variável usada (body + texto do header + URL dinâmica) para um valor de exemplo real. O valor do copy-code é a única exceção (ele fica no botão).
GET /v1/templates/{id} retorna todas as chaves detectadas no array variables de nível superior (um string[]) — forneça todas elas em variables no envio. Não há objeto latestVersion na resposta da API pública.
Placeholders de botão em templates criados na Meta
Um template criado no WhatsApp Manager da Meta e sincronizado no Pilot Status (source: "META") com placeholders posicionais numera a variável de um botão de URL dinâmica por conta própria: em https://ctlnk.io/{{1}}, esse {{1}} não é o {{1}} do body. Mande o valor dele como variables["button_<N>"], em que N é a posição do botão na lista de botões do template, 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:
GET /v1/templateseGET /v1/templates/{id}listam a chave emvariables—["1", "2", "3", "button_1"]para o template acima.- Um envio sem ela, ou com valor vazio, é recusado com
400 MISSING_TEMPLATE_VARIABLES(ouINVALID_TEMPLATE_VARIABLE_VALUE) nomeando a chave, em vez de ser aceito e falhar depois com o131008da Meta. - Placeholders nomeados não mudam: um botão criado no Pilot Status como
https://loja.com/promo/{{link}}é preenchido porvariables.link. - A mesma chave
button_<N>leva o código de um botão de copiar código num número oficial — veja abaixo.
Botões de copiar código em números oficiais
Para a Meta, o código digitado num botãoCOPY_CODE na criação é só um exemplo; o código que o cliente copia é um parâmetro obrigatório de todo envio. Por isso, num template aprovado pela Meta (source: "META" — todo template 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: N é a posição do botão na lista de botões do template, começando em 1, e todos os botões contam. Para os botões [QUICK_REPLY, COPY_CODE] com o exemplo PROMO10:
GET /v1/templateseGET /v1/templates/{id}listam a chave emvariables—button_4para o templatepromo_cupomde Criar via API REST.- Um envio sem ela, ou com valor vazio, é recusado com
400 MISSING_TEMPLATE_VARIABLES(ouINVALID_TEMPLATE_VARIABLE_VALUE) nomeando a chave. Oexamplemantém o limite da criação (15 caracteres alfanuméricos); para o código enviado, o limite da Meta é de 20 caracteres. - Um botão de copiar código cujo exemplo é uma variável nomeada (
["{{cupom}}"]) continua sendo preenchido porvariables.cupom. O botão de código de um template de autenticação (OTP) continua recebendo o código do body. - Números não oficiais (web/QR): o código também é gerado a cada envio — escreva-o no botão como
{{variável}}(ex.:["{{cupom}}"]) e preencha emvariables.
Limites de caracteres
Criar via API REST
bodypode ser um objeto (recomendado), uma string JSON ou texto simples (templates só de body).- Edite com
PUT /v1/templates/{id}(mesmo formato); remova comDELETE /v1/templates/{id}— para um template Meta isso também pede à Meta para excluí-lo, e a resposta depende do que a Meta faz (veja Excluir). GET /v1/templates/GET /v1/templates/{id}retornamsource(META|PILOT_STATUS),metaStatus(APPROVED|PENDING|REJECTED|DISABLED|null),metaLanguageesendable— em um número Meta apenas templatesMETAcommetaStatus: "APPROVED"são enviáveis.
Excluir
DELETE /v1/templates/{id} não retorna mais sucesso sempre. Para um template Meta a exclusão é encaminhada à Meta, e o resultado depende do que a Meta faz:
- Um
200 { "deleted": true, "id" }é a única resposta que significa que o template realmente sumiu — removido na Meta e localmente. - Um
409significa que nada foi removido: a Meta rejeitou a exclusão (ex.: o system token não tem permissão na WABA), então o template ainda existe na Meta e o nome dele continua reservado. O registro local é mantido, e a mensagem nomeia o template e o motivo. Corrija a permissão e tente de novo. - Se a Meta informar que o template não existe (um 404 de verdade / “template does not exist”), o registro local obsoleto é removido e você ainda recebe
200 { "deleted": true, "id" }.
Templates de carrossel
Um template de carrossel é um template aprovado cujobody carrega um bloco carousel: uma faixa rolável na horizontal com 2 a 10 cartões de mídia, cada um com sua própria imagem, linha de texto e botões. Templates de carrossel são exclusivos de números Meta e sempre da categoria MARKETING — em um número Meta a criação é enviada à Meta como um componente CAROUSEL.
Diferente do carrossel de sessão (interativo, somente resposta rápida — um botão de URL ali retorna 400), um cartão de carrossel de template pode combinar botões QUICK_REPLY e URL no mesmo cartão.
O bloco carousel
Ele fica dentro de body, ao lado de body.text — a mensagem exibida acima dos cartões (o corpo do carrossel).
Limites (validados na criação e na atualização)
Os mesmos limites e regras de mídia valem paraPOST (criar) e PUT (atualizar) — a validação não é mais pulada.
Mídia do cartão — cada
card.media.url deve ser uma URL https pública terminada em .png, .jpg, .jpeg ou .webp, sem query string. A Meta aceita uma imagem inacessível com 200 e depois não entrega nada, então a URL é buscada e recusada antes do envio, com um erro tipado que nomeia o cartão problemático.
Um
header de nível superior não é permitido com carousel (a mídia fica em cada cartão), e os botões dos cartões substituem os buttons de nível superior.Criar um template de carrossel
QUICK_REPLY + URL declarado em cardTemplate.buttons, nessa ordem. Um cartão que omite um botão, troca a ordem ou muda um tipo é recusado antes do envio.
Aprovação
- Números Meta: os templates são enviados à Meta para revisão (“Submit to Meta” em
/templates, ou ao salvar). Categorias, idioma e status seguem as regras da Meta. - Números não oficiais (Pilot Status web): os templates são criados localmente e ficam imediatamente utilizáveis — sem etapa de aprovação.
Não suportado
LOCATION (header ou botão), CATALOG/MPM, LIMITED_TIME_OFFER, OTP autofill/one-tap/zero-tap e botões VOICE_CALL. (O carousel de sessão — a variante fora de template — está na referência de Enviar mensagem.)
Botões FLOW são suportados em números Meta — veja Enviar um Flow. O ORDER_DETAILS (card de pedido itemizado) pode ser montado, pré-visualizado e salvo — veja Card de pedido itemizado para o comportamento por tipo de número.
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.
Erros de envio & rejeição
Botões de link/URL aceitam uma única variável que deve estar no final da URL e nunca no domínio; botões de chamada precisam do código do país (ex.:+55).
Verificado antes de enviar à Meta
Validação do lado da API
A Meta rejeitou o envio
Rejeitado após revisão
Bloqueios ao enviar (mesmo aprovado)
Erro comum ao enviar
404 — template sem uma versão aprovada (não existe para a chave, ou o template Meta ainda não tem versão aprovada).