Skip to main content

Groups: monitor and reply

Your number can take part in WhatsApp groups — for example, the group you keep with each customer — and your integration follows everything by webhook: who wrote, what they quoted, who they mentioned, who joined and left. And it replies in the group itself, quoting the message and mentioning the person.

Applies to numbers connected from the dashboard

bZapper sends over the multi-device protocol: everything on this page applies to numbers connected by QR code or pairing code — which is how every number sends today. The official WhatsApp API (Cloud API) doesn't operate groups.

1. Put the number in the group​

With the invite link, look at the group before joining:

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 — Support", "topic": "…", "size": 14,
"announce": false, "locked": false }

Then join with POST /groups/join?instance_id=… and the same { "code" } (accepts the code or the full link). When the number joins, group.joined arrives.

2. Receive: who wrote, what they quoted​

Every group message arrives as message.received with the group block and the author in sender:

{
"event_type": "message.received",
"instance_id": "…",
"group": { "jid": "[email protected]", "name": "Boxy Pharma — Support" },
"sender": { "jid": "[email protected]", "phone": "+5511988887777",
"lid": "55443322@lid", "name": "Rita" },
"mentions": ["[email protected]"],
"payload": {
"type": "text", "body": "@5511900001111 order 4412 is late",
"wa_message_id": "3EB0…", "message_id": "…",
"mentioned_me": true,
"quoted_id": "3EB0…", "quoted_participant": "[email protected]"
}
}
FieldWhat it is
group.nameGroup name — present already on the first message of a new group
sender.phoneAuthor's phone (+CCdigits). Use it to know who the person is (e.g. whether they're on your team)
sender.lidWhatsApp privacy identifier. Stable per person
sender.jidAuthor JID: the phone one when we know it, otherwise the @lid
payload.mentioned_metrue when your number was mentioned
payload.quoted_idwa_message_id of the quoted message (when it's a reply)
payload.quoted_participantAuthor of the quoted message — ties the reply to the right thread
When there's no phone

WhatsApp identifies many group participants only by @lid. bZapper swaps it for the phone using what WhatsApp sends alongside and the map the session has already learned. If the person is still unknown, sender.phone is empty and sender.jid is the @lid — which stays stable and can be used for correlation until the phone shows up.

3. Reply in the group​

Send to the group JID (to: "[email protected]"), always with the instance_id of the number that is in the group.

Quoting the message (quoted_message_id = the received wa_message_id) and mentioning the person:

{
"instance_id": "…",
"to": "[email protected]",
"body": "@5511988887777 I opened ticket #812 and will update you here.",
"quoted_message_id": "3EB0…",
"mentions": ["5511988887777"]
}
  • Quote author: bZapper finds who wrote the quoted message in the history and builds the quote with the right author. If the quoted message didn't go through bZapper, send quoted_participant (the author's phone or JID).
  • Mentions: mentions accepts phones ("5511…", "+55 11 9…") or JIDs. For the mention to be highlighted, body must contain @ followed by the phone digits.

Reacting — POST /messages/reaction with to = the group, quoted_message_id and emoji. The reacted message's author is resolved the same way (or via quoted_participant).

Marking as read — POST /messages/{wa_message_id}/read:

{ "instance_id": "…", "chat": "[email protected]", "wa_message_ids": ["3EB0…"], "sender": "5511988887777" }

In a group the read receipt goes per author. Without sender, we use each message's stored author; if none is in the history, the answer is 400 sender_required.

Typing… — POST /presence/chat with { "instance_id", "to": "[email protected]", "state": "typing" } (and "paused" to stop).

4. Group events​

EventWhen
group.joinedYour number joined the group
group.leftYour number left, was removed, or the group was deleted — payload.reason = left | removed | deleted. After it, nothing else arrives from that group
group.participant_added / group.participant_removedParticipants joined / left (payload.participants, with phone when known)
group.participant_promoted / group.participant_demotedBecame / stopped being admin
group.subject_changed / group.description_changedName / description changed

All carry group { jid, name } and, when present, payload.actor (who did it).

5. Participants​

GET /groups/{jid}?instance_id=… returns the group with size and the participants:

{ "jid": "[email protected]", "name": "Boxy Pharma — Support", "size": 14,
"participants": [
{ "jid": "55443322@lid", "phone": "+5511988887777", "lid": "55443322@lid", "is_admin": true, "is_super_admin": false }
] }

6. Send without duplicates​

If your integration retries sends on its own (timeout, queue with retry), send the Idempotency-Key header — the retry returns the same response without sending the message again. See Send idempotency.