Skip to content

Conceitos

Antes de mergulhar na API, alinhe o vocabulario.

Chip

Um numero de WhatsApp pareado com o hub via Baileys (engenharia reversa do protocolo multidevice). Cada chip:

  • Tem um id ULID e um label legivel
  • Mantem socket persistente com servidor WhatsApp
  • Tem fila propria (BullMQ) com rate limit isolado por chip
  • Pode estar em estados: pairing, connected, disconnected, logged_out, banned

Sessao Baileys (creds) fica em volume Docker (dev) ou MinIO (prod). Sobrevive a restart do hub.

App

Uma aplicacao integradora (ex: seu CRM, atendimento, chatbot). Cada app:

  • Tem api_key (Bearer token) e webhook_secret (pra HMAC)
  • Pode ter 1 ou N chips vinculados via app_chip_access
  • Recebe webhooks dos eventos dos chips vinculados

Vinculo (app_chip_access)

Tabela que define qual app pode usar qual chip. Campos:

  • can_send — pode enviar mensagens via esse chip
  • can_receive — recebe webhooks de mensagens recebidas
  • receive_self_chat — opt-in pra receber mensagens que o chip mandou pra si mesmo (uso: linha de comando do operador)
  • transcribe_audio_mode'off' | 'all' | 'whitelist' — controla transcricao automatica de audios
  • transcribe_audio_jids — whitelist de JIDs pra transcricao parcial

Mensagem (messages)

Cada mensagem inbound (recebida) ou outbound (enviada via API ou manualmente do celular) gera um row.

Campos chave:

  • direction'in' ou 'out'
  • typetext, image, audio, document, location, reaction, unknown
  • content — JSONB variavel por tipo
  • wa_message_id — id no protocolo WhatsApp (chave pra dedup)
  • chip_id, app_id, from_jid, to_jid, chat_jid
  • statusqueued, sent, delivered, read, failed (so outbound)

Evento

Webhooks que o hub dispara pras apps consumidoras. Lista completa: Eventos.

Tipos:

  • Mensagemmessage.received, message.status, message.transcribed
  • Chipchip.connected, chip.disconnected, chip.logged_out, chip.banned, chip.qr_loop, chip.bad_session_streak, chip.silent

Cada delivery e assinada com HMAC SHA-256 + retry exponencial (7 tentativas: 30s → 24h).

Auditoria (audit_events)

Toda mutacao admin (criar app, atualizar webhook_url, replay delivery, etc) grava entry imutavel em audit_events. Trigger Postgres bloqueia UPDATE/DELETE.

Quem (actor_id, actor_type), quando, em qual recurso, antes/depois — tudo registrado.

Ver ADR 007 pra justificativa do design append-only.

Identidades duplas — JID vs LID

WhatsApp esta migrando contatos pra LID (List ID) por privacidade. Um mesmo contato pode aparecer:

  • como 5511999998888@s.whatsapp.net (JID telefone — caminho tradicional)
  • como 12345678901234@lid (LID — quando contato ativa privacidade “Numero de telefone: ninguem”)

Hub trata os 2 e cruza quando possivel:

  • sender.jid — identidade principal que veio na mensagem
  • sender.lid — LID alternate quando WA expoe (cross-match)
  • sender.phone_number — telefone “puro” extraido (vazio se nao expoe)

Anti-ban

Hub aplica multiplas camadas pra reduzir risco de WhatsApp banir o chip:

  • Throttle por chip via BullMQ rate limiter
  • Jitter ±30% nos delays entre mensagens
  • Presenca (composing antes de texto, recording antes de audio)
  • Warmup automatico pra chips novos (30 msg/dia → cresce gradualmente)
  • Limite diario com reset 00h UTC
  • Detector de ban via sliding window (3 sintomas/h → marca banned, pausa fila, dispara webhook)

Ver Anti-ban (em breve) pra detalhes.

Idempotencia

POST /v1/messages aceita campo idempotency_key. Hub mantem unique constraint (app_id, idempotency_key). Reenvio com mesma key retorna a mensagem original — nao duplica.

Use UUID v4 ou ULID pra cada operacao logica do seu lado.

Versionamento

API e versionada via path: /v1/.... Mudancas breaking criam /v2. Adicoes nao-breaking entram em /v1 sem versao nova — ver changelog.