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 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 (sendDelayMinSec–sendDelayMaxSec,
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 doAntiBanGuarde 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.