Raphael Serafim· Publicado em 28 de setembro de 2026· 9 min de leitura

Webhook compatível com a Cloud API da Meta: o que é idêntico e o que muda na WAME

Campo a campo: o webhook da WAME no formato meta comparado ao da WhatsApp Cloud API. O que o seu parser já lê, o que muda e exemplos de mensagem e status.

Ver como Markdown

Na WAME (api-wa.me), o webhook no formato meta segue a mesma estrutura da WhatsApp Cloud API: entry[].changes[].value com messaging_product, metadata, contacts[], messages[] e statuses[], e os mesmos tipos de mensagem e de status. As diferenças são poucas e objetivas — o campo object, o entry.id, o phone_number_id, a URL da mídia e a assinatura. Este artigo é a tabela de referência campo a campo para quem vai migrar um parser da Cloud API.

A camada não oficial da WAME não é afiliada, endossada ou suportada pelo WhatsApp ou pela Meta. O uso é de responsabilidade de quem envia.

Em resumo

  • Igual: estrutura do envelope, value.messages[], value.statuses[], value.contacts[], tipos de mensagem, context, referral, interactive.
  • Diferente: object vem wame, entry.id vem mascarado, phone_number_id é a key da instância, mídia traz url de download, sem X-Hub-Signature-256.
  • Extras: chat_type, group_id para grupos e from_me para mensagens enviadas pelo próprio número.

Como ativar o formato da Meta?

Por padrão, a instância entrega no formato nativo da WAME. Para o formato da Cloud API, defina webhookFormat:

bash
curl -X PUT "https://us.api-wa.me/SUA_KEY/instance" \
  -H "Content-Type: application/json" \
  -d '{
    "allowWebhook": true,
    "allowNumber": "all",
    "webhookMessage": "https://seu-sistema.com.br/webhook/SEGREDO",
    "webhookFormat": "meta"
  }'

Os valores possíveis são native (padrão), meta e both. O both envia os dois formatos e é útil durante a migração, quando parte do sistema ainda lê o formato antigo.

Como é uma mensagem recebida?

json
{
  "object": "wame",
  "provider": "whatsapp",
  "instance": "SUA_KEY",
  "official": false,
  "entry": [{
    "id": "ID_CODIFICADO",
    "changes": [{
      "field": "messages",
      "value": {
        "messaging_product": "whatsapp",
        "metadata": {
          "display_phone_number": "5511988887777",
          "phone_number_id": "SUA_KEY"
        },
        "contacts": [{ "profile": { "name": "Carla" }, "wa_id": "5511999999999" }],
        "messages": [{
          "from": "5511999999999",
          "chat_type": "individual",
          "id": "3EB0C767D26A1D8E4B2A",
          "timestamp": "1790000000",
          "type": "text",
          "text": { "body": "Meu pedido ainda não chegou" }
        }]
      }
    }]
  }]
}

Repare que, abaixo de entry, tudo tem o nome e a posição que a Cloud API usa. O parser típico continua funcionando:

javascript
const value = body?.entry?.[0]?.changes?.[0]?.value;
const msg = value?.messages?.[0];
const nome = value?.contacts?.[0]?.profile?.name;

Como é um status de entrega?

json
{
  "object": "wame",
  "entry": [{
    "changes": [{
      "field": "messages",
      "value": {
        "messaging_product": "whatsapp",
        "metadata": { "display_phone_number": "5511988887777", "phone_number_id": "SUA_KEY" },
        "statuses": [{
          "id": "3EB0C767D26A1D8E4B2A",
          "status": "read",
          "timestamp": "1790000060",
          "recipient_id": "5511999999999",
          "conversation": { "id": null, "expiration_timestamp": null, "origin": { "type": null } },
          "pricing": { "billable": null, "pricing_model": null, "type": null, "category": null }
        }]
      }
    }]
  }]
}

O id é o mesmo que voltou em messages[0].id na resposta do envio, então a conciliação que você já faz continua valendo. As chaves conversation e pricing existem, mas com null: parsers que leem esses campos não quebram, e nada é cobrado pela Meta na instância não oficial. Quando o envio falha, o status vem failed com errors[], no mesmo formato de código, título e detalhe da Meta.

Tabela de paridade campo a campo

CampoCloud APIWAME (formato meta)
objectwhatsapp_business_accountwame
entry[].idID da WABAIdentificador codificado (não use para rotear)
changes[].fieldmessagesmessages
value.messaging_productwhatsappwhatsapp
value.metadata.display_phone_numberNúmero do negócioNúmero conectado
value.metadata.phone_number_idID do número na MetaKey da instância
value.contacts[].profile.nameNome do perfilNome do perfil
value.contacts[].wa_idTelefoneTelefone
messages[].fromTelefoneTelefone (em grupo, quem enviou)
messages[].id, timestamp, typeSimSim
text.bodySimSim
image, video, audio, document, stickerid + mime_type + sha256id + url + mime_type + sha256
audio.voiceSimSim
locationlatitude, longitude, name, addressIgual
interactive.button_reply / list_replyid, titleid, title
reactionSimSim
context (resposta citada)from, idfrom, id
referral (anúncio Click-to-WhatsApp)SimSim
statuses[].statussent, delivered, read, failedsent, delivered, read, played, failed
statuses[].recipient_idSimSim
statuses[].errors[]Em failedEm failed
statuses[].conversation / pricingPreenchidosPresentes com null
chat_type, group_idGrupos na Groups APISempre chat_type; group_id em grupo
AssinaturaX-Hub-Signature-256Não há (use segredo na URL)

O que muda na prática para o seu código?

Quatro ajustes cobrem quase todos os casos.

1. Validação do object

Se o seu código descarta o que não é whatsapp_business_account, aceite também wame:

javascript
const ORIGENS = ['whatsapp_business_account', 'wame'];
if (!ORIGENS.includes(body.object)) return res.sendStatus(200);

2. Roteamento por phone_number_id

Na WAME, metadata.phone_number_id é a key da instância. Se você usa esse campo para descobrir de qual cliente é o evento, cadastre a key no lugar do ID da Meta. O envelope também traz a key em instance, no topo. O entry.id vem mascarado e não serve para roteamento.

3. Download de mídia

Na Cloud API, o webhook traz o id e você chama a Graph API para obter a URL. Na WAME, a URL já vem no evento:

javascript
// Antes: resolver o media id na Graph API
// const url = await obterUrlNaGraph(msg.image.id);

// Depois: a URL de download já chega no webhook
const url = msg.image.url; // https://us.api-wa.me/SUA_KEY/message/ID/media

4. Verificação de origem

Sem X-Hub-Signature-256, a proteção é um segredo no caminho da URL e, se possível, restrição de origem. Um endpoint com caminho previsível aceita evento forjado de qualquer um. Veja webhook em produção: assinatura, retry e idempotência.

O que vem a mais no webhook da WAME?

Três campos que a Cloud API não entrega da mesma forma e que ajudam muito:

  • chat_type: individual, group, newsletter ou broadcast, sempre presente.
  • group_id: o JID do grupo, só em mensagens de grupo. Nesse caso, from é quem enviou.
  • from_me: marca mensagens enviadas pelo próprio número, por exemplo por um atendente no celular, quando o webhook de mensagens enviadas está ligado. É o que permite pausar o bot quando um humano assume, como em celular e API no mesmo número.

Além disso, o formato meta cobre os eventos que só existem na conexão não oficial: ligações (campo call), entradas e saídas em grupos (campo groups), conexão (campo connection) e saúde do número (campo health).

E o formato serve para Instagram e Messenger?

Sim. O mesmo envelope é usado para os três canais da WAME, com o campo provider dizendo de onde veio. O padrão está em um webhook para WhatsApp, Instagram e Messenger.

Por que isso importa depois de outubro de 2026?

Porque, a partir de 1º de outubro de 2026, a Meta passa a cobrar toda mensagem de serviço e toda Utility de resposta dentro da janela de 24h, desde a primeira. Muitas empresas querem tirar o atendimento da cobrança por mensagem, e o maior custo dessa troca seria reescrever o parser de webhook. Com o formato meta, esse custo praticamente some. O contexto está em alternativa à API oficial depois de outubro e o lado do envio em um código só para a API oficial e a não oficial.

Conclusão

O webhook da WAME (api-wa.me) no formato meta foi feito para que um parser escrito para a WhatsApp Cloud API funcione com o mínimo de mudança: mesma estrutura de entry, changes e value, mesmos messages[] e statuses[], mesmos tipos. O que muda — object, phone_number_id, URL de mídia e assinatura — cabe em quatro ajustes pontuais. Ligue o webhookFormat como both durante a transição, compare os eventos lado a lado e troque para meta quando o parser estiver pronto. O passo a passo completo da migração está em migrar da API oficial para a não oficial sem reescrever.

Pronto para automatizar seu WhatsApp?

Crie sua conta gratuita e comece a enviar mensagens pela API em minutos.

Começar grátis

Perguntas frequentes

O webhook da WAME é igual ao da WhatsApp Cloud API?+

Com o webhookFormat meta, a WAME (api-wa.me) entrega os eventos na mesma estrutura da Cloud API: entry[].changes[].value com messaging_product, metadata, contacts[], messages[] e statuses[]. As diferenças são o campo object (wame em vez de whatsapp_business_account), o entry.id mascarado, o phone_number_id com a key da instância e a mídia com url de download.

Como ativo o webhook no formato da Meta na WAME?+

Faça PUT /{key}/instance com allowWebhook true, a URL em webhookMessage e webhookFormat meta. O valor both envia os dois formatos, o nativo da WAME e o da Meta, útil durante a migração. O padrão é native.

Os status de entrega chegam no mesmo formato da Meta?+

Sim. Na WAME (api-wa.me), os status chegam em value.statuses[] com id, status (sent, delivered, read, played ou failed), timestamp e recipient_id, e errors[] quando falha. As chaves conversation e pricing existem com valor null, então parsers que as leem não quebram, e não há cobrança da Meta na instância não oficial.

O webhook da API não oficial vem assinado como o da Meta?+

Não. O webhook da Cloud API vem com o cabeçalho X-Hub-Signature-256; o da instância não oficial da WAME não traz essa assinatura. A proteção recomendada é usar uma URL com segredo no caminho e validar a origem no seu servidor.

Mensagens de grupo chegam no webhook no formato da Meta?+

Sim. Na WAME (api-wa.me), mensagem de grupo chega em messages[] com from igual a quem enviou e group_id com o JID do grupo, além de chat_type group. Em conversa individual, group_id não aparece. É o mesmo desenho que a Cloud API usa para grupos.

Continue lendo