Eventos de ciclo de vida de grupo
O Turbo Notify envia 10 webhooks próprios quando o seu número entra ou sai
de grupos ou quando o estado de um grupo muda. Todos seguem o
formato group.{ação}, com a ação no passado (como em
contact.name_changed).
| Tipo | Quando |
|---|---|
group.joined | Seu número foi adicionado a um grupo (ou criou um) |
group.left | Seu número foi removido, saiu, ou o grupo foi desfeito |
group.name_changed | O nome do grupo mudou |
group.description_changed | A descrição do grupo mudou |
group.picture_changed | A foto do grupo mudou |
group.settings_changed | Uma configuração mudou (announce, locked, ephemeral, parent) |
group.participants_added | Outros participantes foram adicionados ao grupo |
group.participants_removed | Outros participantes foram removidos |
group.participants_promoted | Participantes foram promovidos a admin |
group.participants_demoted | Admins foram rebaixados |
O data de cada evento group.* segue o mesmo padrão do data de message.*: o id
público do grupo vem no primeiro nível como id (grp_{hex32}), junto com name,
mais os campos padrão de contexto direction: "inbound" (eventos de grupo
chegam pelo WhatsApp), channel: "whatsapp" e origin: "tn".
Os campos que indicam quem fez a ação têm duas formas: verifique qual antes de usar.
participants[]e alguns*_bysão objetos de pessoa ({contact_id, name, number}, podem ser nulos); os demais*_bysão o telefone em dígitos (string, ex.:"5511988887777").
- Objeto de pessoa (
{contact_id, name, number}):participants[],added_by,removed_byemgroup.participants_removed,promoted_by,demoted_by.- Telefone em dígitos (string):
joined_by,removed_byemgroup.left, echanged_bynos eventosgroup.name_changed,group.description_changedegroup.settings_changed.group.picture_changednão trazchanged_by: a mudança de foto é percebida pela comparação do hash da imagem, sem um autor identificável.Cuidado com
removed_by: ele muda de forma entre os dois eventos que o trazem. É objeto de pessoa emgroup.participants_removede string emgroup.left. Nos campos que são string,*_by.numberéundefined: use o valor diretamente.
Campo
at. Os eventos que refletem uma ação real no WhatsApp (group.name_changed,group.description_changed,group.settings_changed,group.participants_added,group.participants_removed,group.participants_promoted,group.participants_demotedegroup.left) trazemdata.atcom o momento real da ação no WhatsApp (diferente docreated_atdo envelope). Jágroup.joinedegroup.picture_changednão trazemat: são situações percebidas pelo Turbo Notify, sem um momento único de ação no WhatsApp. Nesses casos, vale apenas ocreated_atdo envelope.
Exemplos
O primeiro exemplo (
group.joined) mostra o envelope completo. Para encurtar, os demais mostram apenastypeedata; o envelope é idêntico: todo eventogroup.*traznumber_alias(o identificador do número dono do evento) logo abaixo deorganization_id, junto comidecreated_at.
group.joined
{ "id": "evt_...", "type": "group.joined", "organization_id": "org_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4", "number_alias": "support", "number_id": "num_5f60718293a4b5c6d7e8f90a1b2c3d4e", "created_at": "2026-05-25T10:00:00Z", "data": { "id": "grp_9f6f0b37c98043e5835822eeae550e77", "name": "Grupo A", "joined_by": "5511988887777", "creation": false, "initial_participants_count": 7, "direction": "inbound", "channel": "whatsapp", "origin": "tn" }}id/namesão o id público (grp_{hex32}) e o nome do grupo naquele momento (o grupo é o assunto do evento).group.joinednão trazdata.at: é a entrada no grupo percebida pelo Turbo Notify, sem um momento de ação próprio no WhatsApp; use ocreated_atdo envelope.joined_byé o número (string de dígitos) do admin que adicionou o seu número. Omitido (chave ausente, nuncanull) quando o evento vem da criação do grupo pelo seu próprio número (creation=true).
group.left
{ "type": "group.left", "data": { "id": "grp_...", "name": "Grupo A", "removed_by": "5511988887777", "reason": "removed", "direction": "inbound", "channel": "whatsapp", "origin": "tn", "at": "2026-05-25T10:01:00Z" }}reason é informativo: removed (removido por um admin), left (você saiu),
deleted (grupo desfeito).
group.name_changed
{ "type": "group.name_changed", "data": { "id": "grp_...", "name": "Grupo A 2.0", "old_name": "Grupo A", "changed_by": "5511988887777", "direction": "inbound", "channel": "whatsapp", "origin": "tn", "at": "2026-05-25T10:02:00Z" }}name é o nome novo (atual) do grupo; old_name é o nome anterior. Não há
campo new_name: name já traz o nome novo (mesma forma de
contact.name_changed).
group.description_changed
{ "type": "group.description_changed", "data": { "id": "grp_...", "name": "Grupo A 2.0", "old_description": "...", "new_description": "...", "changed_by": "5511988887777", "direction": "inbound", "channel": "whatsapp", "origin": "tn", "at": "2026-05-25T10:03:00Z" }}group.picture_changed
Enviado apenas quando uma foto de grupo real é armazenada com sucesso no seu BYO Storage.
O bloco picture segue o mesmo ciclo de vida da mídia
de mensagem: kind: "available" com uma URL pré-assinada e com validade
limitada (url_expires_at, cerca de 15 min) do seu bucket, nunca uma URL do WhatsApp.
{ "type": "group.picture_changed", "data": { "id": "grp_...", "name": "Grupo A 2.0", "picture": { "kind": "available", "url": "https://<bucket>.r2.cloudflarestorage.com/groups/.../picture.jpg?...", "url_expires_at": "2026-05-25T10:19:00Z", "hash": "abc123..." }, "direction": "inbound", "channel": "whatsapp", "origin": "tn" }}Este evento não traz data.at (use o created_at do envelope para saber
quando ele foi enviado), changed_by nem picture.fetched_at: a
mudança é percebida pela comparação do hash da imagem, sem um autor identificável, e a
validade da URL já aparece em picture.url_expires_at. O fetched_at
aparece nas duas formas de leitura de grupo: GET /v1/numbers/{ref}/groups
(listagem) e GET /v1/numbers/{ref}/groups/{group_id} (detalhe). Nunca neste webhook.
Guarde o picture.hash para detectar mudanças reais e baixe a foto de novo
antes que a URL pré-assinada expire (url_expires_at). Para ler a foto quando
quiser, use GET /v1/numbers/{ref}/groups/{group_id}/picture,
onde {ref} é o number_id do envelope deste evento (o seu número
que participa do grupo, não muda) ou o alias atual dele.
Pré-requisito: BYO Storage. Este evento só é enviado quando você tem uma integração de armazenamento de objetos habilitada: o Turbo Notify não entrega links do WhatsApp. Sem armazenamento, a foto fica
unavailablee nenhumgroup.picture_changedé enviado. Veja como em Configurar o BYO Storage.
A foto fica disponível depois. Se um grupo foi visto enquanto você não tinha armazenamento configurado (ou o grupo ainda não tinha foto) e uma foto chega ao BYO Storage mais tarde, o Turbo Notify envia o
group.picture_changedautomaticamente assim que a foto é salva no seu bucket.
group.settings_changed
Um evento por configuração que mudou (o WhatsApp pode enviar várias mudanças ao mesmo tempo; cada uma vira um evento).
{ "type": "group.settings_changed", "data": { "id": "grp_...", "name": "Grupo A 2.0", "setting": "announce", "old_value": false, "new_value": true, "changed_by": "5511988887777", "direction": "inbound", "channel": "whatsapp", "origin": "tn", "at": "2026-05-25T10:05:00Z" }}setting: announce (apenas admins enviam mensagens), locked (apenas admins
editam os dados do grupo), ephemeral (temporizador em segundos para mensagens
temporárias) ou parent (o grupo está vinculado a uma comunidade).
group.participants_added
Um único webhook por operação: todos os participantes adicionados juntos vêm no mesmo evento.
{ "type": "group.participants_added", "data": { "id": "grp_...", "name": "Grupo A 2.0", "participants": [ { "contact_id": "ct_...", "number": "5511555555555" }, { "number": "5511444444444" } ], "added_by": { "contact_id": "ct_...", "number": "5511988887777" }, "direction": "inbound", "channel": "whatsapp", "origin": "tn", "at": "2026-05-25T10:06:00Z" }}participants[]lista quem foi adicionado.added_byé o admin que fez a ação. Omitido (chave ausente, nuncanull) quando não foi possível identificar quem fez a ação.contact_idvem preenchido quando o participante já era seu contato. O Turbo Notify não cria contatos para participantes vistos apenas nestes eventos, para proteger a privacidade deles (LGPD) e não ocupar a sua cota.
group.participants_removed
Mesma forma de added, com removed_by no lugar de added_by.
group.participants_promoted
Mesma forma, com promoted_by no lugar de added_by. Não muda o
participants_count do grupo.
group.participants_demoted
Mesma forma, com demoted_by. Não muda o participants_count.
Várias mudanças ao mesmo tempo
Quando o WhatsApp informa várias mudanças de uma vez (por exemplo, nome, descrição e 5 adições na mesma atualização), o Turbo Notify envia um webhook por mudança. Assim, você filtra pelo tipo que quiser sem precisar interpretar um evento com vários formatos.
Idempotência
Em situações excepcionais, o mesmo evento pode ser entregue mais de uma vez.
Cada evento traz um id único (evt_…), o mesmo em todas as tentativas de
entrega: use-o como chave para eliminar duplicatas do seu lado (guarde os id
recebidos e ignore qualquer nova entrega do mesmo id).