Pular para o conteúdo principal

Primeiros passos

Use um número descartável

No primeiro pareamento, use um número de WhatsApp descartável (chip de teste), não o número que você usa de verdade nem o de um cliente. Ver Introdução para o motivo: o risco de banimento é real, e o primeiro teste é justamente onde mais coisa pode dar errado.

Existem dois caminhos para começar: pelo portal (recomendado, sem escrever código) ou direto pela API (para integrar com seu próprio sistema). Os dois fazem a mesma coisa por baixo: criar uma instância, parear por QR Code e enviar uma mensagem de teste.

Caminho 1 — pelo portal (recomendado)

  1. Acesse /panel no host onde a API está rodando e entre com um usuário do portal (o administrador inicial é semeado a partir de ADMIN_EMAIL/ADMIN_PASSWORD, configurados no ambiente).
  2. Na tela Instâncias, preencha o nome da instância (ex.: minha-instancia) e clique em Criar instância.
  3. Clique em Conectar na linha da instância recém-criada. Um diálogo abre com o QR Code — escaneie com o WhatsApp do número que vai operar a instância (WhatsAppAparelhos conectadosConectar um aparelho).
  4. Aguarde o status mudar para Conectada, depois clique em Detalhes → aba Envio de teste. Preencha telefone e texto e envie. Para o primeiro teste, recomendamos desmarcar "Envio proativo" — o mesmo motivo do caminho por API abaixo: isola se um eventual problema é do WhatsApp Web ou do AntiBanGuard.

Caminho 2 — direto pela API

Todas as chamadas abaixo usam a API key global (AUTHENTICATION_API_KEY do ambiente) no cabeçalho apikey. Ajuste http://localhost:8080 para o host real do seu ambiente.

1. Criar a instância

POST /instance/create

curl -X POST http://localhost:8080/instance/create \
-H "apikey: SUA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "minha-instancia"}'

Resposta 200: { id, name, status, webhookUrl, createdAt }, com status: "disconnected" (ainda não pareada).

2. Pedir o QR Code

GET /instance/connect/:name

curl http://localhost:8080/instance/connect/minha-instancia \
-H "apikey: SUA_API_KEY"

A resposta é { status, qr }, onde qr é uma data URL PNG (data:image/png;base64,...) — cole no campo de endereço de um navegador para visualizar, ou decodifique o base64 e salve como arquivo .png. Escaneie com WhatsAppAparelhos conectadosConectar um aparelho. O mesmo QR também chega ao vivo pelo WebSocket /ws/:instance, sem precisar dar poll nesta rota.

3. Aguardar a conexão

GET /instance/status/:name, repetido a cada poucos segundos até status virar "connected".

watch -n 3 curl -s http://localhost:8080/instance/status/minha-instancia \
-H "apikey: SUA_API_KEY"

4. Enviar a mensagem de teste

POST /message/sendText, com proactive: false. O caminho reativo (proactive: false, o padrão) pula todos os gates do AntiBanGuard — se essa primeira mensagem falhar, o problema é do WhatsApp Web/sessão, não do anti-ban. Só depois de confirmar que o envio básico funciona faça sentido testar proactive: true (o caminho usado por qualquer disparo de verdade, sujeito a opt-in, blacklist, janela de horário e limite diário — ver Arquitetura).

curl -X POST http://localhost:8080/message/sendText \
-H "apikey: SUA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"instance": "minha-instancia",
"phone": "5565999998888",
"text": "Teste da API WhatsApp",
"proactive": false
}'

Resposta 200: { status, id, reason? }, onde status é "queued" (enfileirado — a entrega real acontece a seguir, no worker), "scheduled" (adiado) ou "rejected" (barrado; só possível com proactive: true, reason explica o gate). Nunca "sent": o envio enfileirado ainda não aconteceu no instante em que a API responde.

Este fluxo ainda não foi validado ponta a ponta em produção

Tudo acima é o que o código faz — mas o pareamento por QR Code com um Chromium real (headless, dentro de um container) nunca foi observado rodando ponta a ponta em produção neste projeto. Se o QR não aparecer, a instância não conectar, ou o envio de teste falhar, você pode estar encontrando o primeiro problema real desse fluxo. Consulte a seção de Troubleshooting — além dela, os melhores sinais são os logs do container (docker logs) e o campo reason da resposta de sendText quando status é rejected.