Para gestores de tráfego
API de Conversões (CAPI) para WhatsApp: como mandar a venda de volta para a Meta, na prática
O que é a CAPI para mensagens, quais eventos e campos a Meta aceita, os erros 2804066, 2804069 e 2804071 e como testar sem contaminar a otimização.
Rastrear conversão no WhatsApp é diferente de rastrear no site por um motivo simples: não existe pixel dentro de uma conversa. O único caminho para a Meta saber que uma conversa virou venda é o seu servidor contar para ela. Esse caminho é a API de Conversões (CAPI), e para mensagens ela tem um vocabulário, campos e validações próprios.
Este guia é técnico e prático. Cobre o que a CAPI de mensagens é, as três origens de evento, a anatomia de um evento válido, o vocabulário aceito, os erros em cadeia que a Meta devolve (com os subcódigos reais), de onde vem o ctwa_clid, como testar sem contaminar a otimização e como tratar deduplicação e reenvio.
O que é a API de Conversões (e por que o pixel não resolve no WhatsApp)
A API de Conversões é uma interface servidor-a-servidor: o seu sistema envia eventos (lead, compra, agendamento) diretamente para um conjunto de dados da Meta, sem depender do navegador. No site, ela complementa o pixel. No WhatsApp, ela é o único canal, porque a conversa não roda num navegador que a Meta consiga observar.
A Meta trata eventos de mensagem como uma categoria própria, com action_source igual a business_messaging. É nessa categoria que a otimização de campanhas de clique para o WhatsApp acontece. A documentação oficial está em Conversions API for Business Messaging, e vale a leitura, mas ela não conta o que dá errado. Este guia conta.
As três origens que interessam a quem vende pelo WhatsApp
action_source | Quando usar | Atribui à campanha? | Exige |
|---|---|---|---|
business_messaging | Conversa que começou num clique de anúncio de WhatsApp (ou Instagram/Messenger) | Sim, pelo ctwa_clid | Nome de evento do vocabulário de mensagens, identidade do número, ctwa_clid |
website | Lead que clicou num link rastreável e foi para o WhatsApp a partir de uma página sua | Sim, pelo fbclid/fbc e correspondência de dados | event_source_url, dados do usuário hasheados |
chat | Conversa orgânica (indicação, número salvo, link sem rastreio) | Não | Dados do usuário hasheados (telefone) |
A escolha da origem é por conversa, não por conta. O mesmo número recebe conversas de anúncio (business_messaging), de link do site (website) e orgânicas (chat). Um sistema correto resolve a origem de cada evento a partir do que sabe daquela conversa: houve clique de anúncio com identificador? Houve link rastreável? Nada? A regra é: link rastreável → website; conversa de anúncio com identidade do número → business_messaging; o resto → chat.
Anatomia de um evento de mensagem válido
Um Purchase enviado para business_messaging, com número conectado pelo WhatsApp Business App (sem WABA, então com page_id):
POST https://graph.facebook.com/v21.0/{DATASET_ID}/events
{
"data": [{
"event_name": "Purchase",
"event_time": 1757865600,
"event_id": "lead-8f2c1a-won",
"action_source": "business_messaging",
"messaging_channel": "whatsapp",
"user_data": {
"page_id": "123456789012345",
"ctwa_clid": "ARAo7…(identificador do clique)…",
"ph": ["<sha256 do telefone em E.164, sem + e sem espaços>"]
},
"custom_data": {
"currency": "BRL",
"value": 1960.00
}
}],
"access_token": "<token com permissão no dataset>"
}
Campo por campo:
event_name: do vocabulário de mensagens (abaixo).Purchaseé aceito;Leadnão.event_time: timestamp Unix em segundos do momento da venda. Eventos muito antigos são recusados; envie perto do fato.event_id: identificador estável do evento no seu sistema. Permite reenviar sem duplicar.action_source:business_messaging.messaging_channel:whatsapp(ouinstagram,messenger).user_data.page_idouuser_data.whatsapp_business_account_id: a identidade do número. WABA quando o número está na API oficial; ID da Página do Facebook que roda os anúncios quando o número é do WhatsApp Business App.user_data.ctwa_clid: o identificador do clique. Sem ele, nada é atribuído.user_data.ph: telefone hasheado com SHA-256, normalizado (só dígitos, com DDI). Melhora a correspondência.custom_data.valueecurrency: obrigatórios paraPurchasese você quer otimização por valor e ROAS no relatório.
Vocabulário de eventos aceito em business_messaging
Os dois que importam para a maioria das operações:
LeadSubmitted: lead qualificado. É o equivalente doLeadde site.Leadé rejeitado nesta origem.Purchase: venda, com valor.
Outros eventos padrão (como Schedule, AddToCart, InitiateCheckout, ViewContent) são aceitos conforme o caso de uso. Se a sua integração já usa Lead para site, mantenha um mapeamento na camada de envio: Lead vira LeadSubmitted quando a origem é business_messaging. Guarde o nome efetivamente enviado no seu banco, para o relatório bater com o Gerenciador de Eventos.
Os erros em cadeia e como resolver
A Meta valida em sequência. Cada correção revela o próximo erro. Os subcódigos vêm no campo error_subcode e a explicação em error_user_msg da resposta. Guarde a resposta inteira: é o seu diagnóstico.
| Subcódigo | O que a Meta diz | Causa real | Correção |
|---|---|---|---|
| 2804066 | O nome do evento não é válido para esta origem | Lead em business_messaging | Mapear para LeadSubmitted |
| 2804069 | Não há page_id (ou WABA) | Número por QR sem identidade cadastrada | Enviar user_data.page_id com o ID da Página que roda os anúncios |
| 2804071 | Não há ctwa_clid | Conversa não nasceu de clique, ou o identificador não foi capturado | Capturar no webhook; rebaixar conversa orgânica para chat |
| 190 | Token inválido ou expirado | Token de usuário vencido, ou permissões removidas | Renovar token; preferir token de usuário do sistema |
O ponto que engana todo mundo está no 2804071. Depois de corrigir os dois primeiros, os eventos passam a sair como business_messaging e voltam a ser recusados para todas as conversas orgânicas. A regra real da Meta: business_messaging exige identidade do número e clique, juntos. Conversa orgânica nunca é aceita nessa origem, e o correto é enviá-la como chat. Se você olhar os eventos de um cliente novo e ver 100% como chat, não é bug: ele ainda não rodou anúncio de clique para o WhatsApp, e toda conversa é orgânica.
De onde vem o ctwa_clid
O ctwa_clid é gerado pela Meta no clique e entregue com a primeira mensagem da conversa que nasceu daquele anúncio.
- API oficial (Cloud API): no webhook de mensagem, dentro de
messages[].referral, junto comsource_id(ID do anúncio),source_type,headlineebodydo anúncio. - WhatsApp Business App conectado por QR (via Evolution API ou similar): nos metadados da mensagem (
contextInfo.externalAdReply), com octwaClide o ID do anúncio. É um caminho de melhor esforço, mas funciona na prática e permite atribuir sem migrar o número para a API oficial.
Guarde o ctwa_clid na conversa (não na mensagem) no primeiro contato. Ele é a chave de tudo o que vem depois: atribuição, ROAS por campanha e o envio de eventos. Mais sobre os mecanismos de atribuição em qual anúncio gerou a venda no WhatsApp.
Testando sem contaminar a otimização
- No Gerenciador de Eventos, aba "Testar eventos", pegue o
test_event_code. - Envie os eventos com o campo
test_event_codeno corpo. Eles aparecem na aba de teste em segundos, com os erros de validação. - Corrija até ver "recebido" com correspondência do
ctwa_clid. - Remova o
test_event_code. Evento com código de teste não conta para otimização nem para relatório. Uma integração "funcionando" com o código de teste esquecido é uma integração que não faz nada. - Confirme na aba de visão geral, origem "mensagens de negócios", que os eventos reais estão chegando.
Deduplicação, reenvio e fila
Três cuidados de engenharia que separam uma integração confiável de uma que "às vezes funciona":
event_idestável. Derive do ID do lead e do tipo de evento (lead-<id>-won). Reenviar o mesmo evento não cria duplicata.- Fila com retentativa. O envio para a Meta não pode acontecer dentro do fluxo que salva a venda. Salve primeiro, enfileire depois. Se a Meta estiver fora, o evento espera; se o seu Redis cair, o evento não pode se perder. Uma varredura periódica que reprocessa o que ficou pendente resolve os casos de borda.
- Fila de rejeitados com reenvio manual. Guarde a resposta da Meta em cada tentativa e exponha um botão "reenviar" que normaliza o payload antes (por exemplo, rebaixando para
chatum evento que perdeu a atribuição). Depois que você corrige opage_idda integração, os rejeitados antigos por 2804069 podem ser reenviados e aceitos.
Fazer na mão ou usar uma ferramenta
Fazer na mão é viável para quem tem desenvolvedor e um cliente só. O trabalho real não está no envio (uma requisição HTTP), está em: capturar o ctwa_clid nos dois tipos de conexão, resolver a origem por conversa, manter o mapeamento de nomes, tratar token expirado, enfileirar com retentativa, guardar a resposta da Meta, expor reenvio, e ligar tudo isso a um funil onde alguém marca "vendido" com valor. Multiplique por cliente.
Uma ferramenta que já faz isso custa menos do que uma semana de desenvolvimento, e o gestor de tráfego passa a olhar para o que importa: qual evento enviar, com que critério, e o que a campanha faz com ele.
Perguntas frequentes
O que é a API de Conversões para WhatsApp?
É a forma de o seu servidor enviar para a Meta eventos que aconteceram dentro de uma conversa (lead qualificado, venda, agendamento), com action_source business_messaging. Como não existe pixel numa conversa, é o único caminho para a Meta atribuir e otimizar campanhas de clique para o WhatsApp.
Por que meus eventos de WhatsApp são rejeitados pela Meta?
Quase sempre por um de três motivos, em ordem: nome de evento inválido (Lead em vez de LeadSubmitted, subcódigo 2804066), falta de identidade do número (page_id ou WABA, 2804069) ou falta de ctwa_clid (2804071). A resposta da Meta traz o subcódigo; guarde-a.
O que é ctwa_clid?
É o identificador do clique num anúncio de clique para o WhatsApp. A Meta o entrega junto com a primeira mensagem da conversa (no referral da API oficial ou nos metadados da mensagem no WhatsApp Business App). Sem ele, o evento não é atribuído a nenhuma campanha.
Posso enviar eventos de conversas orgânicas?
Pode, com action_source chat, para registro e correspondência de dados. Mas eles não são atribuídos a campanhas nem servem para otimizar, porque não têm clique. Enviar orgânicas como business_messaging gera rejeição 2804071.
Preciso da API oficial do WhatsApp (WABA) para usar a CAPI?
Não. Com o número no WhatsApp Business App conectado por QR, a Meta aceita o ID da Página do Facebook que roda os anúncios no campo page_id. O ctwa_clid também chega por esse caminho.


