Grupos

Un grupo es una conversación con más de dos personas dentro. Aquí se lista, se crea y se modifica, y se le escribe con el endpoint de envío de siempre.

Listar grupos

GET/v1/groups?channelId=chn_sales01
GET/v1/groups/:chatId

Esta es la lista de conversaciones filtrada a grupos, así que le aplica la regla de la página corta: el filtro se ejecuta después de que vuelva la página, así que una página puede ser corta o vacía mientras cursor sigue sin ser nulo. Sigue paginando hasta que el cursor sea null. Un Group es un Chat con kind: "group" más un campo, pictureUrl.

La lectura de un grupo concreto lleva members. Pedir una conversación uno a uno en una ruta de grupos es 409 CONFLICT ("esa conversación no es un grupo"), no un 404: la conversación existe, solo que no es un grupo.

Crear un grupo

POST/v1/groups
cURL
curl -X POST https://api.sendveo.com/v1/groups \
  -H "X-API-KEY: sv_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "subject": "Deliveries north",
        "members": ["+212670111222", "+212671333444"],
        "text": "Welcome to the deliveries group." }'
201 Created
{
  "group": {
    "id": "cht_m8k3x7q2a1b4",
    "chatId": "120363001122334455@g.us",
    "channelId": "chn_sales01",
    "kind": "group",
    "name": "Deliveries north",
    "pictureUrl": "https://api.sendveo.com/v1/groups/120363001122334455%40g.us/picture",
    "members": [
      { "id": "cmb_1", "phone": "+212661234567", "name": null, "role": "super_admin", "self": true },
      { "id": "cmb_2", "phone": "+212670111222", "name": "Khadija Alaoui", "role": "member", "self": false }
    ]
  }
}

Cada miembro se comprueba antes de crear el grupo. WhatsApp no rechaza a un miembro inalcanzable, lo deja fuera en silencio: así que el grupo volvería con una persona de menos y sin explicación. Sendveo consulta a cada uno primero y rechaza la creación entera con 400 VALIDATION_FAILED, details[0].path = "members.N", nombrando el número. No se crea nada. La misma comprobación se ejecuta al añadir un miembro, con la ruta phone.

Un grupo se crea iniciando una conversación en él, así que text pasa a ser su primer mensaje. Omítelo y el grupo se crea sin que se diga nada. Como mucho 50 miembros por llamada, canonizados y sin duplicados; uno mal formado es 400 nombrando su índice.

Miembros

POST/v1/groups/:chatId/members
DELETE/v1/groups/:chatId/members/:phone

Un miembro lleva role: member, admin o super_admin. Es member salvo que WhatsApp revele una marca de administrador, y la forma de participante que publica no lleva ninguna: así que trata un rol distinto de member como fiable y member como "no nos han dicho lo contrario". No montes sobre él una comprobación de permisos: WhatsApp rechaza igualmente una acción que el número no puede realizar, y una comprobación basada en el rol escondería la acción a quien sí puede hacerla.

Se rellena leftAt en lugar de borrar la fila. Un mensaje de alguien que salió del grupo la semana pasada sigue teniendo que resolverse a un nombre.

Eliminar TU propio número se rechaza con 409 CONFLICT: "para quitar tu propio número de un grupo, sal del grupo". Si no, un script que recorre la lista de miembros saldría del grupo por accidente.

Salir

POST/v1/groups/:chatId/leave

Salir usa el número verificado en el momento de la conexión, nunca uno que venga en la petición. Un canal cuyo número nunca se releyó no puede salir, y responde 409 CONFLICT.

200 OK
{ "left": true, "chatId": "cht_m8k3x7q2a1b4" }

Enviar a un grupo

POST/v1/messages

Enviar a un grupo es POST /v1/messages con el chatId del grupo. Es un id de conversación corriente y no necesita endpoint nuevo ni ámbito nuevo: messages:send, como siempre. Reacciones, reenvíos, respuestas, adjuntos y las acciones de leído y escribiendo funcionan en un grupo exactamente igual que en una conversación uno a uno.

cURL
curl -X POST https://api.sendveo.com/v1/messages \
  -H "X-API-KEY: sv_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "channelId": "chn_sales01",
        "chatId": "120363001122334455@g.us",
        "text": "The gate code is unchanged." }'

Mensajes de grupo

Se añaden dos campos a cada Message, y al webhook message.received. Ambos son aditivos y ambos son null en un mensaje uno a uno, que es lo que sigue viendo un manejador escrito antes de que existieran los grupos.

200 OK
{
  "id": "msg_8Rm5",
  "channelId": "chn_sales01",
  "chatId": "120363001122334455@g.us",
  "direction": "INBOUND",
  "from": "+212671333444",
  "senderName": "Omar Idrissi",
  "text": "The Rabat round leaves at 8am tomorrow.",
  "type": "text",
  "status": "RECEIVED",
  "group":  { "chatId": "120363001122334455@g.us", "id": "cht_m8k3x7q2a1b4", "name": "Atlas team - deliveries" },
  "author": { "phone": "+212671333444", "name": "Omar Idrissi" }
}

group identifica la conversación: group.id es el id de conversación de Sendveo cuando Sendveo conserva la fila, y null si no, mientras que group.chatId y group.name siempre tienen sentido. author es QUIÉN lo dijo dentro del grupo. Es null en un mensaje uno a uno, porque ahí el remitente ES la conversación y from ya lo dice, y null en un mensaje de grupo saliente, que lo dijo el número conectado. from mantiene su significado de la V1 y lleva al autor en un mensaje de grupo entrante, así que un manejador que solo conoce from sigue leyendo un remitente.

Fotos de grupo

GET/v1/groups/:chatId/picture

El pictureUrl de un grupo siempre está, y un grupo sin foto responde ahí 404. Eso es una petición en vez de una llamada extra aguas arriba por cada grupo de una lista. Es el mismo proxy que usa la foto de contacto, con las mismas reglas: tipo de contenido elegido, nada guardado, tope de 2 MB.

Eventos de grupo

Tres eventos se retransmiten a tu webhook. Tratan de una conversación, así que llevan chat donde los eventos de mensaje llevan message, más by. Que te eliminen y salir son un solo evento, y member.removed los distingue; crear un grupo y renombrarlo también son un solo evento.

EventoSe dispara cuandoCampos adicionales
group.member_joinedAlguien fue añadido a un grupo.member, by
group.member_leftAlguien salió, o fue eliminado.member.removed, by
group.updatedSe creó un grupo, o cambió su asunto.subject, by

Ámbitos

Leer los grupos y modificarlos son autoridades separadas. *:read concede groups:read como cualquier otro ámbito de lectura. Una clave emitida antes de que existieran estos ámbitos no los lleva y responde 403; emite una clave nueva.

ÁmbitoConcede
groups:readListar y leer grupos, y las fotos de grupo.
groups:manageCrear un grupo, añadir y eliminar miembros, salir.
API de grupos de WhatsApp · Docs de Sendveo