Groupes
Un groupe est une conversation à plus de deux personnes. Il se liste, se crée et se modifie ici, et on y écrit avec le point de terminaison d'envoi ordinaire.
Lister les groupes
C'est la liste des conversations filtrée sur les groupes : la règle de la page courte s'y applique donc. Le filtre s'exécute après le retour de la page, si bien qu'une page peut être courte ou vide alors que cursor n'est pas encore nul. Continuez de paginer jusqu'à ce que le curseur vaille null. Un Group est un Chat avec kind: "group" plus un champ, pictureUrl.
La lecture d'un groupe seul porte members. Demander une conversation en tête-à-tête sur une route de groupes donne 409 CONFLICT (« cette conversation n'est pas un groupe »), pas un 404 : la conversation existe, elle n'est simplement pas un groupe.
Créer un groupe
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." }'{
"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 }
]
}
}Chaque membre est vérifié avant la création du groupe. WhatsApp ne refuse pas un membre injoignable, il l'écarte en silence : le groupe reviendrait donc avec une personne en moins et sans explication. Sendveo vérifie chacun d'abord et refuse la création entière avec 400 VALIDATION_FAILED, details[0].path = "members.N", en nommant le numéro. Rien n'est créé. Le même contrôle s'exécute à l'ajout d'un membre, avec le chemin phone.
Un groupe se crée en y démarrant une conversation : text devient donc son premier message. Omettez-le et le groupe est créé sans que rien n'ait été dit. Au plus 50 membres par appel, canonisés et dédupliqués ; un membre mal formé donne 400 en nommant son index.
Membres
Un membre porte un role : member, admin ou super_admin. Il vaut member tant que WhatsApp ne divulgue pas de marqueur d'administrateur, et la forme de participant qu'il publie n'en porte aucun : tenez donc un rôle autre que member pour fiable, et member pour « on ne nous a pas dit le contraire ». N'y adossez pas un contrôle de permission : WhatsApp refuse de toute façon une action que le numéro n'a pas le droit d'effectuer, et un contrôle fondé sur le rôle cacherait l'action à des gens qui en ont le droit.
leftAt est renseigné plutôt que la ligne supprimée. Un message de quelqu'un qui a quitté le groupe la semaine dernière doit toujours pouvoir être rattaché à un nom.
Retirer VOTRE propre numéro est refusé avec 409 CONFLICT : « pour retirer votre propre numéro d'un groupe, quittez plutôt le groupe ». Sans cela, un script qui parcourt une liste de membres quitterait le groupe par accident.
Quitter un groupe
Le départ utilise le numéro vérifié au moment de la connexion, jamais un numéro venu de la requête. Un canal dont le numéro n'a jamais été relu ne peut pas quitter, et répond 409 CONFLICT.
{ "left": true, "chatId": "cht_m8k3x7q2a1b4" }Envoyer dans un groupe
Envoyer dans un groupe, c'est POST /v1/messages avec le chatId du groupe. C'est un identifiant de conversation ordinaire : ni nouveau point de terminaison, ni nouvelle portée, messages:send comme toujours. Réactions, transferts, réponses, pièces jointes et les actions « lu » et « en train d'écrire » fonctionnent dans un groupe exactement comme dans une conversation en tête-à-tête.
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." }'Messages de groupe
Deux champs s'ajoutent à chaque Message, ainsi qu'au webhook message.received. Tous deux sont purement additifs et valent null sur un message en tête-à-tête, ce que continue de voir un gestionnaire écrit avant les groupes.
{
"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 identifie la conversation : group.id est l'identifiant de conversation Sendveo lorsque Sendveo détient la ligne, et null sinon, tandis que group.chatId et group.name ont toujours un sens. author est QUI a parlé dans le groupe. Il vaut null sur un message en tête-à-tête, parce que là l'expéditeur EST la conversation et que from le dit déjà, et null sur un message de groupe sortant, dit par le numéro connecté. from garde son sens de la V1 et porte l'auteur sur un message de groupe entrant, si bien qu'un gestionnaire qui ne connaît que from lit toujours un expéditeur.
Photos de groupe
Le pictureUrl d'un groupe est toujours présent, et un groupe sans photo y répond 404. Cela coûte une requête plutôt qu'un appel amont supplémentaire pour chaque groupe d'une liste. C'est le même proxy que pour la photo de contact, avec les mêmes règles : type de contenu choisi, rien de stocké, plafond de 2 Mo.
Événements de groupe
Trois événements sont relayés vers votre webhook. Ils portent sur une conversation, donc ils portent chat là où les événements de message portent message, plus by. Être retiré et partir forment un seul événement, que member.removed permet de distinguer ; la création d'un groupe et son renommage sont un seul événement eux aussi.
| Événement | Déclenché quand | Champs supplémentaires |
|---|---|---|
| group.member_joined | Quelqu'un a été ajouté à un groupe. | member, by |
| group.member_left | Quelqu'un est parti, ou a été retiré. | member.removed, by |
| group.updated | Un groupe a été créé, ou son sujet a changé. | subject, by |
Portées
Lire les groupes et les modifier sont deux autorités distinctes. *:read accorde groups:read comme toute autre portée de lecture. Une clé émise avant l'existence de ces portées ne les porte pas et répond 403 ; émettez une nouvelle clé.
| Portée | Accorde |
|---|---|
| groups:read | Lister et lire les groupes, et les photos de groupe. |
| groups:manage | Créer un groupe, ajouter et retirer des membres, quitter. |