Sign inGet Started

Gestión de grupos de WhatsApp

Todo lo que hace la página Groups, doce operaciones bajo /v1/whatsapp/groups también lo hacen, así que toda la vida de un grupo cabe en código: créalo, espera a que WhatsApp lo confirme, comparte su enlace de invitación, decide quién entra, mantén al día sus datos y sus mensajes fijados, y elimínalo cuando la conversación termine.

Dos cosas condicionan cada llamada en esta página. Nadie puede ser añadido a un grupo, así que el enlace de invitación es la única forma de entrar, e invitar personas ocurre fuera de la API. La mayoría de los cambios se consolidan en WhatsApp en lugar de en la respuesta, así que la llamada que acepta un cambio no es la que te dice que funcionó; Cómo se consolida un cambio cubre eso una sola vez para cada operación a la que aplica.

Grupos de WhatsApp cubre para qué sirve un grupo y el mismo ciclo de vida en el panel. Enviar a un grupo de WhatsApp cubre cómo enviar mensajes a uno.

Requisitos previos

Necesitas una clave de API con acceso a whatsapp_management: nivel de lectura para las consultas de esta página, nivel de escritura para todo lo demás. Usuarios, equipos y roles cubre cómo otorgarlo.

También necesitas un número de empresa con estatus de Official Business Account, que WhatsApp exige al administrador de un grupo y que Antes de crear un grupo cubre cómo obtener. GET /v1/whatsapp/numbers lo reporta por número como is_official_business_account, así que léelo ahí en lugar de descubrirlo a partir de un 412. La marca corresponde al meta_synced_at del número, así que un número conectado hace minutos puede no haberse leído aún.

Inicializa el cliente para tu lenguaje usando la guía de SDK de TypeScript, Python, Go o PHP. Para los ejemplos de CLI, instala y autentícate en el CLI. Los ejemplos de cURL usan el host de EE. UU.; si tu clave comienza con bk_eu1_, llama a https://eu1.platform.bird.com en su lugar. Los SDK leen la región de tu clave, así que no establecen host.

1. Crea el grupo

Una creación nombra el número administrador y un asunto, y a nadie más. Dos opciones quedan fijas durante toda la vida del grupo y no se pueden cambiar después: el número y join_approval_mode, que decide si abrir el enlace de invitación admite a alguien directamente (auto_approve, el valor predeterminado) o genera una solicitud que tú decides (approval_required).

Note: creating a group needs a business number with Official Business Account status, the blue check mark WhatsApp puts next to a business name in the chat. WhatsApp Official Business Account covers what Meta requires and how to request it.

const group = await bird.whatsapp.groups.create({
  whatsapp_number_id: "wan_01krdgeqcxet5s7t44vh8rt9mg",
  subject: "Norwood Fleet — Tuesday route",
  join_approval_mode: "approval_required",
});
console.log(group.id, group.status); // pending; read it back for the invite link

API devuelve 202 con el grupo en status pending y sin invite_link: WhatsApp emite el enlace cuando confirma el grupo. El asunto admite hasta 128 caracteres y una description opcional hasta 2048, y ambos se muestran a cualquiera que abra el enlace, así que nombra el grupo según su propósito en lugar de una referencia interna.

2. Esperar a que WhatsApp lo confirme

Vuelve a leer el grupo hasta que su status deje de ser pending. La lectura responde 200 sea cual sea el estado, así que bifurca según status en lugar de según si la llamada tuvo éxito.

const group = await bird.whatsapp.groups.get("wag_01krdgeqcxet5s7t44vh8rt9mg");
console.log(group.status, group.invite_link);

Pueden volver cinco estados, y solo uno de ellos es un grupo con el que puedes trabajar:

EstadoQué significa
pendingWhatsApp no ha confirmado el grupo. invite_link es null y nada aquí se puede compartir
activeEl grupo existe, su enlace de invitación funciona y acepta mensajes y cambios
suspendedWhatsApp detuvo la actividad en el grupo. Solo WhatsApp puede levantar esto
deletedEl grupo ya no existe, pero sigue siendo legible para que una referencia almacenada aún resuelva
failedWhatsApp rechazó la creación, lo cual es terminal

failed es la otra salida de pending, y last_operation.last_error.description lleva la razón propia de WhatsApp. Nunca reintentes una creación fallida contra ese grupo: crea uno nuevo, cambiando lo que el rechazo objetó.

3. Dejar entrar personas al grupo

Envía el invite_link del grupo a las personas que quieres dentro, por cualquier canal que ya las alcance. Ninguna operación añade un participante, así que el enlace es la única forma de entrar y unirse es decisión de cada persona. Admite a cualquiera que lo tenga, así que trátalo como la credencial que es: Grupos de WhatsApp cubre hasta dónde difundir uno.

En un grupo auto_approve, cualquiera que tenga el enlace entra y no hay nada que decidir. En un grupo approval_required, abrir el enlace genera una solicitud de ingreso. Lista las que están pendientes y luego decídelas en lotes de hasta 50:

const waiting = [];
for await (const request of bird.whatsapp.groups.joinRequests.list(
  "wag_01krdgeqcxet5s7t44vh8rt9mg",
)) {
  waiting.push(request.id);
}
const result = await bird.whatsapp.groups.joinRequests.approve("wag_01krdgeqcxet5s7t44vh8rt9mg", {
  join_request_ids: waiting.slice(0, 50),
});
console.log(result.decided.length, result.failed.length);

WhatsApp decide cada solicitud por separado, así que un lote es parcialmente aplicable: la respuesta separa decided de failed, y cada fallo lleva la razón que WhatsApp dio en error.description. Lee la respuesta en lugar del código de estado. Un rechazo suele deberse a una persona que no ha aceptado los términos vigentes de WhatsApp, lo cual ningún reintento corrige.

Aprobar más personas de las que caben en el grupo no rechaza la llamada: las solicitudes que caben se deciden y el resto vuelve en failed, indicando que la aprobación llevaría al grupo más allá de su límite de participantes. Rechazar funciona de la misma manera, a través de POST /v1/whatsapp/groups/{group_id}/join-requests/batch-reject. Una solicitud también sale de la lista cuando la persona la cancela, así que un ID que era válido hace un momento puede devolver un 422 E15051 para cuando lo uses.

El límite de 50 es propio de Bird para una sola solicitud, no de WhatsApp, así que un barrido de rechazos no está limitado por la capacidad del grupo.

Detectar solicitudes a medida que llegan

Suscríbete a whatsapp.group.join_request_created y whatsapp.group.join_request_revoked para saber cuándo alguien pide unirse y cuándo cancela, en lugar de consultar la lista periódicamente. Una solicitud creada y cancelada entre dos lecturas de la lista no deja rastro, así que estos eventos son la única forma de verla. Cada evento incluye el join_request.id que usan las operaciones por lotes, así que puedes decidir directamente a partir de él. Webhooks de grupo de WhatsApp muestra ambos payloads y todos los campos.

Rotar el enlace de invitación

Rotar emite un enlace nuevo e invalida todos los que el grupo tenía antes, de modo que quien aún conserve uno no pueda unirse. Rota cuando un enlace se haya difundido más de lo previsto, o después de eliminar a alguien que no quieres que vuelva. El nuevo enlace se devuelve en la propia llamada, que responde 200:

const link = await bird.whatsapp.groups.inviteLink.rotate("wag_01krdgeqcxet5s7t44vh8rt9mg");
console.log(link.invite_link); // every earlier link has stopped working

Rotar no es la forma de leer el enlace actual. El grupo lleva su invite_link, así que leer el grupo es la lectura.

La CLI no pide confirmación, así que sus comandos destructivos requieren --yes: rotar un enlace, eliminar a un participante, borrar un grupo, desanclar un mensaje y rechazar solicitudes de unión rechazan con confirmation_required si no lo incluyes.

Cómo se resuelve un cambio

WhatsApp confirma algunos cambios en su respuesta y otros mediante un webhook, y el código de estado indica de cuál se trata:

OperaciónRespondeDónde llega el resultado
Crear, actualizar, eliminar202El last_operation del grupo, cuando WhatsApp responde
Eliminar a un participante202El last_operation propio de ese participante en participants
Aprobar o rechazar solicitudes de unión202decided y failed en la propia respuesta
Rotar, anclar, desanclar200La respuesta, que es el cambio ya aplicado

En las dos primeras filas, el 202 indica que la solicitud fue aceptada, no aplicada. last_operation.status permanece en pending hasta que WhatsApp responde, normalmente en segundos, y luego se resuelve a success o failed; last_error.description indica el motivo en caso de fallo. Vuelve a leer el grupo para ver qué se aplicó.

Mientras una operación está en pending, otro cambio sobre lo mismo devuelve un 409 E15054. Los cambios a nivel de grupo comparten el last_operation del grupo, así que un renombrado pendiente bloquea un borrado. Cada participante lleva el suyo, así que eliminar a varias personas a la vez da a cada una su propio estado y su propio fallo, y solo la eliminación pendiente de esa persona bloquea otro intento sobre ella.

Dos 409 protegen las escrituras y status se comprueba primero, así que un grupo que no está en active devuelve E15047 sin importar lo que diga su last_operation. Esto importa para un grupo que aún se está creando, que está pendiente en ambos sentidos a la vez.

Toda escritura también acepta un encabezado Idempotency-Key. Idempotency explica cómo reintentar de forma segura.

Cambiar el asunto, la descripción o la imagen del grupo

Una actualización cambia lo que los participantes ven en la parte superior del grupo. Los campos que omitas se dejan como están; envía null para borrar la descripción o la imagen, ya que una cadena vacía es un 422 en lugar de una segunda forma de borrar.

const group = await bird.whatsapp.groups.update("wag_01krdgeqcxet5s7t44vh8rt9mg", {
  subject: "Norwood Fleet — Wednesday route",
});
console.log(group.last_operation?.status); // pending until WhatsApp reports back

WhatsApp aplica cada campo por separado, así que una actualización puede aplicarse parcialmente: un campo rechazado mientras los demás surten efecto. Cuando la operación se resuelve, last_operation.results contiene una entrada por cada campo que envió la actualización, que es como asocias un rechazo con la entrada que lo provocó.

profile_picture_url nombra un archivo en la biblioteca de medios de tu espacio de trabajo, no una dirección de internet, y WhatsApp acepta un JPEG cuadrado de al menos 192 por 192 píxeles y hasta 5 MB. Borrarlo elimina la imagen que Bird almacena, pero WhatsApp no tiene operación para retirar la foto de un grupo, así que los participantes siguen viendo la actual hasta que otra imagen la reemplace. El número administrador y join_approval_mode se fijan en el momento de la creación y no se pueden cambiar aquí.

Eliminar a un participante

La eliminación no se puede deshacer. WhatsApp impide que una persona eliminada se una al grupo mediante el enlace de invitación, y el bloqueo sigue a la persona, no al enlace, así que rotar el enlace no le permite volver. Sin operación de agregar que acompañe a esta, nada devuelve a alguien a este grupo una vez que sale; para contactarle de nuevo tienes que crear otro grupo e invitarle.

Nombra a la persona por cualquiera de los identificadores bajo los que la lista participants del grupo la registra: su bsuid, que todos tienen, o su phone_number en formato E.164, que solo aparece cuando WhatsApp lo comparte. En una URL, codifica el + inicial como %2B a menos que tu cliente lo haga por ti.

const group = await bird.whatsapp.groups.participants.remove(
  "wag_01krdgeqcxet5s7t44vh8rt9mg",
  "+15550002222",
);
console.log(group.participants?.length);

La eliminación de un participante queda en pending en su propia entrada hasta que WhatsApp la confirma, y nunca llega a success: la desaparición de la entrada de participants es lo que indica que funcionó. Un valor que nombra a alguien que no está en el grupo devuelve un 422 E15050.

Anclar un mensaje

Anclar fija uno de los mensajes del grupo en la parte superior de su chat, de modo que alguien que se una después no tenga que desplazarse para encontrar aquello a lo que la conversación vuelve una y otra vez. Un anclaje dura duration_days, de 1 a 30, y el valor predeterminado es 7.

const pin = await bird.whatsapp.groups.pins.create("wag_01krdgeqcxet5s7t44vh8rt9mg", {
  message_id: "wam_01kya19eknftrs2s6p82asmvnh",
  duration_days: 14,
});
console.log(pin.pinned_until);

El mensaje tiene que ser uno que pertenezca a este grupo: un mensaje de otro grupo, o un mensaje individual, devuelve un 422 E15053. Un grupo admite solo cierta cantidad de anclajes a la vez, y anclar más allá de ese límite desancla el más antiguo en lugar de fallar; anclar un mensaje ya anclado reemplaza su expiración. Lo que el grupo tiene anclado actualmente está en el propio grupo, como pinned_messages.

WhatsApp desancla un mensaje automáticamente cuando pasan sus días, así que desancla solo para retirarlo antes de tiempo. DELETE /v1/whatsapp/groups/{group_id}/pinned-messages/{message_id} responde 200, y repetirlo es seguro: un mensaje de este grupo que no esté anclado no cambia nada y sigue respondiendo 200.

Eliminar el grupo

Eliminar borra el grupo en WhatsApp. Todos los participantes pierden el acceso, incluido tu negocio, y el enlace de invitación deja de funcionar. Esto no se puede deshacer; retomar la conversación implica crear un grupo nuevo y enviar su enlace.

const group = await bird.whatsapp.groups.delete("wag_01krdgeqcxet5s7t44vh8rt9mg");
console.log(group.last_operation?.status); // pending until WhatsApp confirms it

El grupo sigue siendo legible después en status deleted, así que una referencia almacenada a él sigue resolviendo en lugar de convertirse en un 404. Un grupo failed también se puede eliminar, y ese no llega a ningún sistema externo: la creación nunca produjo un grupo en WhatsApp, así que limpiar la fila es contabilidad interna de Bird. Cualquier otro estado rechaza con un 409 E15047.

Listar tus grupos

La lista devuelve los grupos que creó tu espacio de trabajo, del más reciente al más antiguo, como una página con cursor. Filtra por el número administrador (number, como número E.164 o ID de wan_), por la cuenta WhatsApp Business Account bajo la que envía (waba), o por status, repitiendo el parámetro para coincidir con varios. q busca en el asunto y la descripción una subcadena, sin distinguir mayúsculas.

for await (const group of bird.whatsapp.groups.list({ status: ["active"] })) {
  console.log(group.id, group.subject, group.participant_count);
}

Un grupo eliminado permanece en la lista con status deleted, así que filtra por estado para ver solo los grupos a los que aún puedes enviar mensajes.

Resolución de problemas

  • 412 (E15045): El número no tiene el estado Official Business Account, así que WhatsApp no le permite crear un grupo. La decisión es de WhatsApp: solicita el estado en WhatsApp Manager en el perfil del número, o crea el grupo con un número que ya lo tenga.
  • 404 (E15046): El ID no corresponde a ningún grupo de este espacio de trabajo. Un grupo pertenece al espacio de trabajo que lo creó, así que un ID de otro espacio de trabajo no se encuentra aquí.
  • 409 (E15047): El grupo está pendiente, suspendido, eliminado o fallido. Solo un grupo activo acepta cambios. Lee el grupo para ver en qué estado se encuentra.
  • 409 (E15049): El número ya administra los 10.000 grupos que WhatsApp permite. Elimina grupos cuya conversación haya terminado, o crea este con otro número.
  • 409 (E15054): Un cambio sobre el mismo grupo o el mismo participante aún está pendiente. Lee last_operation y espera a que se resuelva.
  • 422 (E15050): La ruta no corresponde a nadie en el grupo. Lee la lista participants del grupo y usa un bsuid o phone_number tal como aparecen.
  • 422 (E15051): Uno de los ID de solicitud de unión ya no está esperando una decisión. Vuelve a listar las solicitudes y usa los ID que se devuelvan.
  • 422 (E15053): El mensaje pertenece a otro grupo o a una conversación individual. El to.group_id del mensaje indica qué grupo puede anclarlo.
  • Un grupo pending que nunca se activa: Bird deja de esperar en lugar de mantenerlo pendiente, y mueve el grupo a failed con el motivo en last_operation.last_error. Crea uno nuevo en lugar de reintentar.

Referencia

Las estructuras completas de solicitud y respuesta están en la referencia de API: crear, listar, obtener, actualizar, eliminar, rotar el enlace de invitación, eliminar a un participante, listar, aprobar y rechazar solicitudes de unión, y anclar y desanclar un mensaje.

Próximos pasos