Webhooks (eventos e payloads)
O Pilot Status permite configurar um webhook por ambiente (TEST/LIVE) e vincular esse webhook a uma API key. Quando eventos ocorrerem, o Pilot Status faz um POST JSON para a URL configurada e registra o resultado (status/resposta/duração) nos logs do painel.
Eventos
Identificadores
messageId: ID da mensagem na Evolution API/WhatsApp (ex.:key.id). Pode sernullem falhas que acontecem antes da Evolution retornar um ID.internalMessageId: ID interno da mensagem no Pilot Status (sempre presente nos eventos de status outbound).
message.sent
Disparado quando a mensagem é enviada para o provedor.
Payload:
{
"event": "message.sent",
"data": {
"messageId": "A52298BB1619CB5EC464BEFB8A3ACB94",
"internalMessageId": "cmm04obm46zz0qv4ycjp8x6r2",
"environment": "TEST",
"destinationNumber": "+5511999999999",
"content": "texto enviado",
"status": "SENT",
"sentAt": "2026-02-24T15:00:05.000Z"
}
}
message.delivered
Disparado quando a mensagem é entregue no dispositivo do destinatário (ex.: status DELIVERY_ACK do provedor).
Payload:
{
"event": "message.delivered",
"data": {
"messageId": "A52298BB1619CB5EC464BEFB8A3ACB94",
"internalMessageId": "cmm04obm46zz0qv4ycjp8x6r2",
"environment": "TEST",
"destinationNumber": "+5511999999999",
"content": "texto enviado",
"status": "DELIVERED",
"deliveredAt": "2026-02-24T15:00:05.000Z"
}
}
message.failed
Disparado quando o envio falha (ex.: erro do provedor). Pode ocorrer tanto durante o processamento de envio quanto via atualização de status do provedor.
Payload:
{
"event": "message.failed",
"data": {
"messageId": "A52298BB1619CB5EC464BEFB8A3ACB94",
"internalMessageId": "cmm04obm46zz0qv4ycjp8x6r2",
"environment": "TEST",
"destinationNumber": "+5511999999999",
"content": "texto enviado",
"status": "FAILED",
"failedAt": "2026-02-24T15:00:05.000Z",
"errorMessage": "Falha ao enviar mensagem pela Pilot Status."
}
}
message.read
Disparado quando a mensagem é marcada como lida pelo provedor (ex.: status READ/PLAYED).
Payload:
{
"event": "message.read",
"data": {
"messageId": "A52298BB1619CB5EC464BEFB8A3ACB94",
"internalMessageId": "cmm04obm46zz0qv4ycjp8x6r2",
"environment": "TEST",
"destinationNumber": "+5511999999999",
"content": "texto enviado",
"status": "READ",
"readAt": "2026-02-24T15:00:05.000Z"
}
}
message.received
Disparado quando o sistema recebe uma mensagem (via provedor).
Observação:
- Mensagens recebidas em grupos (
remoteJidcom@g.usno provedor) são entregues comomessage.group(não comomessage.received).
Payload:
{
"event": "message.received",
"data": {
"fromMe": false,
"from": "5511999999999",
"destinationNumber": "5511888888888",
"content": "Oi",
"receivedAt": "2026-02-24T10:30:00Z",
"messageId": "msg_in_id",
"environment": "LIVE",
"whatsappInstanceName": "Cliente 1"
}
}
message.group
Disparado quando o sistema recebe uma mensagem em um grupo.
Payload:
{
"event": "message.group",
"data": {
"fromNumber": "5511999999999",
"fromName": "Nome no WhatsApp",
"fromMe": false,
"groupName": "Meu Grupo",
"content": "Mensagem no grupo",
"environment": "LIVE",
"messageId": "msg_in_id"
}
}
message.reply
Disparado quando um usuário responde a uma mensagem enviada pela plataforma, seja respondendo via texto tradicional, seja clicando em um botão interativo de resposta rápida.
O sistema automaticamente correlaciona a resposta com a mensagem original. Quando o usuário clica em um botão, o ID do botão clicado é retornado no campo buttonId.
Payload:
{
"event": "message.reply",
"data": {
"from": "5511999999999",
"destinationNumber": "5511999999999",
"content": "Olá, tudo bem? Confirma seu agendamento?",
"replyContent": "Sim, confirmo",
"receivedAt": "2024-02-18T10:30:00Z",
"messageId": "msg_12345",
"quotedMessageId": "msg_original_123",
"messageRepliedId": "cmm04obm46zz0qv4ycjp8x6r2",
"environment": "LIVE",
"buttonId": "btn_confirm_123"
}
}
Nota:
buttonIdsó estará presente se a resposta foi originada de um clique em botão. Respostas de texto convencionais não possuirão este campo.
optin.created
Disparado quando o Pilot Status registra um opt-in (consentimento) para um destino em um projeto (ex.: quando o usuário envia optin <projectId> para o número do Pilot Status; a palavra optin é reconhecida sem distinção de maiúsculas/minúsculas).
Payload:
{
"event": "optin.created",
"data": {
"projectId": "proj_abc",
"environment": "TEST",
"whatsappInstanceName": "Pilot Status",
"destinationNumber": "+5511999999999",
"destinationHash": "8c1f...sha256...",
"fromName": "Nome no WhatsApp",
"isFirstOptIn": true,
"firstOptInAt": "2026-02-24T15:00:05.000Z",
"lastSeenAt": "2026-02-24T15:00:05.000Z"
}
}
Observações:
- O campo
fromNameé o nome de exibição do WhatsApp do contato que fez o opt-in, quando disponível: primeiro usa opushNameenviado pelo provedor na mensagem recebida; se vier vazio, o Pilot Status tenta obter o nome via EvolutionPOST /chat/whatsappNumbers/{instance}(mesmo fluxo usado na verificação de números). Se não houver nome ou a retenção de PII exigir ocultar dados, o valor énull. - Para números móveis brasileiros (
+55…), o sistema pode disparar mais de umPOSTcomoptin.createdpara o mesmo webhook na mesma ação: um payload por variante com e sem o 9º dígito após o DDD (ex.:+5511999999999e+551199999999), cada um com seu própriodestinationHash. OfromNamecostuma ser o mesmo nos dois envios. Trate como idempotente pordestinationHash(e/ou por pardestinationNumber+destinationHash). - O evento é disparado para todos os webhooks ativos do tenant do projeto (
optInProject.tenantId) que tenhamoptin.createdselecionado, em TEST e LIVE — não é obrigatório o webhook estar ligado a uma API key. O campoprojectIdno payload identifica qual projeto registrou o opt-in. - Webhooks com assinatura por número/instância WhatsApp só recebem o evento se a instância que recebeu a mensagem estiver entre as assinadas (ou se o webhook estiver configurado para “todos os números”).
- O campo
environmentnodataespelha o ambiente do webhook (TESTouLIVE), não o ambiente do registro de opt-in no banco. - Quando houver API key associada ao mesmo webhook, a retenção (
retentionDays) da key pode influenciar redação de PII; sem key, usa-se o padrão do produto. - Se a API key tiver retenção
retentionDays <= 0, odestinationNumberé enviado em branco e somentedestinationHashé incluído (em cada um dos envios, quando houver variantes BR); nesse casofromNametambém vem comonull.
Observações
- O webhook é disparado quando estiver ativo e com o evento permitido na lista
events(ou cache equivalente). - O sistema faz tentativa única por evento e registra o resultado nos logs (não há retry/DLQ no MVP).