Skip to main content
O corpo da requisição segue sempre esta estrutura padrão, facilitando a tipagem no seu backend:
{
  "event": "message.read",
  "workspaceId": "ws_123456...",
  "instanceId": "inst_abc789...",
  "messageId": "msg_xyz000...",
  "timestamp": "2025-02-10T14:30:00.000Z",
  "data": {
    "to": "5511999999999",
    "status": "READ",
    "externalId": "wamid.HBgM..."
  }
}
O campo data varia ligeiramente dependendo do evento, mas os campos de identificação (event, ids, timestamp) são constantes.

Tabela de Eventos (Escopos)

Ao configurar um Webhook no painel, você escolhe quais eventos deseja ouvir. Para evitar ruído desnecessário no seu servidor, ative apenas o que for útil para sua aplicação.

Eventos de Mensagem (Ciclo de Vida)

  • message.sent A mensagem saiu da nossa fila e foi aceita pelos servidores da Meta. (1 tique cinza).
  • message.delivered O aparelho do destinatário recebeu a notificação. (2 tiques cinzas).
  • message.read O destinatário abriu a conversa ou deu play no áudio. (2 tiques azuis).
  • message.failed Ocorreu um erro (número inválido, bloqueio ou falha técnica) após todas as tentativas.
  • message.received Seu número recebeu uma mensagem de texto, áudio ou mídia (Inbound). Ideal para Chatbots.
  • message.responded O destinatário usou a função “Responder” (Swipe right) em uma mensagem sua específica.
  • message.deleted A mensagem foi apagada (“Apagar para todos”) pelo remetente ou via API.
  • message.edited O conteúdo do texto foi alterado após o envio.

Eventos de Instância (Conectividade)

  • instance.connecting A instância está aguardando a leitura do QR. Útil para exibir “Aguardando conexão…” na interface.
  • instance.qrcode Um novo código foi gerado e precisa ser escaneado. O payload contém o base64 da imagem.
  • instance.connected A leitura do QR Code foi bem-sucedida ou a sessão foi restaurada automaticamente.
  • instance.disconnected O celular ficou sem bateria, sem internet ou o usuário encerrou a sessão no aparelho.

Retorno de cada evento (WhatsApp)

Abaixo, o corpo completo (body) que a Notifique envia no POST para cada evento de mensagem e de instância. O campo data é o que varia; o restante da estrutura é sempre o mesmo.

Eventos de Mensagem

message.sent
{
  "event": "message.sent",
  "workspaceId": "clxxworkspace123",
  "instanceId": "clxxinstance456",
  "messageId": "clxxmessage789",
  "timestamp": "2025-02-20T14:05:00.000Z",
  "data": {
    "to": "5511999999999",
    "type": "TEXT",
    "status": "SENT",
    "sentAt": "2025-02-20T14:05:00.000Z",
    "externalId": "3EB0xxxx"
  }
}
Todos os campos em data são enviados (nenhum opcional). message.delivered
{
  "event": "message.delivered",
  "workspaceId": "clxxworkspace123",
  "instanceId": "clxxinstance456",
  "messageId": "clxxmessage789",
  "timestamp": "2025-02-20T14:05:30.000Z",
  "data": {
    "messageId": "clxxmessage789",
    "to": "5511999999999",
    "status": "DELIVERED"
  }
}
Todos os campos em data são enviados (nenhum opcional). message.read
{
  "event": "message.read",
  "workspaceId": "clxxworkspace123",
  "instanceId": "clxxinstance456",
  "messageId": "clxxmessage789",
  "timestamp": "2025-02-20T14:06:00.000Z",
  "data": {
    "messageId": "clxxmessage789",
    "to": "5511999999999",
    "status": "READ"
  }
}
Todos os campos em data são enviados (nenhum opcional). message.failed
{
  "event": "message.failed",
  "workspaceId": "clxxworkspace123",
  "instanceId": "clxxinstance456",
  "messageId": "clxxmessage789",
  "timestamp": "2025-02-20T14:05:00.000Z",
  "data": {
    "messageId": "clxxmessage789",
    "to": "5511999999999",
    "status": "FAILED",
    "reason": "instance_disconnected"
  }
}
Campo opcional em data: messageId. message.received (inbound)
{
  "event": "message.received",
  "workspaceId": "clxxworkspace123",
  "instanceId": "clxxinstance456",
  "messageId": "clxxinbound001",
  "timestamp": "2025-02-20T14:10:00.000Z",
  "data": {
    "from": "5511999999999",
    "type": "text",
    "content": "Olá!",
    "status": "RECEIVED"
  }
}
Campos em data podem variar conforme tipo da mensagem (texto, áudio, mídia). Outros campos podem ser opcionais. message.responded
{
  "event": "message.responded",
  "workspaceId": "clxxworkspace123",
  "instanceId": "clxxinstance456",
  "messageId": "clxxmessage789",
  "timestamp": "2025-02-20T14:10:00.000Z",
  "data": {
    "messageId": "clxxmessage789",
    "replyText": "Resposta do destinatário",
    "status": "RESPONDED"
  }
}
Todos os campos em data são enviados (nenhum opcional). message.deleted
{
  "event": "message.deleted",
  "workspaceId": "clxxworkspace123",
  "instanceId": "clxxinstance456",
  "messageId": "clxxmessage789",
  "timestamp": "2025-02-20T14:07:00.000Z",
  "data": {
    "messageId": "clxxmessage789",
    "to": "5511999999999",
    "status": "DELETED",
    "source": "api"
  }
}
Todos os campos em data são enviados (nenhum opcional). message.edited
{
  "event": "message.edited",
  "workspaceId": "clxxworkspace123",
  "instanceId": "clxxinstance456",
  "messageId": "clxxmessage789",
  "timestamp": "2025-02-20T14:08:00.000Z",
  "data": {
    "messageId": "clxxmessage789",
    "to": "5511999999999",
    "status": "EDITED",
    "newContent": "Texto corrigido"
  }
}
Campo opcional em data: newContent (pode ser null quando não disponível).

Eventos de Instância

instance.qrcode
{
  "event": "instance.qrcode",
  "workspaceId": "clxxworkspace123",
  "instanceId": "clxxinstance456",
  "timestamp": "2025-02-20T14:00:00.000Z",
  "data": {
    "base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
  }
}
Todos os campos em data são enviados (nenhum opcional). instance.connected
{
  "event": "instance.connected",
  "workspaceId": "clxxworkspace123",
  "instanceId": "clxxinstance456",
  "timestamp": "2025-02-20T14:01:00.000Z",
  "data": {
    "phoneNumber": "5511999999999"
  }
}
Campo opcional em data: phoneNumber (pode ser null em alguns casos). instance.disconnected
{
  "event": "instance.disconnected",
  "workspaceId": "clxxworkspace123",
  "instanceId": "clxxinstance456",
  "timestamp": "2025-02-20T14:02:00.000Z",
  "data": {}
}
data é vazio (nenhum campo). instance.connecting (aguardando leitura do QR)
{
  "event": "instance.connecting",
  "workspaceId": "clxxworkspace123",
  "instanceId": "clxxinstance456",
  "timestamp": "2025-02-20T14:00:00.000Z",
  "data": {
    "status": "AWAITING_QR",
    "message": "QR code generated; scan to connect"
  }
}
Todos os campos em data são enviados (nenhum opcional).

Segurança e Validação (Headers)

Como garantir que o POST veio da Notifique e não de um hacker? Nós enviamos headers de assinatura em todas as requisições de webhook.
  • X-Notifique-Signature Hash HMAC-SHA256 do corpo da requisição, assinado com seu Segredo de Webhook. Formato: t=timestamp,v1=hash.
  • X-Notifique-Timestamp O momento exato (Unix Timestamp) em que geramos o evento. Use para evitar Replay Attacks.
  • X-Workspace-Id O ID do workspace, para facilitar o roteamento em sistemas multi-tenant.
Dica de Segurança: Sempre verifique se o timestamp é recente (ex: menos de 5 minutos) e recalcule o hash para validar a origem.

Respostas Esperadas

O seu servidor deve responder à nossa requisição o mais rápido possível para evitar timeouts.
  • Status 2xx Sucesso. O evento é marcado como entregue e sai da nossa fila.
  • Status 4xx / 5xx / timeout Falha. Nós agendamos uma retentativa automática.
Importante: Se o seu processamento for demorado (ex: gerar um relatório complexo ao receber uma mensagem), responda 200 OK imediatamente e processe a lógica em background (background job). Se você demorar mais de 10 segundos, nós consideraremos Timeout e enviaremos de novo.