# Um webhook para WhatsApp, Instagram e Messenger: o padrão Meta na prática > Receba WhatsApp, Instagram e Messenger em um único webhook no formato da Meta Cloud API, reusando um só parser. O campo provider diz o canal. **Você pode receber mensagens e eventos de WhatsApp, Instagram e Messenger em um único webhook, no mesmo envelope da Meta Cloud API — reaproveitando um só parser.** A WAME entrega os três canais na estrutura oficial da Meta; o que muda de um para o outro é apenas o campo `provider`. O resultado: um endpoint, um parser, três canais. Neste guia você configura o webhook no formato `meta`, entende o envelope campo a campo, trata os eventos com os SDKs de Node.js e PHP (ou com Express puro) e responde à mensagem recebida dentro do próprio handler. ## Por que webhooks Sem webhook, você teria que ficar perguntando à API se chegou algo novo (polling) — desperdício de requisições e atraso. Com webhook, é o contrário: a WAME **empurra** o evento para o seu servidor no instante em que ele acontece. Mensagem recebida, status de entrega, presença ("digitando"), conexão da instância, QR code, chamadas — tudo chega em tempo real, no seu endpoint. Para quem atende clientes, isso é a base de um chatbot, de um CRM ou de uma central omnichannel: o evento chega, seu código decide o que fazer e responde na hora. ## Passo 1 — Configurar o webhook na instância O webhook é configurado por instância, com um `PUT /{key}/instance`. O campo-chave aqui é o `webhookFormat`: ```bash curl -X PUT "https://us.api-wa.me/YOUR_KEY/instance" \ -H "Content-Type: application/json" \ -d '{"allowWebhook":true,"allowNumber":"all","webhookFormat":"meta","webhookMessage":"https://seu-servidor.com/webhook"}' ``` O que cada campo faz: - **`allowWebhook`** — liga o envio de eventos para o seu endpoint. - **`allowNumber`** — quais números geram eventos (`all` para todos). - **`webhookMessage`** — a URL que vai receber os eventos. - **`webhookFormat`** — o formato do payload. É aqui que a mágica acontece. Sobre o `webhookFormat`, há três opções: - **`native`** — payload no formato interno da WAME. Mais enxuto, mas específico da plataforma. - **`meta`** — payload no **envelope oficial da Meta Cloud API**. É o que permite reaproveitar os parsers oficiais e tratar WhatsApp, Instagram e Messenger com o mesmo código. - **`both`** — envia os dois formatos, útil em migrações ou testes. Para o cenário deste post — um webhook, três canais — use **`meta`**. Assim seu parser já entende a estrutura que a própria Meta documenta, e o campo `provider` diferencia o canal. ## Passo 2 — O envelope Independentemente do canal, o corpo entregue no formato `meta` tem sempre a mesma forma. Só muda o `provider` (e o `messaging_product` interno): ```json { "object": "wame", "provider": "whatsapp", "instance": "YOUR_INSTANCE_ID", "official": true, "entry": [{ "id": "YOUR_INSTANCE_ID", "changes": [{ "field": "messages", "value": { "messaging_product": "whatsapp", "metadata": { "display_phone_number": "5511999990000", "phone_number_id": "YOUR_INSTANCE_ID" }, "contacts": [{ "profile": { "name": "Fulano" }, "wa_id": "5511988887777" }], "messages": [{ "from": "5511988887777", "id": "wamid.XXX", "timestamp": "1700000000", "type": "text", "text": { "body": "Olá!" } }] }}]}] } ``` Os campos que importam: - **`object`** — identifica a origem do evento (`wame`). - **`provider`** — o canal: `whatsapp`, `instagram` ou `messenger`. É o campo que o seu código lê para saber por onde responder. - **`instance`** — o identificador da instância que gerou o evento. - **`official`** — se a instância é oficial (API Cloud da Meta) ou não. - **`entry[]`** — a lista de entradas, cada uma com `changes[]`. - **`entry[].changes[].field`** — o **tipo** de evento (`messages`, `presence`, etc.). - **`entry[].changes[].value`** — o conteúdo do evento, no formato oficial da Meta. Para trocar de canal, imagine o mesmo JSON com `"provider": "instagram"` — a estrutura de leitura do seu código continua idêntica. É esse o ganho de usar o padrão Meta. ## Passo 3 — Tratar os eventos Você não precisa navegar o `entry[].changes[].value` na mão. Os SDKs oficiais têm um parser que achata o envelope em uma lista de eventos tipados, já expondo `provider`, `official`, `fromUserId` e `profile`. ### Node.js / TypeScript Com o SDK `@raphaelvserafim/client-api-whatsapp`, use `parseWebhook`: ```ts import express from 'express'; import { Wame, TypeMessage, parseWebhook } from '@raphaelvserafim/client-api-whatsapp'; const wa = new Wame({ server: "https://us.api-wa.me", key: "YOUR_KEY" }); const app = express(); app.use(express.json()); app.post('/webhook', async (req, res) => { res.sendStatus(200); const events = parseWebhook(req.body); for (const ev of events) { if (ev.type === 'text') { await wa.message.send({ type: TypeMessage.TEXT, body: { to: ev.from, text: "Recebi: " + ev.text, provider: ev.provider } }); } } }); app.listen(3000); ``` Repare em dois pontos: o `res.sendStatus(200)` vem **antes** do processamento, e o `ev.provider` é repassado no envio — assim a resposta volta pelo mesmo canal de onde a mensagem chegou. ### PHP No SDK `raphaelvserafim/client-php-api-wa-me`, o método equivalente é `parseMeta`: ```php use Api\Wame\Wame; $wa = new Wame(['server' => 'https://us.api-wa.me', 'key' => 'YOUR_KEY']); $body = json_decode(file_get_contents('php://input'), true); $events = $wa->webhook->parseMeta($body); foreach ($events as $e) { if ($e['type'] === 'text') { $wa->message->sendText($e['from'], 'Recebi: ' . $e['text']['body'], $e['provider']); } } ``` ### Sem SDK — lendo o envelope cru com Express Se preferir não usar SDK, dá para navegar o envelope diretamente. É útil para entender a estrutura por trás do parser: ```ts import express from 'express'; const app = express(); app.use(express.json()); app.post('/webhook', (req, res) => { res.sendStatus(200); const body = req.body; const provider = body.provider; for (const entry of body.entry || []) { for (const change of entry.changes || []) { if (change.field !== 'messages') continue; for (const msg of change.value.messages || []) { if (msg.type === 'text') { console.log(provider, msg.from, msg.text.body); } } } } }); app.listen(3000); ``` O caminho é sempre o mesmo: `body.entry[].changes[]`, filtrando por `field` e lendo o `value`. Trocar de WhatsApp para Instagram ou Messenger não muda esse percurso — só o `provider`. ## Passo 4 — Tipos de `field` O campo `field` de cada `change` diz que tipo de evento chegou. Trate cada um conforme sua necessidade: - **`messages`** — mensagens recebidas **e** status de entrega (enviado, entregue, lido, falha). É o mais usado. - **`presence`** — presença do contato ("digitando", online). - **`connection`** — mudanças de estado da conexão da instância. - **`qrcode`** — novo QR code disponível (para instâncias não oficiais). - **`call`** — eventos de chamada. - **`groups`** — eventos de grupo (entrada, saída, alterações). - **`health`** — saúde da instância. Sobre os **status de entrega**: eles chegam dentro de `field: "messages"`, no array `statuses` do `value` (em vez de `messages`). É assim que você acompanha se a mensagem que você enviou foi entregue e lida — essencial para métricas e reenvio. ## Passo 5 — Responder à mensagem no próprio handler Como visto nos exemplos, responder é só chamar o `send` com o `provider` do evento. O ponto importante é **repassar `ev.provider`**: sem isso, o envio pode ir pelo canal errado. Como o parser já entrega esse campo, basta encaminhá-lo. Esse padrão fecha o ciclo: chegou uma mensagem no Instagram, seu código responde no Instagram; chegou no WhatsApp, responde no WhatsApp — tudo no mesmo handler, sem `if` por canal para montar a chamada de envio. ## Passo 6 — Boas práticas - **Responda 200 rápido.** Envie o `200` antes de processar a lógica. Se o seu endpoint demora, a WAME pode considerar falha e reentregar o evento, gerando duplicidade. Processe de forma assíncrona (fila, worker) quando a lógica for pesada. - **Seja idempotente.** Use o `id` da mensagem (`wamid.XXX`) para ignorar reentregas do mesmo evento. - **Monitore a entrega.** Consulte as estatísticas do webhook para ver se está tudo chegando: ```bash curl "https://us.api-wa.me/YOUR_KEY/instance/webhook/statistics" ``` - **Trate os três estados.** No handler, considere sempre o caminho de erro (payload inesperado), o vazio (evento sem `messages`) e o feliz — não só o último. ## Conclusão Um único endpoint, um único parser e o campo `provider` para diferenciar o canal: é assim que a WAME transforma WhatsApp, Instagram e Messenger em uma superfície só, usando o envelope oficial da Meta. Você escreve o parser uma vez e ele serve para os três. Comece configurando a instância com `webhookFormat: "meta"` e aponte seu endpoint. Para aprofundar, veja a [documentação de webhooks](/docs/webhooks), o [SDK de TypeScript](/docs/sdk/ts) e o [SDK de PHP](/docs/sdk/php). E se quiser entender como um só conjunto de endpoints atende os três canais, leia [Instagram e Messenger na mesma API do WhatsApp](/blog/api-instagram-messenger-mesma-api-whatsapp). ## Perguntas frequentes ### Como recebo mensagens dos três canais em um só webhook? Configure a instância com webhookFormat "meta". A WAME entrega os eventos de WhatsApp, Instagram e Messenger no mesmo envelope da Meta Cloud API, mudando apenas o campo provider. Assim você usa um único endpoint e um único parser para os três canais. ### O que é o campo provider no envelope? É o campo que identifica de qual canal veio o evento: "whatsapp", "instagram" ou "messenger". Como o restante da estrutura é idêntica, seu código lê provider para saber por onde responder, sem precisar de webhooks separados. ### Qual a diferença entre webhookFormat native, meta e both? native entrega o payload no formato interno da WAME; meta entrega no envelope oficial da Meta Cloud API, reaproveitando os parsers oficiais; both envia os dois formatos. Use meta para padronizar WhatsApp, Instagram e Messenger com o mesmo parser. ### Preciso responder algo ao webhook? Sim, responda HTTP 200 o mais rápido possível para confirmar o recebimento. Processe a lógica de negócio depois, de forma assíncrona, para evitar timeouts e reentregas. Nos SDKs isso é feito enviando o 200 antes de processar os eventos. ### Como sei se meu webhook está recebendo os eventos? Consulte GET /{key}/instance/webhook/statistics para ver estatísticas de entrega, incluindo sucessos e falhas. Isso ajuda a diagnosticar endpoints fora do ar, respostas lentas ou URLs mal configuradas.