Webhook e WebSocket compartilham o mesmo envelope e o mesmo catálogo de eventos. A única diferença é o canal de entrega, o data é idêntico.
Esta página documenta os 6 tipos: message.exchange , message.status , call.update , group.flow , instance.state e label.update .
Envelope
{
"event" : "<event-name>" ,
"data" : { /* payload específico */ },
"instanceData" : {
"baseUrl" : "https://api.example.com" ,
"instance" : "<name>" ,
"token" : "<instance-token>"
}
}
Filtragem é feita pelo nome do event no campo events da config. Vazio = todos os tipos.
Filtragem e roteamento
{ "events" : [ "message.exchange" , "call.update" , "instance.state" ] }
Quando byEvents=true (apenas em webhook), o nome do evento é anexado à URL :
Config: url: "https://app/wh", byEvents: true
Delivery: POST https://app/wh/message.exchange
Útil para roteamento por endpoint sem precisar inspecionar o payload.
message.exchange
Mensagens enviadas e recebidas (texto, mídia, sticker, documento, áudio, enquete, contato, localização, etc.), edits e revogações.
Payload
{
"id" : "wamid.msg.123" ,
"message" : {
"id" : "wamid.msg.123" ,
"direction" : "incoming | outgoing" ,
"timestamp" : "2026-04-28T10:30:00Z" ,
"chat" : {
"jid" : "5511999999999" ,
"lid" : "100@s.whatsapp.net" ,
"name" : "João Silva" ,
"type" : "private | group | newsletter" ,
"isCommunity" : true
},
"sender" : {
"jid" : "5511999999999" ,
"lid" : "100@s.whatsapp.net" ,
"name" : "João Silva"
},
"content" : { "text" : "Ola" },
"media" : {
"type" : "image | video | audio | document | sticker | ptt | ptv" ,
"url" : "https://media-...whatsapp.net/..." ,
"s3Url" : "https://bucket.s3.amazonaws.com/..." ,
"base64" : "iVBORw0KGgo..." ,
"mimetype" : "image/jpeg" ,
"size" : 45678 ,
"caption" : "Foto do evento" ,
"fileName" : "doc.pdf"
},
"edit" : {
"original_id" : "wamid.original" ,
"originalContent" : "Texto antigo" ,
"text" : "Texto novo"
},
"forward" : { "count" : 2 },
"reply" : {
"message_id" : "wamid.replied" ,
"sender" : { "jid" : "..." , "name" : "..." },
"text" : "..." ,
"media" : { /* objeto media simplificado */ }
},
"poll" : {
"title" : "Qual sabor?" ,
"options" : [{ "name" : "Chocolate" , "count" : 0 }]
},
"location" : {
"latitude" : -23.5505 ,
"longitude" : -46.6333 ,
"address" : "Av. Paulista, 1374"
},
"contact" : {
"display_name" : "Maria" ,
"phone_number" : "5511987654321" ,
"vcard" : "BEGIN:VCARD..."
},
"list_response" : {
"title" : "..." ,
"body" : "..." ,
"list_type" : "single_select" ,
"single_select_reply" : { "option_name" : "p1" }
},
"button_response" : {
"title" : "Comprar" ,
"body" : "..." ,
"selected_button_id" : "buy_camiseta"
},
"interactive" : { /* form / native flow / outras superfícies */ }
}
}
Campos condicionais
Apenas os campos relevantes para o tipo da mensagem são preenchidos. Edits têm edit populado; revogações chegam com type: "message_revoke" em data.message.type.
chat.isCommunity aparece apenas quando true , indica que o chat é o canal de aviso (parent / announcement channel) de uma comunidade WhatsApp. Subgrupos vinculados a uma comunidade continuam com type: "group" e sem o campo isCommunity. Em grupos comuns e DMs o campo também é omitido.
media.base64 só aparece quando mediaBase64=true na config (webhook ou WebSocket). Caso contrário, use media.url (whatsapp.net, expira) ou media.s3Url (se S3 estiver configurado na instância).
Exemplo (recebimento de imagem)
{
"event" : "message.exchange" ,
"data" : {
"id" : "wamid.123" ,
"message" : {
"id" : "wamid.123" ,
"direction" : "incoming" ,
"timestamp" : "2026-04-28T10:30:00Z" ,
"chat" : { "jid" : "5511999999999" , "name" : "João" , "type" : "private" },
"sender" : { "jid" : "5511999999999" , "name" : "João" },
"media" : {
"type" : "image" ,
"url" : "https://media-abc.whatsapp.net/..." ,
"mimetype" : "image/jpeg" ,
"size" : 45678 ,
"caption" : "Foto"
}
}
},
"instanceData" : { "baseUrl" : "https://api..." , "instance" : "minha" , "token" : "..." }
}
message.status
Recibos de entrega: delivered, read, played, etc.
Payload
{
"status" : "delivered | read | played | sender | read_self | played_self | retry | inactive | server_error" ,
"messageIds" : [ "wamid.123" , "wamid.124" ],
"timestamp" : "2026-04-28T10:45:00Z" ,
"chat" : {
"jid" : "5511999999999" ,
"type" : "private | group | broadcast" ,
"isCommunity" : true
},
"recipient" : "5511999999999" ,
"messageSender" : null ,
"isFromMe" : false
}
Enum status
Valor Significado deliveredMensagem chegou no device do destinatário. readDestinatário leu (read receipts ativos). playedÁudio/voice note foi reproduzido. senderEco interno (a própria origem reportando entrega). read_selfO próprio usuário marcou como lido em outro device. played_selfO próprio usuário reproduziu em outro device. retryServidor pediu reentrega (transient). inactiveDestinatário offline há tempo demais. server_errorErro genérico do servidor WhatsApp.
messageSender em grupos : JID do autor original da mensagem (relevante quando alguém leu uma mensagem de outro participante).
chat.isCommunity segue a mesma regra de message.exchange: presente e true apenas quando o chat é o canal de aviso de comunidade.
call.update
Eventos de chamada: oferta, aceite, recusa, encerramento, latência.
Payload
{
"type" : "offer | accepted | rejected | terminated | notification | latency" ,
"direction" : "incoming | outgoing" ,
"callId" : "call-abc123" ,
"from" : "5511999999999" ,
"to" : "5511888888888" ,
"timestamp" : "2026-04-28T10:35:00Z" ,
"groupJid" : null ,
"callMedia" : "audio | video | null" ,
"remotePlatform" : "Android | iPhone | null" ,
"remoteVersion" : "2.23.15.74" ,
"noticeType" : "group | null" ,
"reason" : null ,
"duration" : 123 ,
"latency" : 45.6 ,
"latencyStatus" : "Excellent | Good | Average | Poor"
}
Enum type
Valor Quando dispara offerChamada recebida/enviada (toque inicial). acceptedLado remoto atendeu. rejectedLado remoto rejeitou. terminatedChamada encerrada, duration em segundos vem populado. notificationNotificação contextual de chamada (ex.: chamada perdida em grupo). latencyMétrica de latência durante a chamada (latency em ms, latencyStatus).
Para rejeitar chamadas automaticamente, configure autoRejectCalls=true no bloco settings da instância , você ainda recebe os eventos offer + rejected no webhook.
group.flow
Mudanças em grupos: membros, metadata, settings.
Payload, participant change
{
"type" : "joined | left | promoted | demoted" ,
"groupJid" : "120363406289005073@g.us" ,
"groupName" : "Time de Dev" ,
"timestamp" : "2026-04-28T11:00:00Z" ,
"participants" : [
{ "jid" : "5511999999999" , "action" : "joined" }
]
}
typeSignificado nameNome do grupo alterado topicDescrição alterada locked / unlockedMembers can/cannot edit info announce / not_announceMembers can/cannot send messages ephemeral / not_ephemeralMensagens efêmeras on/off inviteInvite link gerado link / unlinkSubgrupo vinculado/desvinculado de comunidade deleteGrupo deletado membership_approvalModo de aprovação de novos membros alterado suspended / unsuspendedGrupo suspenso/reativado pelo WhatsApp
instance.state
Mudanças no estado da própria instância (conexão, QR, ban, pareamento).
Payload
{
"instance" : "minha" ,
"state" : "connected | disconnected | logged_out | stream_replaced | temp_banned | client_outdated | connect_failure | stream_error | cat_refresh_error | qr_ready | pair_success | pair_error | qr_scanned_no_multidevice | keepalive_timeout | keepalive_restored | manual_reconnect" ,
"timestamp" : "2026-04-28T10:50:00Z" ,
"reason" : "..." ,
"reasonCode" : 123 ,
"message" : "..." ,
"expireAt" : "2026-04-28T11:50:00Z" ,
"expireInSeconds" : 3600 ,
"onConnect" : true ,
"codes" : [ "1@abc...,xyz==,base64string" ],
"jid" : "5511999999999@s.whatsapp.net" ,
"platform" : "iPhone | Android | Desktop" ,
"errorMsg" : "..."
}
Enum state
State Significado Campos extras populados connectedSessão ativa, pronta para enviar/receber. , disconnectedDesconectado (transient, geralmente reconecta sozinho). , logged_outSessão invalidada (precisa novo connect). reasonstream_replacedOutra sessão tomou o lugar (multi-device conflict). , temp_bannedBan temporário aplicado pelo WhatsApp. expireAt, expireInSeconds, reasonclient_outdatedVersão do WhatsApp Web em uso está obsoleta, entre em contato com o suporte. messageconnect_failureFalha durante conexão. reason, reasonCodestream_errorErro de stream do WhatsApp. errorMsgcat_refresh_errorFalha ao renovar credenciais (cat). errorMsgqr_readyNovo QR disponível para pareamento. codes[], onConnectpair_successPareamento concluído. jid, platformpair_errorErro durante o pareamento. errorMsgqr_scanned_no_multideviceQR escaneado mas o device-alvo não tem multidevice. , keepalive_timeoutConexão instável, keepalive não respondido. , keepalive_restoredConexão estabilizou após keepalive_timeout. , manual_reconnectReconexão disparada manualmente via REST. ,
Para o seu cliente saber quando recarregar o QR na UI, escute instance.state com state=qr_ready e renderize data.codes[0].
label.update
Edição/associação de etiquetas (WhatsApp Business labels).
Payload
{
"type" : "edit | chat | message" ,
"labelId" : "1" ,
"timestamp" : "2026-04-28T10:00:00Z" ,
"action" : "updated | deleted | add | remove" ,
// type=edit:
"name" : "Important" ,
"color" : 0 ,
"labelType" : "CUSTOM" ,
"isActive" : true ,
"isImmutable" : false ,
"orderIndex" : 1 ,
"deleted" : false ,
// type=chat:
"chatJid" : "5511999999999@s.whatsapp.net" ,
"labeled" : true ,
// type=message:
"messageId" : "wamid.abc"
}
Combinações type × action
typeaction válidaCampos extras editupdated, deletedname, color, labelType, isActive, isImmutable, orderIndex, deletedchatadd, removechatJid, labeledmessageadd, removechatJid, messageId
Eventos não emitidos (internos)
Capturados pelo handler whatsmeow mas não propagados via webhook/WS:
*events.Picture, mudança de foto de perfil (apenas logado).
*events.FBMessage, Facebook Business (apenas logado).
*events.HistorySync, sync de histórico (processado e gravado em DB).
Se você precisar consumir alguma dessas mudanças, faça polling pelos endpoints REST correspondentes (perfil, histórico).
Referências
Configurar webhook Filtre os eventos via events[] na config.
Configurar WebSocket Mesma sintaxe de filtro do webhook.
Conectar via WebSocket Receba os eventos em tempo real.
Visão geral de Eventos Comparação webhook x WebSocket.