# Como integrar a WAME API (WhatsApp) com o Chatwoot — passo a passo > Tutorial para integrar o WhatsApp ao Chatwoot usando a WAME API: conecte os dois sentidos (mensagens que chegam e respostas dos atendentes) com o API Channel do Chatwoot e os webhooks da WAME. Com código em Node.js. **Sim, dá para usar o WhatsApp da WAME API dentro do Chatwoot.** Não existe um conector nativo, mas a integração é direta: uma **ponte (middleware)** liga os **webhooks da WAME** ao **API Channel do Chatwoot**. O resultado é atendimento omnichannel — mensagens do WhatsApp viram conversas no Chatwoot e as respostas dos atendentes voltam para o cliente. ```text WhatsApp ⇄ WAME API ⇄ (seu middleware) ⇄ Chatwoot (API Channel) ``` Neste tutorial você cria a inbox no Chatwoot, configura os webhooks dos dois lados e sobe uma ponte em Node.js. ## Visão geral dos dois sentidos | Sentido | Origem | Destino | | --- | --- | --- | | Entrada | Webhook da WAME (`webhookMessage`) | API pública do Chatwoot | | Saída | Webhook da inbox do Chatwoot | `POST /{key}/message/text` da WAME | ## Passo 1 — Criar o API Channel no Chatwoot No Chatwoot, vá em **Configurações → Caixas de entrada → Adicionar inbox → API**. Defina um nome e, no campo **webhook_url**, aponte para o endpoint de saída do seu middleware (ex.: `https://sua-ponte.com/webhook/chatwoot`). Ao criar, guarde o **`inbox_identifier`** (identificador da inbox) — ele é usado nas chamadas da API pública. ## Passo 2 — Configurar o webhook da WAME Aponte o webhook de mensagens da WAME para o endpoint de entrada do seu middleware: ```bash curl -X PUT "https://us.api-wa.me/SUA_KEY/instance" \ -H "Content-Type: application/json" \ -d '{ "allowWebhook": true, "allowNumber": "all", "webhookMessage": "https://sua-ponte.com/webhook/wame" }' ``` ## Passo 3 — A ponte (middleware) em Node.js O exemplo abaixo usa Express. Variáveis de ambiente: ```bash CHATWOOT_URL=https://app.chatwoot.com CHATWOOT_INBOX_IDENTIFIER=seu_inbox_identifier WAME_SERVER=https://us.api-wa.me WAME_KEY=SUA_KEY ``` ### Entrada: WhatsApp → Chatwoot Quando chega uma mensagem, a WAME chama `/webhook/wame`. O middleware garante o contato e a conversa no Chatwoot e cria a mensagem como **recebida**: ```ts import express from "express"; const app = express(); app.use(express.json()); const CW = process.env.CHATWOOT_URL!; const INBOX = process.env.CHATWOOT_INBOX_IDENTIFIER!; // Em produção, persista esse mapa (Redis/DB). Aqui, em memória para o exemplo. const sessions = new Map(); async function ensureConversation(phone: string, name: string) { if (sessions.has(phone)) return sessions.get(phone)!; // 1) Criar/identificar o contato (usamos o telefone como identifier) const contact = await fetch(`${CW}/public/api/v1/inboxes/${INBOX}/contacts`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ identifier: phone, name, phone_number: `+${phone}` }), }).then((r) => r.json()); const sourceId = contact.source_id; // 2) Abrir uma conversa para esse contato const conversation = await fetch( `${CW}/public/api/v1/inboxes/${INBOX}/contacts/${sourceId}/conversations`, { method: "POST", headers: { "Content-Type": "application/json" }, body: "{}" } ).then((r) => r.json()); const data = { sourceId, conversationId: conversation.id }; sessions.set(phone, data); return data; } app.post("/webhook/wame", async (req, res) => { const evt = req.body; // estrutura do evento de mensagem da WAME const phone = String(evt.from || evt.number || "").replace(/\D/g, ""); const text = evt.text || evt.message?.text || ""; if (!phone || !text) return res.sendStatus(200); const { sourceId, conversationId } = await ensureConversation(phone, evt.name || phone); await fetch( `${CW}/public/api/v1/inboxes/${INBOX}/contacts/${sourceId}/conversations/${conversationId}/messages`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ content: text, message_type: "incoming" }), } ); res.sendStatus(200); }); ``` ### Saída: Chatwoot → WhatsApp Quando um atendente responde, o Chatwoot chama o `webhook_url` da inbox. Filtramos só mensagens **de saída** (do atendente) e enviamos pela WAME: ```ts const WAME = `${process.env.WAME_SERVER}/${process.env.WAME_KEY}`; app.post("/webhook/chatwoot", async (req, res) => { const evt = req.body; // Só reage a mensagens criadas, de saída e não privadas if (evt.event !== "message_created") return res.sendStatus(200); if (evt.message_type !== "outgoing" || evt.private) return res.sendStatus(200); // O telefone é o identifier que definimos ao criar o contato const phone = (evt.conversation?.meta?.sender?.identifier || "").replace(/\D/g, ""); const text = evt.content || ""; if (!phone || !text) return res.sendStatus(200); await fetch(`${WAME}/message/text`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ to: phone, text }), }); res.sendStatus(200); }); app.listen(3000, () => console.log("Ponte WAME ⇄ Chatwoot rodando na porta 3000")); ``` > Ajuste os nomes dos campos do evento da WAME (`from`, `text`, etc.) conforme o payload real do seu webhook — confira na [documentação](/docs). Em produção, **persista o mapa de sessões** (telefone ↔ contato/conversa) em um banco ou Redis. ## Sem código? Use o n8n Se preferir não manter um serviço próprio, dá para montar os mesmos dois fluxos em uma ferramenta de automação como o **n8n**: um workflow recebe o webhook da WAME e chama a API do Chatwoot; outro recebe o webhook do Chatwoot e chama a WAME. ## Dicas finais - Envie e responda **só para contatos com opt-in** — veja as [boas práticas para evitar bloqueio](/blog/api-nao-oficial-whatsapp). - Para mídia, use os endpoints específicos (imagem, documento) em vez de `/message/text` — veja [como enviar mídia e botões](/blog/como-enviar-mensagem-whatsapp-api). - Precisa de uma visão geral dos endpoints? Veja o [guia da API](/blog/guia-api-whatsapp-endpoints). Com essa ponte, seu time atende o WhatsApp direto no Chatwoot, com todo o histórico centralizado. Comece criando sua conta na [api-wa.me](/) e configurando o webhook. ## Perguntas frequentes ### Dá para usar a WAME API com o Chatwoot? Sim. Não há um conector nativo, mas a integração é feita com uma ponte (middleware) que liga os webhooks da WAME ao API Channel do Chatwoot. As mensagens que chegam no WhatsApp aparecem no Chatwoot, e as respostas dos atendentes voltam para o WhatsApp. ### O que é o API Channel do Chatwoot? É um tipo de caixa de entrada (inbox) do Chatwoot feito para conectar canais externos. Você empurra mensagens recebidas via API pública do Chatwoot e recebe as respostas dos atendentes em uma webhook_url configurada na inbox. ### Preciso saber programar para integrar WAME e Chatwoot? É preciso um pequeno serviço (middleware) que traduz os dois formatos. Pode ser feito em Node.js ou PHP, ou com uma ferramenta de automação como o n8n, sem escrever muito código. ### Funciona com Chatwoot self-hosted? Sim. Funciona tanto com o Chatwoot na nuvem (app.chatwoot.com) quanto com uma instância self-hosted — basta apontar a base URL da API do Chatwoot para o seu domínio.