Skip to content

Contatos

Hub persiste a lista de contatos do celular pareado em DB proprio. Vale como backup forense — se o chip e banido, voce ainda tem snapshot (nomes, telefones, fotos, bios). Endpoints exigem admin key.

Origem dos dados

3 caminhos populam a tabela contacts:

  1. messaging-history.set — dispara apenas apos pareamento inicial. Traz a agenda inteira de uma vez.
  2. contacts.upsert / contacts.update — em tempo real conforme contatos sao adicionados/editados no celular.
  3. handleInbound — toda mensagem recebida enriquece o registro do remetente (phone_number real via key.senderPn, notify, etc).

⚠️ Limitacao do WhatsApp moderno: sync inicial (messaging-history.set) hoje entrega contatos so como LID puro (sem telefone) por privacidade Meta. Cruzamento LID↔telefone vem das mensagens recebidas. Pra um chip ja pareado, fazer repair e a unica forma de re-disparar o sync inicial.

GET /v1/chips/:chipId/contacts

Lista contatos com paginacao por cursor.

Query params

ParamTipoNotas
searchstring opcionalmatch por nome/notify/phone_number/jid (case-insensitive)
limitint 1-200, default 50tamanho da pagina
cursorULID opcionalid do ultimo item da pagina anterior

Response

{
"data": [
{
"id": "01HZTQ...",
"chip_id": "...",
"jid": "5511999998888@s.whatsapp.net",
"lid": "12345678901234@lid",
"phone_number": "5511999998888",
"name": null,
"notify": "Maria",
"verified_name": null,
"status_text": null,
"has_photo": true,
"photo_url": "/v1/chips/.../contacts/.../photo",
"last_synced_at": "...",
"removed_at": null,
"created_at": "...",
"updated_at": "..."
}
],
"next_cursor": "01HZTQ...",
"total": 137
}

name (agenda) frequentemente e null — WA so envia em casos especificos (privacidade do operador). Use notify (pushName) como fallback.

photo_url aponta pro endpoint de stream — concatenar com base URL.

GET /v1/chips/:chipId/contacts/:jid

Detalhe de 1 contato. :jid precisa ser url-encoded (@ vira %40).

Terminal window
curl "$HUB/v1/chips/$CHIP_ID/contacts/5511999998888%40s.whatsapp.net" \
-H "Authorization: Bearer $ADMIN_KEY"

Mesmo schema do item da lista.

404 contact-not-found se o JID nao existe no DB.

GET /v1/chips/:chipId/contacts/:jid/photo

Stream da foto de perfil. Lazy fetch: se ainda nao cacheou, hub baixa via Baileys, salva no MinIO, e responde.

Terminal window
curl "$HUB/v1/chips/$CHIP_ID/contacts/5511...%40s.whatsapp.net/photo" \
-H "Authorization: Bearer $ADMIN_KEY" \
-o foto.jpg

Headers de resposta:

Content-Type: image/jpeg
Cache-Control: private, max-age=3600

Cache local de 1h no cliente HTTP. No MinIO fica indefinidamente (ate proximo update detectado).

Erros

StatusCodeQuando
404contact-not-foundJID nao esta na tabela
404(proprio body)contato nao tem foto OU bloqueia visualizacao
503chip-offlinechip nao esta connected, nao da pra fetch

Estrategia pra app consumidora

  1. Listar contatos via GET /v1/chips/:chipId/contacts?search=maria
  2. Renderizar lista com notify (ou name) + telefone
  3. Na tela de detalhe, fazer <img src="{photo_url}"> direto — primeiro hit faz fetch async, subsequentes cacheiam
  4. Pra cross-match com sua base interna: usar phone_number (quando nao-vazio) ou lid