Mensagens de Template
Quando você precisa escrever primeiro para um cliente — recuperar um carrinho abandonado, avisar que um pedido está pronto, entregar um PIN de retirada — a mensagem tem que sair como um template aprovado pela Meta. Estes endpoints são a porta pública para pedir esse envio e para consultar onde ele parou.O que faz e o que não faz
Pré-requisitos
Para saber quais templates você pode enviar, consulte o catálogo.
GET /v1/templates lista os que
você tem aprovados, com o nome e o idioma exatos que esta chamada espera. Uma lista
vazia significa que nenhum foi aprovado ainda, e até que haja um cada envio é recusado.
O campo sendable de cada template diz se esta API consegue enviá-lo: é false quando o texto mistura variáveis por posição e por nome, numera com buracos ou tem variável no cabeçalho (esta API preenche só o corpo). Um template com sendable: false responde 422 ao enviar, e o ajuste é na Meta, não no seu request.Enviar uma mensagem
Campos do request
O identificador da sua empresa não viaja no request: ele é derivado da sua API key
(Autenticação). O template viaja sim, por nome e idioma, e é
validado contra os que você tem aprovados.
Respostas
Envio aceito — 202
Validamos, reservamos o event_id e entregamos ao serviço de envio. A resposta chega
assim que isso acontece e não traz o desfecho:
Sem envio novo — 200
Um 200 significa que esta requisição não produziu um envio. São dois casos:
- Um
event_idrepetido: devolve o estado guardado da primeira requisição, como descrito na seção de idempotência abaixo. - Um envio inviável de saída — o aviso está vencido, a conversa do cliente está em
pausa, ou o comerciante desligou o envio pelo painel: responde
"status": "discarded"com o motivo emstatus_detail(stale,pausedoudisabled). A requisição funcionou; o envio está desligado de propósito.
Idempotência
Mesmoevent_id = mesmo envio. Reenviá-lo devolve o estado da primeira requisição e
nunca gera um segundo WhatsApp. Por isso é seguro repetir depois de um timeout de rede.
A idempotência roda antes das validações de telefone, template e frescura: um reenvio
devolve o estado guardado sem julgar esses campos de novo. O que roda primeiro é a
forma do corpo — o charset do event_id, os tamanhos de template.name e
template.language, o parse de occurred_at. Um reenvio malformado recebe 422 e nunca
chega à idempotência.
Há um caso em que um event_id deixa de servir: se do lado do envio ele já ficou atrelado a
outra mensagem, ou saiu da janela de 30 dias, a resposta é 409 com
"type": "idempotency_conflict". Mande esse evento com um event_id novo — repetir o mesmo
devolve o mesmo 409. De propósito não guardamos estado sob a chave recusada: se
guardássemos, a próxima tentativa receberia um reenvio silencioso em vez do 409 que diz o
que corrigir.
Consultar o estado
“Enviado” não é “entregue”: a Meta reporta a entrega ao telefone minutos ou horas depois — ou nunca, se o telefone estiver desligado. Esse ciclo é consultado pelo seuevent_id:
event_id que nunca foi enviado responde 404; um que não respeita o charset responde
422.
Dois detalhes úteis na integração:
updated_até quando o registro mudou pela última vez, não quando você consultou. Consultar não o move, mas uma escrita de entrega que deixa ostatusigual move, então não o use como marca d’água: reconcilie peloevent_id.- Só
failedediscardedsão definitivos.sent,deliveredereadsão resolvidos de novo a cada consulta, porque ainda pode chegar um recibo posterior — inclusive um de falha depois de umread.
Janelas de tempo
Erros
Os erros seguem o formato padrão da API:Os dois
422 de conta se distinguem por detail[0].type, não pelo campo: eles chegam
com "loc": ["body"] porque não há um valor a corrigir. É o mesmo formato de array de
qualquer outro 422 — veja Tratamento de Erros. Já o 409 usa o formato
padrão e traz o seu type na raiz.Nem um aviso vencido, nem uma conversa em pausa, nem o envio desligado são erros: os três
respondem
200 com "status": "discarded" e "status_detail" em "stale", "paused"
ou "disabled". Uma pausa é posta por um agente humano que assumiu a conversa, ou por um
corte de faturamento; o desligamento é posto pelo comerciante no painel de carrinho
abandonado. Nenhum dos dois é levantado pela requisição.Receita: Shopify (Flow)
O Shopify Flow faz esse mesmoPOST sem código e sem um servidor seu no meio: é o exemplo
guiado do contrato acima, com o disparo do abandono já resolvido.
Usa Shopify? Siga a receita guiada →
Testar a integração
- Fase de teste — envie para telefones da sua própria equipe, em uma janela combinada. A mensagem chega de verdade, com o template real: essa é exatamente a prova.
- Fase produtiva — mesma key, mesmo contrato; só muda que os telefones são de clientes reais.

