Todos os caminhos desta documentação são relativos à base URL abaixo.
Por exemplo, POST /session/{number}/send-message corresponde a https://wpp.dw.hml.2wa.com.br/session/{number}/send-message.
Todas as rotas exigem o header x-api-key com uma API Key ativa.
Gerencie suas API Keys na página API Keys.
Todas as rotas possuem limite de requisições por minuto. Quando excedido, a API retorna 429 Too Many Requests.
| Header | Descrição |
|---|---|
| X-RateLimit-Limit | Limite de requisições por minuto da sua conta |
| X-RateLimit-Remaining | Requisições restantes na janela atual |
| X-RateLimit-Reset | Timestamp (Unix) quando a janela reseta |
O limite padrão é 60 req/min. Caso precise de mais, contate o administrador.
POST /session/connect — Inicia uma nova conexão e retorna um tempIdGET /session/pending/{tempId}/qr — Obtenha o QR code para escanearPOST /session/pending/{tempId}/pairing-code — Obtenha um código numérico de 8 caracteres para vincular sem QRGET /session/pending/{tempId}/status — Monitore até conectar; a resposta incluirá o phone_numberInicia uma nova conexão WhatsApp. Retorna um ID temporário para acompanhar o processo.
| Campo | Tipo | Descrição |
|---|---|---|
| webhookUrl | string | URL para receber eventos via webhook |
| displayName | string | Nome de exibição do número |
| language | string | en ou pt-BR (padrão: en). Idioma do campo error nos webhooks deste número. Só pode ser definido aqui, no pareamento |
| proxyHost | string | Host do proxy |
| proxyPort | integer | Porta do proxy |
| proxyUser | string | Usuário do proxy |
| proxyPass | string | Senha do proxy |
| proxyType | string | http ou socks5 (padrão: http) |
Retorna o QR code da sessão pendente como imagem base64.
Faça polling a cada 2-3 segundos até obter o QR. Se status: false, o QR ainda não está pronto.
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.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| phoneNumber | string | Sim | Número do telefone a vincular (ex: 5511999998888) |
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.
Monitora o status da conexão pendente. Quando conectado, retorna o número de telefone.
O tempId expira após 5 minutos se não for escaneado.
Todas usam o número de telefone como identificador (ex: 5511999998888).
Lista todos os números conectados da sua conta com status em tempo real.
Retorna o status da sessão de um número específico.
Envia uma mensagem de texto.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| to | string | Sim | Número destino (ex: 5511999998888) |
| isGroup | boolean | Não | Marca que o to é o id de um grupo. Dispensável se o to já vier com @g.us |
| message | string | Sim | Texto da mensagem |
| humanMode | boolean | Não | Simula comportamento humano antes do envio (marca como lido, digitando..., delay aleatorio) |
O messageId pode ser usado para rastrear o status de entrega via GET /session/{number}/messages/{messageId}/status.
O to aceita o id do grupo com o sufixo, ou o id puro junto de isGroup. A segunda forma existe para responder direto com o que veio no webhook, sem precisar montar o JID:
Grupo não passa pela checagem de cadastro no WhatsApp, que só existe para número individual. Se o grupo não existir ou o seu número não participar dele, quem recusa é o WhatsApp e o erro volta como SEND_ERROR com o texto original. Vale o mesmo para send-media, schedule-message e schedule-media.
Envia arquivo. Aceita dois formatos: upload (multipart/form-data) ou base64 (application/json).
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| to | string | Sim | Número destino |
| isGroup | boolean | Não | Marca que o to é o id de um grupo. Dispensável se o to já vier com @g.us |
| file | file | Sim | Arquivo a enviar |
| caption | string | Não | Texto de legenda (imagens, vídeos, documentos) |
| sendAudioAsVoice | boolean | Não | Enviar áudio como mensagem de voz |
| humanMode | boolean | Não | Simula comportamento humano antes do envio (marca como lido, digitando..., delay aleatorio) |
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| to | string | Sim | Número destino |
| isGroup | boolean | Não | Marca que o to é o id de um grupo. Dispensável se o to já vier com @g.us |
| base64 | string | Sim | Conteúdo do arquivo em base64 |
| filename | string | Sim | Nome do arquivo (ex: foto.jpg) |
| mimetype | string | Sim | Tipo MIME (ex: image/jpeg) |
| caption | string | Não | Texto de legenda (imagens, vídeos, documentos) |
| sendAudioAsVoice | boolean | Não | Enviar áudio como mensagem de voz |
| humanMode | boolean | Não | Simula comportamento humano antes do envio (marca como lido, digitando..., delay aleatorio) |
Consulta o status de entrega de uma mensagem enviada, usando o messageId retornado por send-message ou send-media.
O status evolui conforme o WhatsApp confirma a entrega. Cada mudança também dispara o webhook message_status_updated.
| Status | Significado |
|---|---|
| sent | Mensagem enviada pelo gateway |
| server | Recebida pelo servidor do WhatsApp |
| delivered | Entregue no aparelho do destinatário |
| read | Lida pelo destinatário |
| failed | Falha no envio |
Retorna 404 se o messageId não for encontrado para esse número.
Lista os contatos individuais do WhatsApp conectado.
Grupos não entram nesta lista. Para vê-los, use GET /session/{number}/chats.
Retorna detalhes de um contato específico, incluindo foto de perfil. O contactId é o JID do contato (ex.: 5521988887777@s.whatsapp.net).
profilePicUrl é null quando o contato não tem foto ou não permite a visualização.
Lista as conversas em memória do WhatsApp conectado.
Inclui os grupos de que o número participa. O id termina em @g.us quando é grupo e em @s.whatsapp.net quando é conversa individual.
Retorna detalhes de uma conversa com as últimas mensagens.
Aceita tanto o chatId de uma conversa individual quanto o de um grupo (...@g.us).
| Param | Tipo | Padrão | Descrição |
|---|---|---|---|
| limit | integer | 10 | Quantidade de mensagens |
| mediaBase64 | boolean | false | Incluir mídia como base64 |
Com mediaBase64=true, cada mensagem que possui mídia inclui o campo mediaBase64 com o conteúdo do arquivo.
Histórico de mensagens gravado pelo servidor, com filtro por conversa e por período. Diferente de /chats/{chatId}, que lê a memória da sessão e se perde quando a conexão cai, este histórico sobrevive a quedas e reinícios.
A retenção é de 7 dias. O valor vem em retentionDays na resposta, e o que passa da janela é apagado automaticamente. Não há histórico anterior à data em que o recurso entrou no ar.
| Param | Tipo | Padrão | Descrição |
|---|---|---|---|
| chatId | string | - | Conversa a consultar. Sem ele, traz todas as conversas do número |
| isGroup | boolean | false | Marca que o chatId é o id de um grupo, quando vier sem o sufixo @g.us |
| startDate | string | - | Início do período em ISO 8601 (ex: 2026-08-29T00:00:00-03:00) |
| endDate | string | - | Fim do período em ISO 8601 |
| limit | integer | 50 | Máximo de 200 por página |
| offset | integer | 0 | Deslocamento para paginação |
As mensagens vêm da mais recente para a mais antiga, e o total serve para montar a paginação. O período filtra pelo horário da mensagem no WhatsApp, e o fuso enviado é respeitado.
Para um grupo, use o chatId com @g.us ou o id puro com isGroup=true, que é o mesmo valor que chega no from do webhook.
Conversas que tiveram mensagem no período, com a contagem e a data da última. Serve para descobrir o que consultar sem precisar saber os ids de antemão. Aceita startDate e endDate.
Faz download da mídia de uma mensagem específica. Funciona para mensagens recebidas dentro da janela de retenção de 7 dias, mesmo que a conexão tenha caído e voltado no meio do caminho.
Desconecta e remove o número da sua conta. Faz logout do WhatsApp.
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.
Agenda uma mensagem de texto para envio futuro.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| to | string | Sim | Número destino (ex: 5511999998888) |
| isGroup | boolean | Não | Marca que o to é o id de um grupo. Dispensável se o to já vier com @g.us |
| message | string | Sim | Texto da mensagem |
| scheduledAt | string | Sim | Data/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) |
| humanMode | boolean | Não | Simula comportamento humano antes do envio |
| retryIfOffline | boolean | Não | Se o número estiver offline no horário, mantém tentando dentro da janela de retentativa |
| retryWindowMinutes | integer | Não | Janela de retentativa em minutos após o horário (padrão 30). Depois disso, marca como falho |
Agenda o envio de uma mídia. Aceita upload (multipart/form-data) ou base64 (application/json). Tamanho máximo: 16MB.
send-media)| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| to | string | Sim | Número destino |
| isGroup | boolean | Não | Marca que o to é o id de um grupo. Dispensável se o to já vier com @g.us |
| file | file | Sim* | Arquivo (multipart) — ou use base64/filename/mimetype |
| base64 / filename / mimetype | string | Sim* | Mídia em base64 (alternativa ao upload) |
| scheduledAt | string | Sim | Data/hora futura em ISO 8601. O fuso segue o valor enviado: Z = UTC; para Brasília use o offset -03:00 |
| caption | string | Não | Legenda |
| sendAudioAsVoice | boolean | Não | Enviar áudio como mensagem de voz |
| humanMode / retryIfOffline / retryWindowMinutes | - | Não | Mesmas opções de schedule-message |
Lista os agendamentos da sua conta (paginado).
| Param | Tipo | Descrição |
|---|---|---|
| status | string | Filtra por pending, processing, sent, failed ou cancelled |
| number_id | integer | Filtra por número de origem |
| limit / offset | integer | Paginação (padrão 50 / 0) |
Retorna um agendamento específico.
| Campo | Descrição |
|---|---|
| id | Identificador do agendamento |
| type | text ou media |
| to_number | Número destino |
| message | Texto (ou legenda, no caso de mídia) |
| scheduled_at | Data/hora programada do disparo |
| status | Estado atual (ver abaixo) |
| retry_if_offline / retry_until | Configuração e prazo da retentativa |
| attempts | Quantas vezes o envio foi tentado |
| message_id | ID da mensagem gerada (preenchido após o envio) |
| error_message | Motivo da falha, quando status = failed |
| sent_at | Quando foi efetivamente enviado |
| Status | Significado |
|---|---|
| pending | Aguardando o horário do disparo |
| processing | Em processamento pelo worker |
| sent | Enviado com sucesso (use message_id para acompanhar a entrega) |
| failed | Falhou definitivamente (ver error_message) |
| cancelled | Cancelado antes do disparo |
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.
logs| Campo | Descrição |
|---|---|
| status | Evento da transição (ver abaixo) |
| message | Detalhe ou motivo do evento (ex.: mensagem de erro) |
| attempt | Número da tentativa de envio no momento do evento |
| created_at | Quando o evento ocorreu |
| Evento | Significado |
|---|---|
| created | Agendamento criado |
| processing | Reservado pelo worker para envio |
| sent | Enviado com sucesso |
| requeued | Voltou para a fila (número offline com retentativa ativa, ou reinício do worker) |
| failed | Falhou (ver message com o motivo) |
| cancelled | Cancelado antes do disparo |
Cancela um agendamento. Apenas agendamentos com status pending podem ser cancelados.
Histórico paginado das chamadas feitas à API pela sua conta.
| Param | Tipo | Padrão | Descrição |
|---|---|---|---|
| limit | integer | 50 | Quantidade de registros |
| offset | integer | 0 | Deslocamento para paginação |
| startDate | string | - | Data inicial (ISO 8601) |
| endDate | string | - | Data final (ISO 8601) |
Resumo de uso no período: total de chamadas, endpoints mais usados e contagem de mensagens por status.
| Param | Tipo | Descrição |
|---|---|---|
| startDate | string | Data inicial (ISO 8601) |
| endDate | string | Data final (ISO 8601) |
Histórico das tentativas de entrega de webhook de um número, com payload, status HTTP, tentativa e erro.
| Param | Tipo | Padrão | Descrição |
|---|---|---|---|
| limit | integer | 50 | Quantidade de registros |
| offset | integer | 0 | Deslocamento para paginação |
Quando configurado, o sistema envia eventos para a URL de webhook via POST.
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.
Se a entrega falhar, o sistema faz até 3 tentativas: imediata, depois 30s e 2min. Todas as tentativas são registradas e visíveis em GET /session/{number}/webhook-logs.
Mensagens de grupo também chegam por aqui, e nelas o isGroup vem true. Nesse caso o from traz o identificador do grupo (por exemplo 120363023480137063) em vez do número de quem escreveu, o participant traz o número de quem enviou e o pushName, o nome dessa pessoa. Para responder no próprio grupo, devolva o from como to junto de isGroup: true; para falar no privado com quem escreveu, use o participant.
O participant pode vir null quando o WhatsApp identifica a pessoa apenas por um id interno e não informa o telefone. Nesse caso o pushName continua sendo a pista de quem escreveu, então trate o campo como opcional.
Enviado a cada confirmação de entrega de uma mensagem que você enviou. O campo status pode ter os seguintes valores:
| status | Significado |
|---|---|
| server | Recebida pelo servidor do WhatsApp |
| delivered | Entregue no aparelho do destinatário |
| read | Lida 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.
Enviado ao clicar em "Testar Webhook" no painel. Use para validar que a URL está acessível e a assinatura HMAC está correta.
Enviado sempre que o número entra em operação. É o par do session_disconnected: use os dois para saber se pode enviar mensagens naquele momento. O campo reason diferencia os casos:
| reason | Descrição |
|---|---|
| paired | Primeiro vínculo do número, logo após a leitura do QR Code ou do código de pareamento. É neste evento que você descobre qual telefone foi vinculado |
| reconnected | O número voltou depois de uma queda ou do reinício do servidor |
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:
| reason | Descrição |
|---|---|
| logged_out | O usuário fez logout do WhatsApp (sessão encerrada permanentemente) |
| disconnected | Desconexão temporária (queda de rede, reinício). O sistema tentará reconectar automaticamente |
Enviado quando um disparo agendado é entregue com sucesso. O messageId permite acompanhar o status (entregue/lido) pelos eventos message_status_updated.
Enviado quando um disparo agendado falha definitivamente (número não existe no WhatsApp, ou offline após esgotar a janela de retentativa).
Trate a falha sempre pelo errorCode, que é estável e nunca muda de valor. O campo error é só para exibir, e o texto acompanha o idioma escolhido para o número:
| errorCode | Quando ocorre | error (en) | error (pt-BR) |
|---|---|---|---|
| SESSION_NOT_READY | O número estava desconectado no horário do disparo e a janela de retentativa acabou | Session not ready | O número não está conectado ao WhatsApp |
| NOT_ON_WHATSAPP | O destinatário não tem WhatsApp | The number 5521988887777 is not registered on WhatsApp | O número 5521988887777 não tem WhatsApp |
| MISSING_MEDIA | A mídia do agendamento não foi encontrada na hora do envio | Scheduled media is missing | A mídia do agendamento não foi encontrada |
| SEND_ERROR | Qualquer outra falha devolvida pelo WhatsApp | Texto original do erro, sem tradução | |
O idioma é definido por número, no momento do pareamento, pelo campo language (en ou pt-BR). O padrão é en, então integrações existentes continuam recebendo exatamente o mesmo texto de antes.
| Código | Descrição |
|---|---|
400 | Requisição inválida (parâmetros faltando ou sessão não pronta) |
403 | API Key inválida ou conta inativa |
404 | Número não encontrado ou sessão pendente expirada |
429 | Rate limit excedido — muitas requisições. Verifique os headers X-RateLimit-* |
500 | Erro interno do servidor |
Além do status HTTP, toda resposta de erro traz um errorCode estável, que nunca muda de valor. Decida pelo código e use o message apenas para exibir ao usuário, já que o texto acompanha o idioma do número.
| errorCode | HTTP | Quando ocorre |
|---|---|---|
| MISSING_TO | 400 | Parâmetro to não informado |
| INVALID_TO_DIGITS | 400 | O to tem caracteres que não são dígitos |
| INVALID_TO_LENGTH | 400 | O to não tem entre 7 e 15 dígitos |
| MISSING_MESSAGE | 400 | Parâmetro message ausente ou vazio |
| SESSION_NOT_READY | 400 | O número não está conectado ao WhatsApp |
| NOT_ON_WHATSAPP | 404 | O destinatário não tem WhatsApp |
| NO_FILE | 400 | Envio de mídia sem arquivo e sem base64 |
| MEDIA_TOO_LARGE | 400 | Mídia acima do limite de 16MB |
| SCHEDULED_AT_IN_PAST | 400 | O scheduledAt não é uma data futura |
| SCHEDULED_NOT_FOUND | 404 | Agendamento inexistente ou de outra conta |
| CANNOT_CANCEL | 400 | Só agendamentos pendentes podem ser cancelados |
| NUMBER_NOT_FOUND | 404 | Número não encontrado ou de outra conta |
| MISSING_API_KEY | 403 | Header x-api-key ausente |
| INVALID_API_KEY | 403 | API Key inválida ou desativada |
| RATE_LIMIT_EXCEEDED | 429 | Limite de requisições por minuto estourado |
| FEATURE_NOT_ENABLED | 403 | Funcionalidade não liberada para a conta |
| INVALID_GROUP_ID | 400 | O to foi marcado como grupo mas não tem formato de id de grupo |
| INTERNAL_ERROR | 500 | Erro interno |
Os mesmos códigos aparecem no webhook scheduled_message_failed: uma falha de envio devolve NOT_ON_WHATSAPP tanto na resposta HTTP quanto no evento. Veja Webhooks.
O texto do message sai no idioma escolhido para o número no pareamento (campo language: en ou pt-BR). Para rotas que não têm número no path, como POST /session/connect, vale o header Accept-Language; sem ele, o padrão é en.