Documentação da API
Swagger UI
Base URL

Todos os caminhos desta documentação são relativos à base URL abaixo.

https://wpp.dw.hml.2wa.com.br

Por exemplo, POST /session/{number}/send-message corresponde a https://wpp.dw.hml.2wa.com.br/session/{number}/send-message.

Autenticação

Todas as rotas exigem o header x-api-key com uma API Key ativa.

x-api-key: sua-api-key-aqui

Gerencie suas API Keys na página API Keys.

Rate Limiting

Todas as rotas possuem limite de requisições por minuto. Quando excedido, a API retorna 429 Too Many Requests.

Headers de resposta
HeaderDescrição
X-RateLimit-LimitLimite de requisições por minuto da sua conta
X-RateLimit-RemainingRequisições restantes na janela atual
X-RateLimit-ResetTimestamp (Unix) quando a janela reseta

O limite padrão é 60 req/min. Caso precise de mais, contate o administrador.

Fluxo de uso
Conectar um novo número
1
POST /session/connect — Inicia uma nova conexão e retorna um tempId
2
GET /session/pending/{tempId}/qr — Obtenha o QR code para escanear
Alternativa: POST /session/pending/{tempId}/pairing-code — Obtenha um código numérico de 8 caracteres para vincular sem QR
3
GET /session/pending/{tempId}/status — Monitore até conectar; a resposta incluirá o phone_number
4
Use o phone_number como identificador em todas as rotas operacionais
Rotas de Conexão
POST /session/connect

Inicia uma nova conexão WhatsApp. Retorna um ID temporário para acompanhar o processo.

Body (JSON, opcional)
CampoTipoDescrição
webhookUrlstringURL para receber eventos via webhook
displayNamestringNome de exibição do número
proxyHoststringHost do proxy
proxyPortintegerPorta do proxy
proxyUserstringUsuário do proxy
proxyPassstringSenha do proxy
proxyTypestringhttp ou socks5 (padrão: http)
Resposta
{ "status": true, "tempId": "a1b2c3d4e5f6...", "message": "Session started, use the tempId to get QR code" }
GET /session/pending/{tempId}/qr

Retorna o QR code da sessão pendente como imagem base64.

Resposta
{ "status": true, "qr": "data:image/png;base64,iVBOR..." }

Faça polling a cada 2-3 segundos até obter o QR. Se status: false, o QR ainda não está pronto.

POST /session/pending/{tempId}/pairing-code

Alternativa ao QR code. Retorna um código numérico de 8 caracteres para vincular o dispositivo. No celular, vá em Dispositivos Vinculados > Vincular com número de telefone e insira o código.

Body (JSON)
CampoTipoObrigatórioDescrição
phoneNumberstringSimNúmero do telefone a vincular (ex: 5511999998888)
Resposta
{ "status": true, "pairingCode": "A1B2-C3D4" }

O código expira em ~60 segundos. Pode solicitar novo código na mesma sessão. Nota: após solicitar pairing code, o QR code não será mais emitido naquela sessão.

GET /session/pending/{tempId}/status

Monitora o status da conexão pendente. Quando conectado, retorna o número de telefone.

Resposta (aguardando)
{ "status": true, "connected": false, "sessionStatus": "awaiting_auth" }
Resposta (conectado)
{ "status": true, "connected": true, "sessionStatus": "connected", "phone_number": "5511999998888" }

O tempId expira após 5 minutos se não for escaneado.

Rotas Operacionais

Todas usam o número de telefone como identificador (ex: 5511999998888).

GET /session/numbers

Lista todos os números conectados da sua conta com status em tempo real.

Resposta
{ "status": true, "numbers": [ { "phone_number": "5511999998888", "display_name": "Atendimento", "status": "connected", "webhook_url": "https://meusite.com/webhook", "created_at": "2026-02-24T12:00:00.000Z" } ] }
GET /session/{number}/status

Retorna o status da sessão de um número específico.

Resposta
{ "status": true, "connected": true, "sessionStatus": "connected", "message": "Session is authenticated" }
POST /session/{number}/send-message

Envia uma mensagem de texto.

Body (JSON)
CampoTipoObrigatórioDescrição
tostringSimNúmero destino (ex: 5511999998888)
messagestringSimTexto da mensagem
humanModebooleanNãoSimula comportamento humano antes do envio (marca como lido, digitando..., delay aleatorio)
Exemplo
{ "to": "5521988887777", "message": "Ola! Tudo bem?", "humanMode": true }
Resposta
{ "status": true, "message": "Message sent", "messageId": "BAE5F2A7C4B8D123" }

O messageId pode ser usado para rastrear o status de entrega via GET /session/{number}/messages/{messageId}/status.

POST /session/{number}/send-media

Envia arquivo. Aceita dois formatos: upload (multipart/form-data) ou base64 (application/json).

Opção 1 — File upload (multipart/form-data)
CampoTipoObrigatórioDescrição
tostringSimNúmero destino
filefileSimArquivo a enviar
captionstringNãoTexto de legenda (imagens, vídeos, documentos)
sendAudioAsVoicebooleanNãoEnviar áudio como mensagem de voz
humanModebooleanNãoSimula comportamento humano antes do envio (marca como lido, digitando..., delay aleatorio)
Opção 2 — Base64 (application/json)
CampoTipoObrigatórioDescrição
tostringSimNúmero destino
base64stringSimConteúdo do arquivo em base64
filenamestringSimNome do arquivo (ex: foto.jpg)
mimetypestringSimTipo MIME (ex: image/jpeg)
captionstringNãoTexto de legenda (imagens, vídeos, documentos)
sendAudioAsVoicebooleanNãoEnviar áudio como mensagem de voz
humanModebooleanNãoSimula comportamento humano antes do envio (marca como lido, digitando..., delay aleatorio)
Exemplo base64
{ "to": "5521988887777", "base64": "iVBORw0KGgo...", "filename": "foto.jpg", "mimetype": "image/jpeg", "caption": "Confira esta imagem!", "humanMode": true }
Resposta
{ "status": true, "message": "File sent", "messageId": "BAE5F2A7C4B8D456" }
GET /session/{number}/messages/{messageId}/status

Consulta o status de entrega de uma mensagem enviada, usando o messageId retornado por send-message ou send-media.

Estados possíveis

O status evolui conforme o WhatsApp confirma a entrega. Cada mudança também dispara o webhook message_status_updated.

StatusSignificado
sentMensagem enviada pelo gateway
serverRecebida pelo servidor do WhatsApp
deliveredEntregue no aparelho do destinatário
readLida pelo destinatário
failedFalha no envio
Resposta
{ "status": true, "messageStatus": { "message_id": "BAE5F2A7C4B8D123", "to_number": "5521988887777", "type": "text", "status": "delivered", "created_at": "2026-06-24T12:00:00.000Z", "updated_at": "2026-06-24T12:00:03.000Z" } }

Retorna 404 se o messageId não for encontrado para esse número.

GET /session/{number}/contacts

Lista os contatos do WhatsApp conectado (exclui grupos @g.us).

Resposta
{ "status": true, "contacts": [ { "id": "5521988887777@s.whatsapp.net", "name": "João" } ] }
GET /session/{number}/contacts/{contactId}

Retorna detalhes de um contato específico, incluindo foto de perfil. O contactId é o JID do contato (ex.: 5521988887777@s.whatsapp.net).

Resposta
{ "status": true, "contact": { "id": "5521988887777@s.whatsapp.net", "name": "João", "number": "5521988887777", "profilePicUrl": "https://pps.whatsapp.net/..." } }

profilePicUrl é null quando o contato não tem foto ou não permite a visualização.

GET /session/{number}/chats

Lista as conversas em memória do WhatsApp conectado.

Resposta
{ "status": true, "chats": [ { "id": "5521988887777@s.whatsapp.net", "name": "João" } ] }
GET /session/{number}/chats/{chatId}

Retorna detalhes de uma conversa com as últimas mensagens.

Query params
ParamTipoPadrãoDescrição
limitinteger10Quantidade de mensagens
mediaBase64booleanfalseIncluir mídia como base64
Resposta
{ "status": true, "chat": { "id": "5521988887777@s.whatsapp.net", "name": "João", "messages": [ { "id": "BAE5F2A7C4B8D123", "body": "Olá!", "from": "5521988887777@s.whatsapp.net", "to": "5511999998888@s.whatsapp.net", "timestamp": 1708800000, "fromMe": false, "type": "chat", "hasMedia": false } ] } }

Com mediaBase64=true, cada mensagem que possui mídia inclui o campo mediaBase64 com o conteúdo do arquivo.

GET /session/{number}/download-media/{messageId}

Faz download da mídia de uma mensagem específica.

Resposta
{ "status": true, "media": { "mimetype": "image/jpeg", "data": "base64...", "filename": "photo.jpg" } }
DELETE /session/{number}

Desconecta e remove o número da sua conta. Faz logout do WhatsApp.

Resposta
{ "status": true, "message": "Number disconnected and removed" }
Agendamento de Mensagens

Agende disparos para um horário futuro. No horário, a mensagem é enviada automaticamente, gerando o mesmo registro de status (messages/{messageId}/status) e os mesmos webhooks de entrega/leitura de um envio imediato.

POST /session/{number}/schedule-message

Agenda uma mensagem de texto para envio futuro.

Body (JSON)
CampoTipoObrigatórioDescrição
tostringSimNúmero destino (ex: 5511999998888)
messagestringSimTexto da mensagem
scheduledAtstringSimData/hora futura em ISO 8601. O fuso segue o valor enviado: Z significa UTC; para horário de Brasília use o offset -03:00 (ex: 2026-06-26T14:08:00-03:00)
humanModebooleanNãoSimula comportamento humano antes do envio
retryIfOfflinebooleanNãoSe o número estiver offline no horário, mantém tentando dentro da janela de retentativa
retryWindowMinutesintegerNãoJanela de retentativa em minutos após o horário (padrão 30). Depois disso, marca como falho
Exemplo
{ "to": "5521988887777", "message": "Lembrete: sua consulta e amanha as 10h", "scheduledAt": "2026-06-25T13:00:00Z", "retryIfOffline": true, "retryWindowMinutes": 60 }
Resposta
{ "status": true, "message": "Message scheduled", "scheduled": { "id": 42, "type": "text", "to_number": "5521988887777", "status": "pending", "scheduled_at": "2026-06-25T13:00:00.000Z", "retry_until": "2026-06-25T14:00:00.000Z" } }
POST /session/{number}/schedule-media

Agenda o envio de uma mídia. Aceita upload (multipart/form-data) ou base64 (application/json). Tamanho máximo: 16MB.

Body (além dos campos de mídia de send-media)
CampoTipoObrigatórioDescrição
tostringSimNúmero destino
filefileSim*Arquivo (multipart) — ou use base64/filename/mimetype
base64 / filename / mimetypestringSim*Mídia em base64 (alternativa ao upload)
scheduledAtstringSimData/hora futura em ISO 8601. O fuso segue o valor enviado: Z = UTC; para Brasília use o offset -03:00
captionstringNãoLegenda
sendAudioAsVoicebooleanNãoEnviar áudio como mensagem de voz
humanMode / retryIfOffline / retryWindowMinutes-NãoMesmas opções de schedule-message
Resposta
{ "status": true, "message": "Media scheduled", "scheduled": { "id": 43, "type": "media", "to_number": "5521988887777", "media_filename": "foto.jpg", "media_mimetype": "image/jpeg", "status": "pending", "scheduled_at": "2026-06-25T13:00:00.000Z", "retry_until": null } }
GET /session/scheduled-messages

Lista os agendamentos da sua conta (paginado).

Query params
ParamTipoDescrição
statusstringFiltra por pending, processing, sent, failed ou cancelled
number_idintegerFiltra por número de origem
limit / offsetintegerPaginação (padrão 50 / 0)
Resposta
{ "status": true, "total": 3, "scheduled": [ { "id": 42, "status": "pending", ... } ] }
GET /session/scheduled-messages/{id}

Retorna um agendamento específico.

Campos do objeto
CampoDescrição
idIdentificador do agendamento
typetext ou media
to_numberNúmero destino
messageTexto (ou legenda, no caso de mídia)
scheduled_atData/hora programada do disparo
statusEstado atual (ver abaixo)
retry_if_offline / retry_untilConfiguração e prazo da retentativa
attemptsQuantas vezes o envio foi tentado
message_idID da mensagem gerada (preenchido após o envio)
error_messageMotivo da falha, quando status = failed
sent_atQuando foi efetivamente enviado
Estados do agendamento
StatusSignificado
pendingAguardando o horário do disparo
processingEm processamento pelo worker
sentEnviado com sucesso (use message_id para acompanhar a entrega)
failedFalhou definitivamente (ver error_message)
cancelledCancelado antes do disparo
GET /session/scheduled-messages/{id}/logs

Retorna o histórico de status do agendamento, em ordem cronológica. Cada transição registra o motivo, ajudando a entender por que um disparo falhou ou foi reagendado.

Campos de cada item de logs
CampoDescrição
statusEvento da transição (ver abaixo)
messageDetalhe ou motivo do evento (ex.: mensagem de erro)
attemptNúmero da tentativa de envio no momento do evento
created_atQuando o evento ocorreu
Eventos possíveis
EventoSignificado
createdAgendamento criado
processingReservado pelo worker para envio
sentEnviado com sucesso
requeuedVoltou para a fila (número offline com retentativa ativa, ou reinício do worker)
failedFalhou (ver message com o motivo)
cancelledCancelado antes do disparo
Resposta
{ "status": true, "scheduled": { /* objeto do agendamento */ }, "logs": [ { "status": "created", "message": null, "attempt": 0, "created_at": "2026-06-26T18:30:21.734Z" }, { "status": "failed", "message": "Número offline e janela de retentativa esgotada", "attempt": 1, "created_at": "2026-06-26T18:30:25.110Z" } ] }
DELETE /session/scheduled-messages/{id}

Cancela um agendamento. Apenas agendamentos com status pending podem ser cancelados.

Resposta
{ "status": true, "message": "Scheduled message cancelled" }
Logs e Uso
GET /session/logs

Histórico paginado das chamadas feitas à API pela sua conta.

Query params
ParamTipoPadrãoDescrição
limitinteger50Quantidade de registros
offsetinteger0Deslocamento para paginação
startDatestring-Data inicial (ISO 8601)
endDatestring-Data final (ISO 8601)
Resposta
{ "status": true, "logs": [ { "id": 1024, "method": "POST", "path": "/session/5511999998888/send-message", "status_code": 200, "response_time_ms": 412, "ip_address": "203.0.113.10", "created_at": "2026-06-24T12:00:00.000Z" } ] }
GET /session/usage

Resumo de uso no período: total de chamadas, endpoints mais usados e contagem de mensagens por status.

Query params
ParamTipoDescrição
startDatestringData inicial (ISO 8601)
endDatestringData final (ISO 8601)
Resposta
{ "status": true, "usage": { "api_calls": 1284, "endpoints": [ { "path": "/session/.../send-message", "method": "POST", "count": 980 } ], "messages": { "sent": 12, "delivered": 800, "read": 600, "failed": 3 } } }
GET /session/{number}/webhook-logs

Histórico das tentativas de entrega de webhook de um número, com payload, status HTTP, tentativa e erro.

Query params
ParamTipoPadrãoDescrição
limitinteger50Quantidade de registros
offsetinteger0Deslocamento para paginação
Resposta
{ "status": true, "logs": [ { "id": 88, "event": "message_received", "url": "https://meusite.com/webhook", "response_status": 200, "attempt": 1, "success": true, "error_message": null, "created_at": "2026-06-24T12:00:00.000Z" } ] }
Webhook

Quando configurado, o sistema envia eventos para a URL de webhook via POST.

Segurança — Assinatura HMAC

Toda requisição de webhook inclui o header X-Webhook-Signature com uma assinatura HMAC-SHA256. Use o webhook_secret disponível na página API Keys para validar a autenticidade.

const crypto = require('crypto'); const signature = req.headers['x-webhook-signature']; const expected = crypto.createHmac('sha256', webhookSecret) .update(JSON.stringify(req.body)).digest('hex'); const valid = signature === expected;
Retry automático

Se a entrega falhar, o sistema faz até 3 tentativas com backoff: imediato, 5s, 30s, 120s. Todas as tentativas são registradas e visíveis em GET /session/{number}/webhook-logs.

Evento: message_received
{ "event": "message_received", "phoneNumber": "5511999998888", "message": { "id": "ABCDEF123456", "body": "Ola!", "type": "chat", "from": "5521988887777", "to": "5511999998888", "timestamp": 1708800000, "hasMedia": false, "pushName": "Joao" } }
Evento: message_status_updated

Enviado a cada confirmação de entrega de uma mensagem que você enviou. O campo status pode ter os seguintes valores:

statusSignificado
serverRecebida pelo servidor do WhatsApp
deliveredEntregue no aparelho do destinatário
readLida pelo destinatário

O estado inicial sent é registrado no momento do envio e não gera webhook. Para consultar o status atual de uma mensagem a qualquer momento, use GET /session/{number}/messages/{messageId}/status.

{ "event": "message_status_updated", "phoneNumber": "5511999998888", "messageId": "BAE5F2A7C4B8D123", "status": "delivered", "timestamp": 1708800005000 }
Evento: webhook_test

Enviado ao clicar em "Testar Webhook" no painel. Use para validar que a URL está acessível e a assinatura HMAC está correta.

{ "event": "webhook_test", "phoneNumber": "5511999998888", "timestamp": 1708800000000, "message": "This is a test event from WA Gateway" }
Evento: session_disconnected

Enviado sempre que o número desconecta, seja por logout ou por queda temporária (perda de conexão, reinício, etc). O campo reason diferencia os casos:

reasonDescrição
logged_outO usuário fez logout do WhatsApp (sessão encerrada permanentemente)
disconnectedDesconexão temporária (queda de rede, reinício). O sistema tentará reconectar automaticamente
{ "event": "session_disconnected", "phoneNumber": "5511999998888", "reason": "logged_out" // ou "disconnected" }
Evento: scheduled_message_sent

Enviado quando um disparo agendado é entregue com sucesso. O messageId permite acompanhar o status (entregue/lido) pelos eventos message_status_updated.

{ "event": "scheduled_message_sent", "phoneNumber": "5511999998888", "scheduledId": 42, "messageId": "BAE5F2A7C4B8D123", "to": "5521988887777", "type": "text" }
Evento: scheduled_message_failed

Enviado quando um disparo agendado falha definitivamente (número não existe no WhatsApp, ou offline após esgotar a janela de retentativa).

{ "event": "scheduled_message_failed", "phoneNumber": "5511999998888", "scheduledId": 42, "to": "5521988887777", "type": "text", "error": "Session not ready" }
Códigos de Erro
CódigoDescrição
400Requisição inválida (parâmetros faltando ou sessão não pronta)
403API Key inválida ou conta inativa
404Número não encontrado ou sessão pendente expirada
429Rate limit excedido — muitas requisições. Verifique os headers X-RateLimit-*
500Erro interno do servidor