Grupos: monitorar e responder
Seu número pode participar de grupos de WhatsApp — por exemplo, o grupo que você mantém com cada cliente — e a sua integração acompanha tudo por webhook: quem escreveu, o que citou, quem mencionou, quem entrou e saiu. E responde no próprio grupo, citando a mensagem e mencionando a pessoa.
O bZapper envia pelo protocolo multi-dispositivo: tudo desta página vale para números conectados por QR code ou código de pareamento — que é como todo número envia hoje. A API oficial do WhatsApp (Cloud API) não opera grupos.
1. Colocar o número no grupo
Com o link de convite, veja o grupo antes de entrar:
curl -X POST "https://api.bzapper.com.br/groups/join/preview?instance_id=$INST" \
-H "Authorization: Bearer $BZ_KEY" -H "Content-Type: application/json" \
-d '{"code":"https://chat.whatsapp.com/AbCdEf123"}'
{ "jid": "[email protected]", "name": "Boxy Pharma — Suporte", "topic": "…", "size": 14,
"announce": false, "locked": false }
E entre com POST /groups/join?instance_id=… e o mesmo { "code" } (aceita o código ou o link
inteiro). Quando o número entra, chega group.joined.
2. Receber: quem escreveu, o que citou
Toda mensagem de grupo chega em message.received com o bloco group e o autor em sender:
{
"event_type": "message.received",
"instance_id": "…",
"group": { "jid": "[email protected]", "name": "Boxy Pharma — Suporte" },
"sender": { "jid": "[email protected]", "phone": "+5511988887777",
"lid": "55443322@lid", "name": "Rita" },
"mentions": ["[email protected]"],
"payload": {
"type": "text", "body": "@5511900001111 o pedido 4412 atrasou",
"wa_message_id": "3EB0…", "message_id": "…",
"mentioned_me": true,
"quoted_id": "3EB0…", "quoted_participant": "[email protected]"
}
}
| Campo | O que é |
|---|---|
group.name | Nome do grupo — já vem na primeira mensagem de um grupo novo |
sender.phone | Telefone de quem escreveu (+DDIdígitos). Use para saber quem é a pessoa (ex.: se é da sua equipe) |
sender.lid | Identificador de privacidade do WhatsApp. Estável por pessoa |
sender.jid | JID do autor: o de telefone quando o conhecemos, senão o @lid |
payload.mentioned_me | true quando o seu número foi mencionado |
payload.quoted_id | wa_message_id da mensagem citada (quando é resposta) |
payload.quoted_participant | Autor da mensagem citada — liga a resposta ao fio certo |
O WhatsApp identifica muitos participantes de grupo só pelo @lid. O bZapper troca pelo
telefone usando o que o WhatsApp manda junto e o mapa que a sessão já aprendeu. Se a pessoa
ainda é desconhecida, sender.phone vem vazio e sender.jid é o @lid — que continua
estável e serve para correlacionar até o telefone aparecer.
3. Responder no grupo
Envie para o JID do grupo (to: "[email protected]"), sempre com o instance_id do número que
está no grupo.
Citando a mensagem (quoted_message_id = o wa_message_id recebido) e mencionando a
pessoa:
{
"instance_id": "…",
"to": "[email protected]",
"body": "@5511988887777 já abri o chamado #812 e te aviso aqui.",
"quoted_message_id": "3EB0…",
"mentions": ["5511988887777"]
}
- Autor da citação: o bZapper acha quem escreveu a mensagem citada no histórico e monta a
citação com o autor certo. Se a citada não passou pelo bZapper, informe
quoted_participant(telefone ou JID do autor). - Menções:
mentionsaceita telefone ("5511…","+55 11 9…") ou JID. Para a menção aparecer destacada, obodyprecisa ter@seguido dos dígitos do telefone.
Reagindo — POST /messages/reaction com to = o grupo, quoted_message_id e emoji. O
autor da mensagem reagida é resolvido do mesmo jeito (ou por quoted_participant).
Marcando como lida — POST /messages/{wa_message_id}/read:
{ "instance_id": "…", "chat": "[email protected]", "wa_message_ids": ["3EB0…"], "sender": "5511988887777" }
Em grupo o recibo de leitura vai por autor. Sem sender, usamos o autor gravado de cada
mensagem; se nenhuma estiver no histórico, a resposta é 400 sender_required.
Digitando… — POST /presence/chat com { "instance_id", "to": "[email protected]", "state": "typing" }
(e "paused" para parar).
4. Eventos do grupo
| Evento | Quando |
|---|---|
group.joined | Seu número entrou no grupo |
group.left | Seu número saiu, foi removido ou o grupo foi apagado — payload.reason = left | removed | deleted. Depois dele, nada mais chega daquele grupo |
group.participant_added / group.participant_removed | Participantes entraram / saíram (payload.participants, com telefone quando conhecido) |
group.participant_promoted / group.participant_demoted | Virou / deixou de ser admin |
group.subject_changed / group.description_changed | Nome / descrição mudou |
Todos trazem group { jid, name } e, quando houver, payload.actor (quem fez a ação).
5. Participantes
GET /groups/{jid}?instance_id=… devolve o grupo com size e os participantes:
{ "jid": "[email protected]", "name": "Boxy Pharma — Suporte", "size": 14,
"participants": [
{ "jid": "55443322@lid", "phone": "+5511988887777", "lid": "55443322@lid", "is_admin": true, "is_super_admin": false }
] }
6. Enviar sem duplicar
Se a sua integração repete o envio sozinha (timeout, fila com retry), mande o cabeçalho
Idempotency-Key — a repetição devolve a mesma resposta sem mandar a mensagem de novo. Veja
Idempotência no envio.