Identificadores e Correlação de Eventos

22. Identificadores e Correlação de Eventos#

Está seção explica como JIDs, LIDs e números de telefone fluem pelo sistema, e como correlacionar eventos a conversas e mensagens.

Glossario de Identificadores#

Termo Formato Exemplo O que e
Phone JID <phone>@s.whatsapp.net 554196332719@s.whatsapp.net Identificador de contato individual
Group JID <id>@g.us 120363012345678901@g.us Identificador de grupo
LID <id>:<device>@lid 216251804708983:34@lid Linked ID — formato interno do WhatsApp para dispositivos vinculados
Base LID <id>@lid 216251804708983@lid LID sem sufixo de dispositivo, usado como chat JID
chat_lid <id>@lid 42812401807390@lid Campo auxiliar nos eventos — LID original do chat antes da resolução para phone JID
sender_lid <id>:<device>@lid 42812401807390:77@lid Campo auxiliar nos eventos — LID original do sender antes da resolução para phone JID
RemoteJID Phone JID ou Group JID Campo no banco que identifica a conversa
WhatsAppID string alfanumerica 3EB0A1B2C3D4E5F6 ID único da mensagem atribuido pelo WhatsApp
ExternalID UUID v4 a1b2c3d4-e5f6-... ID da mensagem na API Catcher
InstanceID UUID v4 84c2e480-... Qual instância WhatsApp (número conectado)
SenderJID Phone JID 554196332719@s.whatsapp.net Quem enviou a mensagem (util em grupos)

Normalizacao automática#

A API normaliza automaticamente todos os identificadores:

  1. LID → Phone JID: O WhatsApp pode enviar identificadores no formato LID (@lid). A API tenta resolver LIDs para Phone JID (@s.whatsapp.net) usando: campo SenderAlt do protocolo, registro de identidade de contatos (tabelas contacts/contact_identities), e busca na tabela messages como último fallback. Os campos principais (phone, chat, from, to, sender) sempre contem o phone JID quando a resolução e possível. Quando o LID original estava presente, ele e exposto nos campos auxiliares chat_lid e sender_lid para correlação.

  2. BR 13→12 digitos: Números brasileiros com 13 digitos (55XX9XXXXXXXX) são normalizados para 12 digitos (55XXXXXXXXXX), removendo o 9 extra. Isso e aplicado em todas as direcoes (inbound e outbound).

  3. Formato consistente: O campo chat em todos os eventos e identico ao campo remote_jid no banco. Você pode agrupar eventos em conversas usando instance_id + chat.

Campos LID auxiliares (chat_lid, sender_lid)#

Quando o WhatsApp usa internamente um LID para identificar um contato ou chat, a API expoe o LID original nos campos opcionais chat_lid e sender_lid (omitidos quando vazios). Esses campos são uteis para:

  • Correlação de eventos: Quando phone está vazio (primeiro contato via LID, sem mapeamento no registro), use chat_lid para agrupar message.sent + message.delivered + message.read + message.played da mesma conversa.
  • Correlação retroativa: Quando um message.received chega com phone preenchido e chat_lid presente, você pode retroativamente associar eventos anteriores que tinham phone vazio mas o mesmo chat_lid.
  • Debug: Os campos auxiliares permitem diagnosticar quando o WhatsApp opera em modo LID e verificar se a resolução de identidade está funcionando.

Disponibilidade dos campos LID por evento:

Evento chat_lid sender_lid
message.received Sim Sim
message.sent Sim
message.delivered Sim Sim
message.read Sim Sim
message.played Sim Sim
message.deleted Sim Sim
message.edited Sim Sim

Aprendizado automático: A API aprende mapeamentos LID→telefone conforme interage com contatos. Quando um contato responde (message.received com SenderAlt), o mapeamento e salvo no registro de identidade. A partir dai, todos os eventos futuros para esse LID terao phone preenchido automaticamente.

Modelo de dados da mensagem#

A tabela messages no banco de cada tenant armazena todas as mensagens (inbound e outbound):

Campo Tipo Descricao
id (UUID) UUID ID público na API (exposto como elemento de message_ids nos eventos)
instance_id string Qual instância WhatsApp
direction string "inbound" ou "outbound"
remote_jid string A conversa. Phone JID (1:1) ou Group JID (grupo)
sender_jid string Quem enviou. Phone JID do remetente. Util para mensagens de grupo, onde remote_jid e o JID do grupo
message_type string text, image, video, audio, document, sticker, location, contact, reaction, poll
content string Texto ou caption
status string queued → sent → delivered → read / failed / deleted
whatsapp_id string ID da mensagem no WhatsApp (chave de correlação para status updates)
source string "api" (fila Catcher), "external" (WhatsApp Web/celular)
media_id string Referência a mídia no S3

Como remote_jid funciona por direcao:

Cenario Inbound remote_jid Outbound remote_jid Mesmo valor?
Chat 1:1 com 5541... 554196332719@s.whatsapp.net 554196332719@s.whatsapp.net Sim
Grupo 120363... 120363012345678901@g.us 120363012345678901@g.us Sim

Não existe tabela Chat. Conversas são derivadas agrupando mensagens por remote_jid. O endpoint GET /v1/instances/{instanceId}/chats faz isso automaticamente.

Como sender_jid funciona#

Cenario sender_jid remote_jid
Inbound 1:1 554196332719@s.whatsapp.net (quem mandou) 554196332719@s.whatsapp.net (a conversa)
Inbound grupo 554196332719@s.whatsapp.net (quem mandou) 120363012345678901@g.us (o grupo)
Outbound (API) vazio (a instância e o remetente) JID do destinatário
Outbound (externo) vazio (a instância e o remetente) JID do destinatário

Para mensagens de grupo, sender_jid e essencial para saber quem disse cada coisa dentro do grupo.

Correlação: como agrupar eventos em conversas#

Chave primaria da conversa: instance_id + campo chat do evento (ou remote_jid no banco)

Chave secundaria (quando chat e um LID não resolvido): instance_id + campo chat_lid do evento

Todos os eventos de mensagem incluem o campo chat, que corresponde exatamente ao remote_jid no banco:

Evento Campo de conversa Campo auxiliar LID Campo de mensagem (UUID Catcher)
message.received chat chat_lid message_ids (array)
message.sent chat chat_lid message_ids (array)
message.delivered chat chat_lid message_ids (array)
message.read chat chat_lid message_ids (array)
message.played chat chat_lid message_ids (array)
message.deleted chat chat_lid message_ids (array)
message.edited chat chat_lid message_ids (array)

Padronizacao: todos os eventos de mensagem usam message_ids (array). Para a maioria, o array tem exatamente 1 elemento; apenas message.delivered, message.read e message.played podem trazer multiplos quando o WhatsApp agrega confirmacoes em batch. Consumers leem event.data.message_ids[0] na maioria dos casos e iteram o array nos eventos de status.

Cenario LID (APIs externas): Quando outra API envia mensagens via LID e a Catcher ainda não conhece o telefone associado, os eventos message.sent e message.delivered terao phone vazio e chat com o LID. Use chat_lid como chave de agrupamento. Quando o contato responder, a Catcher aprendera o mapeamento, e a partir dai os eventos passarao a ter phone e chat com o phone JID. Você pode correlacionar retroativamente comparando o chat_lid dos novos eventos com os anteriores.

Correlação: como rastrear o lifecycle de uma mensagem#

O ciclo de vida de uma mensagem outbound e rastreado pelo message_ids[0] (UUID do Catcher):

text
message.sent (message_ids = ["550e8400-e29b-41d4-a716-..."])
    ↓
message.delivered (message_ids = ["550e8400-e29b-41d4-a716-..."])
    ↓
message.read (message_ids = ["550e8400-e29b-41d4-a716-..."])
    ↓ (se view-once)
message.played (message_ids = ["550e8400-e29b-41d4-a716-..."])

No banco, os timestamps são atualizados conforme os eventos chegam:

text
queued_at → sent_at → delivered_at → read_at → played_at (view-once)
                           ↓
                       deleted_at (se revogada)

message_ids — UUIDs do Catcher#

O campo message_ids em todos os eventos de mensagem contem um array de UUIDs internos do Catcher (v4, 36 chars cada). Este identificador e:

  • Garantido único — nunca reciclado, mesmo quando o WhatsApp reutiliza IDs após delecao
  • Estável — o mesmo UUID persiste em todos os eventos do ciclo de vida da mensagem (received → delivered → read → played → deleted)
  • Aceito nos endpoints da API — os endpoints de delete, edit, react, forward e mark-read aceitam tanto o UUID do Catcher quanto o ID do WhatsApp (hex)

Para a maioria dos eventos (message.received, message.sent, message.deleted, message.edited, message.starred, message.deleted_for_me, media.retry_result, label.message_association), o array tem exatamente 1 elemento — leia event.data.message_ids[0]. Apenas message.delivered, message.read e message.played podem trazer multiplos elementos quando o WhatsApp agrega receipts.

Nota: message.undecryptable e o único evento onde message_ids[0] contem o ID do WhatsApp (não o UUID), pois a mensagem não pode ser persistida no banco.


Diferenciacao: 1:1 vs grupo#

O campo is_group está disponível nos seguintes eventos:

Evento is_group Como identificar se ausente
message.received Sim
message.sent Sim
message.delivered Sim
message.read Sim
message.played Sim
message.deleted Não chat termina com @g.us
message.edited Sim

Quando is_group não estiver presente, você pode inferir pelo sufixo do campo chat: @g.us = grupo, @s.whatsapp.net = individual.

Endpoints de busca por identificador#

Preciso de... Endpoint Parametro
Listar conversas GET /v1/instances/{id}/chats
Mensagens de uma conversa GET /v1/instances/{id}/chats/{chatJID}/messages chatJID = remote_jid = chat dos eventos
Uma mensagem especifica GET /v1/instances/{id}/message/{messageId} messageId = UUID do Catcher (elemento de message_ids do evento) ou ID do WhatsApp (hex)
Mídias de uma conversa GET /v1/instances/{id}/media?remote_jid={chatJID} remote_jid = chat dos eventos