Sem modelo aprovado, você só responde
Esta é a regra que mais trava quem chega na API do WhatsApp, e ela não é da Zera: é da Meta. Você escreve o que quiser para quem falou com você nas últimas 24 horas. Para começar uma conversa fora disso, o texto precisa ter sido aprovado antes.
A regra, em uma frase. Quando uma pessoa manda uma mensagem para o seu número, abre uma janela de 24 horas em que você responde texto livre, imagem, áudio, o que for. Passadas as 24 horas sem ela escrever de novo, a janela fecha, e a única coisa que passa é um modelo aprovado.
Cada mensagem nova que ela mandar abre a janela outra vez. A regra inteira está em A janela de 24 horas.
É por isso que a maioria dos primeiros envios de quem integra não chega: o desenvolvedor testa com um número que nunca falou com a empresa, manda texto livre, recebe erro, e passa a tarde procurando defeito no código. O defeito não estava lá.
Ver os seus modelos
No painel, em Canais, no número, aba Modelos. A aba lê a Meta quando você abre e mostra, por modelo: o nome, a situação, a categoria, o idioma, a nota de qualidade e, quando a Meta devolve, o motivo da recusa. A leitura anterior é reaproveitada por dez minutos, então o que você vê pode ser de alguns minutos atrás; a data da leitura fica no topo, e o botão de atualizar força uma nova, respeitando um minuto entre duas.
O que essa aba não mostra, e vale saber antes de procurar:
- O texto do modelo. A leitura não pede o corpo, porque a tela não desenha o corpo. Para ver o texto, use o Gerenciador da Meta ou peça
componentsna chamada da Graph. - Entregues, taxa de leitura e cliques por modelo. Isso é outra chamada e outra permissão, que este produto nunca fez. Uma tabela com três colunas zeradas diria que os seus modelos não chegaram a ninguém, e seria mentira. Meia tabela verdadeira vale mais.
- Mais de cem modelos. A leitura traz cem numa página só, e a tela avisa quando existem mais. Acima disso, o caminho é a Graph, paginando.
A chamada exata que a aba faz está em Referência, com a mesma lista de campos.
Criar um modelo
Um modelo de texto você cria no próprio painel. Em Canais, no número, aba Modelos, no cartão Criar um modelo de texto. Você escreve o nome, escolhe o idioma e a categoria, escreve o texto com as variáveis e dá um exemplo para cada uma. A Zera envia para aprovação na Meta com a autorização daquele número e, logo depois, relê o modelo na Meta e mostra o que a releitura respondeu: o "ok" de uma escrita não é prova de nada, e quando a releitura não confirma a tela diz isso em vez de desenhar um modelo que talvez não exista.
O que o painel não faz, e por isso continua sendo na Meta: editar um modelo, apagar um modelo, criar modelo com cabeçalho, botão, mídia ou rodapé, e criar modelo da categoria de autenticação. Cada um desses tem um formato próprio que este formulário não monta, e mandar um campo plausível para a Meta é construir a recusa. Um formulário que faz menos e funciona vale mais do que um que promete botão e volta recusado.
Para esses casos, e para quem prefere fazer por programa, existem os dois caminhos de sempre.
Caminho 1: o Gerenciador da Meta
É o caminho de quem não quer escrever código para isso. Em business.facebook.com, com o mesmo acesso que autorizou a conexão do número, vá em WhatsApp Manager e depois em Modelos de mensagem. Você escreve, escolhe a categoria e o idioma, e envia para aprovação ali mesmo.
Caminho 2: a Graph, com o seu token
É o caminho de quem vai criar modelo por programa, ou de quem precisa de cabeçalho, botão, mídia ou rodapé. O formato abaixo vem da referência da Meta, e a autoridade sobre ele é ela. É a mesma chamada que o painel faz por você no cartão de criar, com o mesmo corpo de BODY.
curl -X POST "https://graph.facebook.com/v25.0/SEU_WABA_ID/message_templates" \
-H "Authorization: Bearer SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "confirmacao_de_pedido",
"language": "pt_BR",
"category": "UTILITY",
"components": [
{
"type": "BODY",
"text": "Olá {{1}}, o seu pedido {{2}} foi confirmado e sai hoje.",
"example": { "body_text": [ [ "Ana", "4821" ] ] }
},
{ "type": "FOOTER", "text": "Padaria Exemplo" }
]
}'
As barras invertidas no fim das linhas são a continuação de linha do terminal do Linux e do macOS, e o comando roda igual no Git Bash e no WSL. No Windows PowerShell 5.1, que é o que vem instalado no Windows, ele não roda: lá curl é apelido de outro comando, e o corpo perde as aspas no caminho até o programa. No PowerShell 7 ele roda. O jeito de escrever que serve no 5.1 está medido em O primeiro dia.
{
"id": "1234567890123456",
"status": "PENDING",
"category": "UTILITY"
}
As quatro partes de um modelo
- Nome. Só letras minúsculas, números e sublinhado. Nada de espaço, nada de acento. O nome é o que você usa no envio, e ele não aparece para quem recebe.
- Idioma. Um modelo vale para um idioma.
pt_BRept_PTsão modelos diferentes, com aprovações diferentes. Enviar com o código de idioma errado devolve erro mesmo com o modelo aprovado. - Categoria. São três, e a escolha é o que mais gera recusa.
- Componentes.
HEADER(opcional, texto ou mídia),BODY(obrigatório),FOOTER(opcional, texto curto) eBUTTONS(opcional).
As variáveis
As variáveis são {{1}}, {{2}} e assim por diante, numeradas em sequência a partir de 1. Três regras que economizam uma recusa:
- Mande sempre o
examplecom um valor plausível para cada variável. Sem exemplo, a Meta costuma recusar por formato. - Nunca comece nem termine o texto com uma variável, e nunca ponha duas variáveis coladas.
- No envio, a ordem dos parâmetros é a ordem dos números. Faltar um parâmetro derruba o envio inteiro, e não só a variável.
As três categorias
| Categoria | Para que serve | Exemplo |
|---|---|---|
UTILITY | Algo que a pessoa já pediu ou comprou: confirmação, atualização de status, lembrete de agendamento. | O seu pedido saiu para entrega. |
MARKETING | Oferta, novidade, convite, recuperação de carrinho. Qualquer coisa que a pessoa não pediu. | Chegou a nova coleção, com 20% na primeira compra. |
AUTHENTICATION | Código de acesso e verificação em duas etapas. Formato próprio e restrito. | O seu código é 482913. |
Essas três são as que a Meta aceita hoje quando você cria um modelo. O formulário do painel oferece duas, utilidade e marketing: a de autenticação tem formato próprio e restrito na Meta, que aquele formulário não monta, e oferecê-la ali seria oferecer uma recusa. Para criar um modelo de código de verificação, o caminho é o Gerenciador da Meta ou a Graph. O painel sabe traduzir mais duas categorias, OTP e TRANSACTIONAL, que são herança de um vocabulário antigo da Meta: se alguma delas aparecer na coluna Categoria, é modelo velho, e não erro da tela.
Duas coisas importam nessa escolha. A primeira: a Meta cobra preços diferentes por categoria, e a de marketing é a mais cara. O preço é dela, muda com o tempo e é cobrado direto de você, então o número que vale é o da tabela da Meta e o da fatura dela, nunca uma tabela nossa.
A segunda: a Meta reclassifica. Se você marcar como utilidade um texto que ela considera promoção, o modelo é recusado ou reclassificado. Um aviso de pedido com uma oferta enfiada no meio é o caso clássico.
Quanto tempo demora
Não existe prazo garantido, e esta página não inventa um. A Meta fala em análise em até 24 horas, e na prática muita coisa sai antes. A Zera não mede esse tempo, então quem responde é a Meta: a situação do modelo aparece na aba Modelos assim que ela muda.
As situações que você vai ver
| Situação | O que quer dizer |
|---|---|
APPROVED | Aprovado. Pode enviar. |
PENDING | Em análise na Meta. |
REJECTED | Recusado. O motivo aparece ao lado quando a Meta devolve. |
PAUSED | Pausado pela Meta por qualidade baixa. Volta sozinho, e é aviso sério. |
DISABLED | Desativado. É o passo seguinte ao pausado, quando a qualidade não melhora. |
IN_APPEAL | Em recurso, depois de você contestar a recusa. |
LIMIT_EXCEEDED | A conta passou do número de modelos que ela pode ter. |
PENDING_DELETION | Aguardando exclusão. |
DELETED | Excluído. |
Quando a Meta recusa
Modelo recusado não some e não bloqueia os outros: ele volta a valer depois de corrigido e reenviado para aprovação. O que muda tudo é ler o motivo, e o painel traz ele junto da linha vermelha, porque linha vermelha sem motivo é um beco.
A coluna Motivo da recusa só nasce quando algum modelo daquela conta veio com motivo: coluna sempre vazia afirmaria que a Meta não deu motivo para nenhum, e isso seria diferente de não ter havido recusa. Existe ainda um caso em que ela não aparece e não é por falta de motivo: quando a leitura precisou cair na consulta de reserva, sem o campo. Nesse caso a tela avisa, com essas palavras, que a leitura voltou sem a coluna.
| Motivo | O que ele está dizendo | O que costuma resolver |
|---|---|---|
INVALID_FORMAT |
O formato não segue o que a Meta exige: variável fora de lugar, botão inválido, texto malformado. | Conferir as variáveis (numeração em sequência, nunca no começo nem no fim, nunca coladas) e mandar o example. |
INCORRECT_CATEGORY |
A categoria escolhida não é a que a Meta considera correta para este texto. | Reenviar na categoria que o texto realmente é. Quase sempre é utilidade virando marketing. |
TAG_CONTENT_MISMATCH |
O conteúdo não corresponde à categoria escolhida. | Mesmo caminho do anterior, ou tirar do texto o trecho que não pertence à categoria. |
PROMOTIONAL |
A Meta marcou o texto como promocional. | Tirar a oferta de dentro de um modelo de utilidade, ou reenviar como marketing. |
ABUSIVE_CONTENT |
A Meta classificou o conteúdo como abusivo. | Reescrever. Vale conferir a Política de Comércio e a de Mensagens do WhatsApp antes de reenviar. |
SCAM |
A Meta classificou o conteúdo como tentativa de golpe. | Reescrever, tirando urgência artificial, prêmio, cobrança fora de contexto e link encurtado. |
NONE |
Não é motivo: é a ausência dele. A Meta manda NONE em todo modelo que ela não recusou. |
Nada a fazer. |
Se aparecer um motivo que não está nesta lista, o painel mostra o valor cru e avisa que não sabe traduzir, em vez de escrever uma causa que ninguém apurou. Nesse caso, mande para [email protected]: motivo novo entra nesta tabela.
Qualidade, pausa e desativação
Cada modelo tem uma nota de qualidade que a Meta calcula a partir do que as pessoas fazem depois de receber: bloquear e denunciar derrubam a nota. Verde é saudável, amarelo é aviso, vermelho é o passo antes da pausa.
Modelo pausado pela Meta é aviso de qualidade baixa, e ele é desativado se continuar assim. Nota caindo quase nunca é problema de um texto isolado: é volume alto para gente que não esperava a mensagem. A saída não é reescrever o modelo, é rever para quem ele está indo.
Enviar um modelo aprovado
É o mesmo endereço do envio de texto, com type igual a template. O language.code tem que ser exatamente o do modelo aprovado: modelo aprovado em pt_BR não é enviado como pt.
{
"messaging_product": "whatsapp",
"to": "5511987654321",
"type": "template",
"template": {
"name": "confirmacao_de_pedido",
"language": { "code": "pt_BR" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Ana" },
{ "type": "text", "text": "4821" }
]
}
]
}
}
Modelo sem variável nenhuma dispensa o components. O endereço completo da chamada está em Referência.
O que a Zera faz e o que ela não faz
- Faz: lê os seus modelos na Meta e mostra situação, categoria, idioma, qualidade e motivo da recusa, com a data da leitura.
- Faz: cria modelo de texto e envia para aprovação, com teto de dez por hora, e relê na Meta para confirmar que ele entrou de verdade.
- Não faz: editar nem apagar modelo, e não cria modelo com cabeçalho, rodapé, botão, mídia ou da categoria de autenticação. Esses continuam no Gerenciador da Meta.
- Não faz: analítica por modelo. Entregues, taxa de leitura e cliques não são lidos por este produto.
- Faz, se você pedir: escrever o texto e cuidar do envio para aprovação. É trabalho de gente, e não do painel. Escreva para [email protected].