O que muda na API
Mudanças de endpoint, de envelope de webhook e de comportamento, em ordem cronológica. Campos novos são aditivos: nada que você já recebe deixa de vir sem aviso aqui.
Adição é compatível com o que você já faz. Correção muda o que você recebe na direção do que estava documentado. Requer atenção muda o comportamento de quem não fizer nada.
- Requer atençãoChatwootWhatsApp Oficial
Janela de 24h: mensagem livre fora dela deixa de ser enviada
Na conta oficial, passadas 24h da última mensagem do cliente, o texto livre não é mais tentado: ou sai como modelo aprovado, ou vira aviso na conversa.
A Meta recusa qualquer mensagem livre fora da janela de 24h. Até agora a tentativa saía daqui, era recusada lá e o erro ficava só no log: o atendente via a mensagem como enviada.
O que muda:
- Se o texto que o atendente escreveu corresponde a um modelo aprovado, o envio sai como modelo e a conversa reabre. As variáveis são extraídas do próprio texto, então ele pode editar o modelo antes de mandar.
- Se não corresponde, nada é enviado: uma nota privada explica o motivo e a mensagem fica marcada como falha.
POST /chatwoot/templates/syncpublica os modelos aprovados como respostas prontas (atalhotpl_<nome>), que é como o atendente dispara um sem sair do painel.
Quando não sabemos quando o cliente falou pela última vez, o envio segue normalmente — a Meta continua sendo quem decide.
- CorreçãoChatwoot
Chatwoot: a conta passa a ser descoberta pela caixa de entrada
Quem usa um único Token de Acesso para várias contas do Chatwoot tinha as mensagens enviadas pelo celular escritas na conta errada — ou recusadas com 404.
O
account_idera descoberto pelo perfil do Token de Acesso, que devolve a conta ativa do usuário — e ela não tem relação com a conta dona da caixa de entrada configurada. Num bot de automação que atende dezenas de contas com um token só, isso apontava para a conta errada.Agora a conta é descoberta procurando o
inbox_identifierconfigurado nas caixas de entrada de cada conta que o token enxerga. Quando a varredura não acha a caixa em nenhuma delas, nada é escrito: o log explica o motivo, em vez de a mensagem ir parar na conversa de outro cliente.Nenhuma ação é necessária de sua parte. Se a sua integração estava funcionando, ela continua igual.
- CorreçãoChatwootWhatsAppWhatsApp Oficial
Chatwoot: cinco falhas no espelho das conversas
Mensagem com mídia que não pôde ser baixada deixava de aparecer no painel; riscos de entregue/lido não funcionavam no WhatsApp não oficial; anexos além do primeiro eram descartados.
Uma auditoria da integração encontrou cinco problemas, todos corrigidos:
- Mensagem do cliente sumia quando a mídia não podia ser baixada (arquivo acima de 40 MB, download recusado). O Chatwoot recusa mensagem sem conteúdo e sem anexo, e a conversa ficava sem rastro. Agora chega um aviso no lugar do silêncio.
- Riscos de entregue e lido nunca funcionaram no WhatsApp não oficial: dependiam de uma configuração do seu webhook que nasce desligada. O recibo agora vai direto ao Chatwoot.
- Contato identificado só por LID virava um telefone inventado, e a resposta do atendente não chegava a ninguém.
- Do segundo anexo em diante, nada era enviado quando o atendente anexava vários arquivos. E todo documento chegava ao cliente como
file.pdf, em vez do nome real. - Envio recusado pelo provedor ficava com cara de entregue no painel; agora aparece como falha.
- CorreçãoAPIWhatsApp Oficial
Diagnóstico de webhook: a rota de estatísticas passa a falar da sua instância
GET /instance/webhook/statistics respondia 500 em conta oficial e, quando respondia, devolvia os contadores da fila do servidor — iguais para todas as instâncias. Agora devolve o resultado real de cada POST da sua instância.
A rota tinha dois defeitos que se somavam.
Em conta oficial (Cloud API) ela respondia 500: por dentro, passava pela sessão do QR Code, que a conta oficial não tem. Era justamente a instância cujo webhook dá mais trabalho a que não conseguia ser diagnosticada. Em instância de QR Code ainda não carregada no servidor, o "não encontrada" também saía como 500.
E quando respondia, os números eram os contadores da fila do processo — globais, compartilhados por todas as instâncias daquele servidor. Respondiam "a fila está entupida?", nunca "o webhook da minha instância saiu, e o meu servidor respondeu o quê?". A única resposta para isso vivia no log do servidor, fora do seu alcance.
Agora a resposta é sobre a sua instância:
json{ "status": 200, "data": { "official": true, "webhook": { "allowNumber": "all", "webhookFormat": "meta", "configured": ["webhookMessage", "webhookMessageFromMe"], "anyUrl": true }, "delivery": { "queued": 118, "attempts": 118, "ok": 117, "clientError": 0, "failed": 1, "avgMs": 143, "last": { "ts": "2026-10-14T22:34:01.020Z", "status": 200, "ms": 131, "outcome": "ok" }, "recent": [] }, "queue": { "waiting": 0, "active": 0, "failed": 0, "scope": "worker-global" } } }Como ler:
anyUrl: false— nenhum canal tem URL. Sem URL não há o que entregar: o evento sai só pelo socket. É a causa nº 1 de "não recebo nada", e era o que obrigava a abrir log para descobrir o óbvio.configureddiz quais canais têm URL de fato.okalto e ainda assim "não chega nada" — o POST saiu e o seu servidor respondeu 2xx. O evento se perdeu no seu processamento, não no transporte. Esse era o caso que não deixava rastro nenhum.clientError— o seu servidor recusou com 4xx. Não retentamos 4xx por desenho: 404 ou 422 não melhora repetindo.failed— timeout, 5xx ou 429. Esses nós retentamos: 5 tentativas com backoff exponencial. O nosso tempo limite de entrega é de 8 segundos.queuedmuito acima deattempts— a fila travou do nosso lado. O problema não é o seu servidor.queuecontinua na resposta, agora marcadascope: "worker-global": são números do processo, compartilhados com outras instâncias. Para julgar a sua, usedelivery.
Letras miúdas: os contadores valem a partir desta versão, não há histórico retroativo. Ficam 7 dias, e
recenttraz as últimas 20 entregas com status, duração e erro. Vale para conta oficial (Cloud API) e QR Code.No mesmo lote,
/instance/webhook/errorsaiu da documentação — ela aparecia lá e nunca existiu na API. - CorreçãoMessenger
Messenger: reações passam a funcionar, e figurinha deixa de chegar como imagem
O endpoint de reação enviava um valor fixo em vez do emoji escolhido, e toda tentativa era recusada pela Meta. Reação recebida e figurinha também não chegavam identificadas.
- Enviar reação (
/message/reactioncomprovider: messenger) descartava o emoji e mandava um valor fixo: a Meta respondia100/2018468em todas as tentativas. Agora vai o emoji que você enviar. O formato aceito é o emoji em UTF-8 (👍,❤️); nomes em texto (like) são recusados na hora, com explicação. Remover continua sendotext: "". - Receber reação não era entregue: o evento era descartado antes de chegar ao seu webhook. Agora chega como mensagem
type: "reaction", comreaction.message_id,reaction.emojiereaction.action(reactouunreact; na remoção o emoji vem vazio). - Figurinha chegava como imagem comum. O Messenger a entrega como anexo que se declara
imagecomsticker_idno payload; agora chega comotype: "sticker"com o id. O arquivo animado não é exposto pela Meta no webhook — a URL servida é a versão estática. - Foto do contato: quando a Graph recusa o perfil, o motivo passa a ser registrado no log, em vez de o contato ficar sem avatar sem explicação.
- Enviar reação (
- AdiçãoChatwoot
Chatwoot: citação nativa, nota de voz e horário real
Com Token de Acesso configurado, a conversa no painel passa a ter balão de resposta de verdade, player de voz e o horário em que a mensagem existiu no canal.
A API pública da caixa de entrada aceita apenas texto e anexo. Com Token de Acesso, a mensagem do cliente passa a ser criada pela Application API, o que destrava três coisas:
- Citação nativa: a resposta aparece no balão do Chatwoot, não mais como um trecho citado dentro do texto.
- Nota de voz com player próprio, em vez de um anexo de áudio qualquer.
- Horário real da mensagem: o backlog reentregue depois de uma queda de conexão não aparece mais todo empilhado na hora da entrega.
Sem Token de Acesso nada muda. Citações a mensagens anteriores a esta versão aparecem sem o balão, porque elas não têm o identificador do canal gravado.
- AdiçãoChatwootWhatsAppWhatsApp Oficial
Chatwoot: “digitando…” nos dois sentidos e risco azul ao responder
O cliente passa a ver quando o atendente está digitando, o atendente passa a ver quando o cliente digita, e responder pelo painel marca a conversa como lida no WhatsApp.
Três sinais que existiam nas duas pontas e não se encontravam:
- Atendente digitando → cliente vê. No WhatsApp não oficial é presença; na conta oficial o indicador vai junto do marcar-como-lida, como a Cloud API exige. "Parou de digitar" não existe na conta oficial: lá o indicador some sozinho em cerca de 25 segundos.
- Cliente digitando → atendente vê no painel. O indicador nunca abre conversa nova.
- Responder pelo painel marca como lida no canal, então o cliente deixa de ver dois riscos cinzas enquanto já está sendo atendido.
- AdiçãoMessengerAPI
Webhook do Messenger: número de sequência e carimbos de tempo
Cada evento passa a levar um bloco wame com um número de sequência por conversa e três horários, para reconstruir a ordem e medir onde o tempo foi gasto.
A entrega dos webhooks é paralela: a ordem em que as requisições chegam ao seu servidor é a ordem em que cada uma completa, não a ordem em que os eventos entraram. Duas mensagens enviadas em sequência podem chegar invertidas.
Em vez de serializar a entrega, os eventos de Messenger passam a carregar:
json"wame": { "seq": 42, "event_ms": 1760000000000, "received_at_ms": 1760000000420, "dispatched_at_ms": 1760000000437 }seqé um contador por conversa, atribuído na ordem em que recebemos o evento da Meta. Ordenar por ele reconstrói a sequência, inclusive quando os horários são iguais.event_msé o horário do evento segundo a Meta, em milissegundos;received_at_ms, quando ele entrou aqui;dispatched_at_ms, quando saiu daqui. A diferença entre o primeiro e o segundo é latência da Meta; entre o segundo e o terceiro, nossa.
O bloco é aditivo: nenhum campo existente mudou. Por enquanto só nos eventos de Messenger.
No mesmo lote,
GET /messenger/webhook-fieldsmostra quais campos de webhook a sua Página assina ePOSTno mesmo caminho assina os que faltam — é o que explica recibo de entrega, de leitura ou reação que nunca chegam.