Changelog

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.

  1. 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/sync publica os modelos aprovados como respostas prontas (atalho tpl_<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.

  2. 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_id era 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_identifier configurado 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.

  3. 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.
  4. 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. configured diz quais canais têm URL de fato.
    • ok alto 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.
    • queued muito acima de attempts — a fila travou do nosso lado. O problema não é o seu servidor.
    • queue continua na resposta, agora marcada scope: "worker-global": são números do processo, compartilhados com outras instâncias. Para julgar a sua, use delivery.

    Letras miúdas: os contadores valem a partir desta versão, não há histórico retroativo. Ficam 7 dias, e recent traz as últimas 20 entregas com status, duração e erro. Vale para conta oficial (Cloud API) e QR Code.

    No mesmo lote, /instance/webhook/error saiu da documentação — ela aparecia lá e nunca existiu na API.

  5. 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/reaction com provider: messenger) descartava o emoji e mandava um valor fixo: a Meta respondia 100/2018468 em 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 sendo text: "".
    • Receber reação não era entregue: o evento era descartado antes de chegar ao seu webhook. Agora chega como mensagem type: "reaction", com reaction.message_id, reaction.emoji e reaction.action (react ou unreact; na remoção o emoji vem vazio).
    • Figurinha chegava como imagem comum. O Messenger a entrega como anexo que se declara image com sticker_id no payload; agora chega como type: "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.
  6. 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.

  7. 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.
  8. 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-fields mostra quais campos de webhook a sua Página assina e POST no mesmo caminho assina os que faltam — é o que explica recibo de entrega, de leitura ou reação que nunca chegam.