Pular para o conteúdo principal

FAQ

Perguntas reais, respondidas com honestidade — inclusive quando a resposta é "não" ou "ainda não sabemos".

É uma API oficial do WhatsApp/Meta?

Não. Esta API é construída sobre whatsapp-web.js, uma biblioteca não oficial que automatiza uma sessão real do WhatsApp Web dentro de um Chromium headless — não o produto WhatsApp Business Platform da Meta. Ver Introdução e Arquitetura para o porquê dessa escolha.

Posso ser banido usando esta API?

Sim. Como a automação não é oficial, a Meta pode detectar padrões de envio, ausência de respostas ou denúncias de destinatários e banir o número, a qualquer momento e sem aviso prévio — isso vale mesmo com o AntiBanGuard ativo. O guard reduz o risco (opt-in, janelas de horário, limites diários, warmup, espaçamento entre envios, circuit breaker de saúde), mas não elimina a possibilidade de banimento. Use sempre um número descartável para o primeiro teste (ver Primeiros passos) e leia o Guia anti-ban inteiro antes de disparar em produção.

Quantas instâncias cabem num servidor?

Cada instância conectada mantém seu próprio processo Chromium headless. A conta é: RAM disponível para o container ÷ RAM por instância, e é isso que MAX_INSTANCES (src/infra/config.ts, padrão 10) limita.

O consumo por instância é uma estimativa, não uma medição

O número usado nesta documentação (~150–300MB de RAM por Chromium conectado) é uma estimativa carregada de projeto para projeto, não um valor medido sob tráfego real neste ambiente — o primeiro deploy real (2026-07-15) subiu com zero instâncias conectadas, então o consumo de memória de um Chromium ativo, sob volume real de mensagens e mídia, ainda não foi observado aqui. Trate a tabela de dimensionamento em Deploy no EasyPanel como ponto de partida, não como número garantido — meça no seu ambiente e ajuste MAX_INSTANCES com folga antes de escalar.

Preciso de PostgreSQL e Redis, ou dá para usar só um dos dois?

Preciso dos dois — não é opcional. src/infra/config.ts exige DATABASE_URL e REDIS_URL como variáveis obrigatórias (z.string().min(1), sem .optional()); a API não sobe sem ambas. PostgreSQL (via Prisma) guarda instâncias, contadores de anti-ban, usuários do portal, alertas e log de webhooks; Redis (via BullMQ) sustenta as filas de envio e de entrega de webhook. O docker-compose.yml do repositório já sobe os três serviços (app, postgres, redis) juntos para desenvolvimento local — ver Instalação local.

A sessão do WhatsApp sobrevive a um restart do container?

Sim, mas só se o volume /app/sessions estiver montado como volume persistente. As sessões autenticadas (resultado de escanear o QR Code) ficam salvas nesse diretório (SESSIONS_PATH em src/infra/config.ts, padrão /app/sessions, também criado explicitamente no Dockerfile: RUN mkdir -p /app/sessions /app/data). Com o volume montado — o docker-compose.yml já declara sessions:/app/sessions — a sessão sobrevive a redeploys e restarts. Sem esse volume, cada restart derruba todas as sessões conectadas e é preciso escanear o QR Code de novo, uma a uma. Ver a seção Volume persistente do guia de deploy para o passo a passo no EasyPanel.

Posso escalar em vários containers da mesma API?

Não hoje. O espaçamento entre envios proativos (sendDelayMinSecsendDelayMaxSec, 30–90s por padrão) é resolvido por processo — src/core/sendSlotting.ts guarda o último horário de envio de cada instância num Map em memória, nunca persistido em Redis ou no banco. Rodar múltiplos containers Node apontando para a mesma fila BullMQ faria cada processo espaçar apenas as instâncias que ele mesmo processa, sem coordenação entre processos — na prática, o espaçamento real entre envios da mesma instância deixaria de ser respeitado se ela fosse processada por mais de um container. Escalar horizontalmente exigiria mover esse slotting para o Redis (compartilhado entre processos), o que não está implementado. Hoje, escale verticalmente (mais RAM/CPU num único container, respeitando MAX_INSTANCES) em vez de rodar réplicas da mesma API. Ver também o débito registrado em Arquitetura.

A apikey continua funcionando com o Portal de Controle?

Sim. JWT (login do portal) e apikey (header apikey, integrações servidor-a-servidor) são dois métodos de autenticação aceitos em paralelo pelo mesmo hook em src/server.ts — nenhuma integração existente via apikey precisa migrar para JWT. Requisições autenticadas por apikey são tratadas com poder total (equivalentes a admin), sem passar pela distinção de papéis admin/operador do portal — ver Portal de Controle.

Qual a diferença entre proactive: true e proactive: false?

proactive é um campo do corpo de POST /message/sendText (e das demais rotas de envio) que decide se a mensagem passa pelos seis gates do AntiBanGuard ou não:

  • proactive: false (o padrão) — envio reativo, uma resposta a alguém que escreveu primeiro. Pula todos os gates do AntiBanGuard e vai direto para a fila, sem espaçamento artificial.
  • proactive: true — envio proativo, iniciado pela instância sem provocação do contato (campanha, cobrança, lembrete). Passa pelos seis gates na ordem — opt-in, blacklist, existência no WhatsApp, circuit breaker, janela de horário, limite diário — e pode ser recusado (rejected) ou adiado (scheduled) por qualquer um deles.

Use proactive: false no primeiro teste de qualquer instância nova: se a mensagem falhar, o problema é do WhatsApp Web/sessão, não do anti-ban. Detalhe completo dos seis gates em Guia anti-ban.

O envio real acontece na hora que a API responde?

Não. A resposta de POST /message/sendText é sempre queued (enfileirado — o envio de fato acontece a seguir, no worker), scheduled (adiado para mais tarde ou para a próxima janela) ou rejected (barrado antes de entrar na fila; só possível com proactive: true). Nunca sent — ver Envio retorna rejected, o que significa? em Troubleshooting.

Onde vejo mais perguntas de operação do dia a dia?

Problemas específicos (Chromium não sobe, container reinicia, sessão perdida, portal não abre, instância presa em vermelho) têm sua própria página: Troubleshooting.