Raphael Serafim· Publicado em 10 de setembro de 2026· 10 min de leitura

Como criar um chatbot de IA com a API da OpenAI para responder no WhatsApp

Um webhook, uma chamada à API da OpenAI e uma resposta pela WAME API: o código completo de um chatbot de IA que atende no WhatsApp, Instagram e Messenger. Com memória por contato, controle de custo e o que fazer quando a IA não deve responder.

Ver como Markdown

Um chatbot de IA no WhatsApp são três peças: receber a mensagem, perguntar ao modelo, devolver a resposta. Nenhuma delas é difícil — o que costuma dar trabalho é o meio de campo: o formato do webhook, a memória da conversa e saber quando a IA não deve responder.

Este artigo mostra o código completo, em Node.js, e trata das três coisas.

O que você precisa

  1. Uma instância na WAME API — a não oficial conecta por QR Code em segundos e serve para testar.
  2. Uma chave da API da OpenAI.
  3. Uma URL pública para o webhook. Em desenvolvimento, ngrok ou similar.

Peça 1: receber a mensagem

Aponte o webhook da sua instância (formato meta) para a sua URL. Todo evento chega no envelope padrão da Meta Cloud API, e o campo provider diz o canal:

{
  "object": "wame",
  "provider": "whatsapp",
  "entry": [{
    "id": "<instance-id>",
    "changes": [{
      "field": "messages",
      "value": {
        "messages": [{
          "from": "5566996852025",
          "id": "wamid.XXXX",
          "type": "text",
          "text": { "body": "vocês entregam em Cuiabá?" }
        }]
      }
    }]
  }]
}

Isso importa mais do que parece: como os três canais chegam no mesmo envelope, o bot que você escrever para o WhatsApp já atende Instagram e Messenger. É o padrão único de webhook da plataforma.

O extrator, com as guardas que evitam 90% dos bugs:

function extrair(body) {
  const msg = body?.entry?.[0]?.changes?.[0]?.value?.messages?.[0];

  // Status de entrega ("delivered", "read") também chega aqui.
  // Sem esta guarda, o bot responde a si mesmo em loop.
  if (!msg || msg.type !== 'text') return null;

  return {
    de: msg.from,
    texto: msg.text.body,
    canal: body.provider,
    messageId: msg.id,
  };
}

Peça 2: perguntar ao modelo

A API da OpenAI não guarda estado. Cada chamada é independente, então a memória é sua:

import OpenAI from 'openai';

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

// Em produção use Redis ou banco. Em memória, some no restart.
const historico = new Map();

const SYSTEM = `Você é o atendente da Loja Exemplo, no WhatsApp.

Regras:
- Responda em português, em no máximo 3 frases curtas.
- Nunca invente prazo, preço ou disponibilidade.
- Se a pergunta exigir dado que você não tem, responda exatamente
  com o texto [HUMANO] e nada mais.`;

async function responder(de, texto) {
  const anterior = historico.get(de) ?? [];

  // Últimas 10 mensagens: o suficiente para o contexto e
  // o bastante para o custo não crescer sem limite.
  const mensagens = [
    { role: 'system', content: SYSTEM },
    ...anterior.slice(-10),
    { role: 'user', content: texto },
  ];

  const r = await openai.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: mensagens,
    max_tokens: 300,
    temperature: 0.3,
  });

  const resposta = r.choices[0].message.content.trim();

  historico.set(de, [
    ...anterior.slice(-10),
    { role: 'user', content: texto },
    { role: 'assistant', content: resposta },
  ]);

  return resposta;
}

Três decisões nesse código valem explicação:

temperature: 0.3 — atendimento não quer criatividade. Temperatura baixa deixa a resposta mais previsível e reduz invenção.

max_tokens: 300 — WhatsApp não é lugar de parágrafo longo. Além de melhorar a leitura, limita o custo por resposta.

slice(-10) — o custo da OpenAI é por token, e o histórico inteiro vai em toda chamada. Sem corte, uma conversa longa fica progressivamente mais cara. Dez mensagens costumam bastar.

Peça 3: devolver pelo WhatsApp

async function enviar(para, texto, canal) {
  await fetch(`https://us.api-wa.me/${process.env.WAME_KEY}/message/text`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ to: para, text: texto, channel: canal }),
  });
}

Juntando tudo

import express from 'express';

const app = express();
app.use(express.json());

app.post('/webhook/wame', async (req, res) => {
  // Responda 200 IMEDIATAMENTE. A OpenAI leva segundos, e um
  // webhook que demora a responder é reenviado — o cliente
  // receberia a mesma resposta duas ou três vezes.
  res.sendStatus(200);

  const msg = extrair(req.body);
  if (!msg) return;

  try {
    const resposta = await responder(msg.de, msg.texto);

    if (resposta.includes('[HUMANO]')) {
      await enviar(msg.de, 'Só um instante, vou chamar alguém do time.', msg.canal);
      await avisarAtendente(msg);   // sua fila, seu CRM, seu Chatwoot
      return;
    }

    await enviar(msg.de, resposta, msg.canal);
  } catch (e) {
    console.error('falha ao responder', msg.de, e);
    await enviar(msg.de, 'Tive um problema aqui. Já chamo um atendente.', msg.canal);
    await avisarAtendente(msg);
  }
});

app.listen(3000);

Pronto — cerca de 60 linhas para um bot de IA que atende nos três canais.

O detalhe que separa demo de produção

Responder 200 antes de processar. É a linha mais importante do arquivo. A chamada à OpenAI leva de 1 a 5 segundos; se o seu handler esperar por ela para responder ao webhook, a entrega é considerada falha e reenviada. O resultado é o cliente recebendo a mesma resposta três vezes — e você pagando três vezes por ela.

Ter uma saída para o humano. O [HUMANO] do system prompt existe para isso. Um bot que responde "não sei" é ruim; um bot que inventa o prazo de entrega é pior, porque vira reclamação. Modelo instruído a admitir o limite e código que trata esse caso resolvem os dois. Como o avisarAtendente funciona do outro lado — fila, atribuição e o bot saindo de cena — está em vários atendentes no mesmo número.

Tratar o erro como caminho normal. A OpenAI vai falhar em algum momento — timeout, limite, indisponibilidade. O catch acima não deixa o cliente no vácuo. Do lado do WhatsApp, cada erro pede um tratamento diferente: alguns valem nova tentativa, outros não.

Não responder a si mesmo. A guarda em extrair cuida disso: status de entrega e leitura também chegam no webhook, e sem o filtro o bot entra em loop.

E se o webhook não chegar?

Acontece, e quase sempre é uma das mesmas causas. Antes de mexer no código, aponte o webhook da instância para uma URL do webhook.site e mande uma mensagem: se o evento aparecer lá, o problema é o seu servidor; se não aparecer, é a configuração da instância. Esse teste de 30 segundos separa os dois mundos e evita horas de depuração no lado errado. Há um guia completo em webhook não chega: as 7 causas.

Quando usar n8n em vez de código

Se você quer o fluxo montado visualmente, ou já opera n8n, existe um template pronto de bot de IA com memória por contato — cinco nós, sem escrever nada.

O código faz sentido quando você precisa de controle: regra de negócio no meio da conversa, consulta ao seu banco antes de responder, custo medido por cliente, ou o bot rodando dentro de um sistema que você já mantém. Se você entrega software para clientes, normalmente é esse o caso.

E se o que você quer não é um bot atendendo cliente, mas um agente de IA operando o WhatsApp para você — ler a caixa de entrada, achar quem ficou sem resposta, mandar um documento —, o caminho é outro: o servidor MCP da WAME, que dispensa escrever integração.

Conclusão

O chatbot em si é a parte fácil. O que decide se ele fica no ar é o entorno: responder o webhook na hora, cortar o histórico, ter saída para o humano e tratar erro como caminho esperado.

Comece com uma instância não oficial e um número de teste. Quando o comportamento estiver bom, migre para a API oficial — o webhook e o SDK são os mesmos, então o código do bot não muda.

Pronto para automatizar seu WhatsApp?

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

Começar grátis

Perguntas frequentes

Como conectar a API da OpenAI ao WhatsApp?+

São três peças: um webhook que recebe a mensagem do WhatsApp pela WAME API, uma chamada à API da OpenAI com o histórico da conversa, e um POST para /{key}/message/text devolvendo a resposta. O webhook recebe todos os canais no mesmo formato, então o mesmo código atende WhatsApp, Instagram e Messenger.

Preciso de n8n para fazer um bot de IA no WhatsApp?+

Não. O n8n é conveniente quando você quer montar o fluxo visualmente ou já usa a ferramenta, e existe um template pronto da WAME para isso. Mas em código são cerca de 60 linhas, e você ganha controle total sobre memória, custo e regras de quando não responder.

Quanto custa rodar um chatbot de IA no WhatsApp?+

Dois custos separados: o da OpenAI, cobrado por token consumido, e o da mensagem. Na API não oficial da WAME a mensagem tem preço fixo por instância; na oficial, a Meta cobra por conversa. O custo da IA é o que mais varia, e ele depende do tamanho do histórico que você envia a cada chamada — por isso limitar a memória importa.

Como fazer o bot lembrar da conversa anterior?+

A API da OpenAI não guarda estado: cada chamada é independente. Você mantém as últimas mensagens por contato num armazenamento seu (Redis, banco ou memória) e as envia como histórico a cada requisição. Guardar as últimas 10 costuma bastar e mantém o custo previsível.

O que fazer quando a IA não souber responder?+

Instrua o modelo no system prompt a devolver um marcador combinado quando não tiver certeza, e trate esse marcador no seu código transferindo para um atendente humano. Bot de IA que inventa resposta em atendimento custa mais caro que bot que passa a bola.

Continue lendo