Déposer les membres d'une classe. La route s'appelle avec une clé d'intégration : voir Conventions.
PUT /api/institutions/:institutionId/classes/by-ref/:ref/roster
Rattache une liste de personnes à une classe, en créant les comptes qui manquent. Exige roster.write — la portée roster:write.
| Paramètre de chemin | Type | Description |
|---|---|---|
institutionId | uuid | L'établissement de la clé, rendu par GET /api/me |
ref | string | Votre ref de la classe, encodée pour une URL. La classe doit exister : créée par un dépôt d'emploi du temps avec ce group.ref, ou dans MeetingHub avec cette référence |
| Paramètre de requête | Type | Défaut | Description |
|---|---|---|---|
dryRun | string | absent | Absent : ESSAI À BLANC, rien n'est écrit. false ou 0 : la liste est appliquée. Toute autre valeur : essai à blanc |
L'essai à blanc est le comportement par défaut, à l'inverse du dépôt d'emploi du temps : appliquer une liste crée des comptes.
Corps de la requête
{
"members": [
{ "email": "awa@ecole.fr", "displayName": "Awa Diallo" },
{ "phone": "6 99 12 34 56", "displayName": "Ben Traoré" }
]
}
| Champ | Type | Obligatoire | Règles |
|---|---|---|---|
members | object[] | oui | De 1 à 5 000 entrées |
Chaque entrée de members :
| Champ | Type | Obligatoire | Règles |
|---|---|---|---|
email | string | l'un des deux | Espaces de bord retirés, mis en minuscules. Doit avoir la forme nom@domaine.ext, 254 caractères au plus |
phone | string | l'un des deux | Un numéro de téléphone. Espaces, points, tirets, parenthèses et barres obliques sont ignorés. Rendu au format international : +237699123456. Sans indicatif — ni +, ni 00 —, il est supposé camerounais, et doit alors avoir neuf chiffres |
displayName | string | oui | Le nom qui figurera sur les feuilles de présence. Espaces de bord retirés, tronqué à 120 caractères, ne peut pas être vide |
Une entrée peut porter le courriel et le téléphone. C'est le courriel, quand il y en a un, qui identifie la personne dans la liste ; le téléphone sinon.
Traitement
Chaque entrée est vérifiée dans l'ordre du tableau : courriel, téléphone, présence de l'un des deux, doublon, puis nom. La première règle qui échoue la fait refuser ; les autres entrées continuent.
Pour chaque personne retenue, un compte est cherché par son courriel, puis par son téléphone :
- Un compte existe et appartient déjà à l'établissement : il est ajouté à la classe s'il n'en était pas membre. Son nom n'est pas modifié.
- Un compte existe hors de l'établissement : il n'y entre pas d'office. Il est invité — un courriel lui est envoyé s'il en a un — et rejoint l'établissement, avec le rôle
learner, puis la classe, en acceptant depuis « Mon espace ». Il figure dansawaitingAcceptance, et n'est compté ni dansaddedToOrgni dansaddedToGroup. - Aucun compte n'existe : un compte est créé avec ce courriel, ce téléphone et ce nom, et un mot de passe que personne ne connaît. Il est rattaché à l'établissement avec le rôle
learner, ajouté à la classe, et un lien d'activation est émis. C'est ce lien qui permet à la personne de choisir son mot de passe.
La route ne retire jamais personne : une personne absente de la liste reste dans la classe.
Réponse
201 si la liste est appliquée, 200 si c'est un essai à blanc — dans les deux cas même si des entrées sont refusées.
{
"dryRun": false,
"read": 2,
"accountsCreated": 1,
"accountsFound": 1,
"addedToOrg": 1,
"addedToGroup": 1,
"alreadyInGroup": 0,
"joinedFromOutside": [],
"awaitingAcceptance": ["+237699123456"],
"rejected": [],
"invitations": [
{
"email": "awa@ecole.fr",
"phone": null,
"displayName": "Awa Diallo",
"link": "https://reunion.votre-etablissement.fr/app/?setup=…",
"delivered": false
}
]
}
| Champ | Type | Description |
|---|---|---|
dryRun | boolean | true pour un essai à blanc |
read | integer | Le nombre d'entrées reçues |
accountsCreated | integer | Comptes créés, ou qui le seraient en essai à blanc |
accountsFound | integer | Personnes retenues qui avaient déjà un compte |
addedToOrg | integer | Personnes rattachées à l'établissement, nouveaux comptes compris |
addedToGroup | integer | Personnes ajoutées à la classe |
alreadyInGroup | integer | Personnes qui en étaient déjà membres |
awaitingAcceptance | string[] | Les comptes inscrits hors de l'établissement : invités, ils n'entrent qu'en acceptant. Désignés par le courriel, à défaut le téléphone, que la liste donnait |
joinedFromOutside | string[] | Obsolète, toujours vide : un compte d'ailleurs n'entre plus d'office. Voir awaitingAcceptance |
rejected | Rejet[] | Les entrées refusées, dans l'ordre du tableau |
invitations | Invitation[] | Une par compte créé ; toujours vide en essai à blanc |
Un rejet :
| Champ | Type | Description |
|---|---|---|
line | integer | La position de l'entrée dans members, en comptant à partir de 1 |
value | string | La valeur lue : le courriel ou le téléphone fautif, ou, pour un doublon ou un nom absent, l'identifiant normalisé ; vide s'il manquait |
reason | string | La cause, ci-dessous |
reason | Cause |
|---|---|
adresse-invalide | email fourni, mais sans la forme nom@domaine.ext |
telephone-invalide | phone fourni, mais qui n'est pas un numéro lisible |
identifiant-absent | Ni email ni phone |
doublon-dans-le-fichier | Ce courriel — à la casse près — ou ce téléphone figure déjà plus haut dans la liste |
nom-absent | displayName absent ou vide |
Une invitation :
| Champ | Type | Description |
|---|---|---|
email | string ou null | Le courriel du compte créé |
phone | string ou null | Son téléphone, au format international |
displayName | string | Son nom |
link | string ou null | Le lien d'activation, quand il n'a pas pu être envoyé par courriel ; null s'il a été envoyé |
delivered | boolean | true si le lien est parti par courriel |
Les liens d'activation
Aujourd'hui, MeetingHub n'envoie aucun courriel depuis ce dépôt : delivered vaut toujours false, et chaque lien est rendu dans link. Une personne inscrite par son seul téléphone n'en recevrait de toute façon pas. C'est à vous de remettre le lien à la personne, par votre propre messagerie, un SMS ou WhatsApp.
Un lien vaut un mot de passe : il ouvre le compte à qui le possède. Transmettez-le à la seule personne concernée, et ne le conservez pas dans vos journaux. Il est valable 7 jours — durée par défaut, que l'exploitant de l'instance peut changer — et ne sert qu'une fois : dès que la personne a choisi son mot de passe, il ne fonctionne plus.
Un lien perdu n'est pas réémis par un nouveau dépôt : le compte existe déjà, et la personne est alors comptée dans accountsFound. Un administrateur de l'établissement en émet un nouveau avec sa session, par POST /api/institutions/:institutionId/members/:accountId/activation-link, pour un compte qui n'appartient qu'à cet établissement.
Erreurs de la requête entière
| Code | Corps | Cause |
|---|---|---|
400 | attendu : { "members": [...] } | Le corps n'a pas de tableau members |
400 | liste vide | members est vide |
400 | N inscrits — le maximum est 5000 par dépôt | Plus de 5 000 entrées |
403 | cet accès ne permet pas cela — il faut : roster.write | Portée absente |
403 | le dépôt d’une liste vaut pour tout l’établissement | Avec une session : un directeur de centre, dont l'accès se limite à ses centres |
404 | classe « … » inconnue | Aucune classe ne porte cette ref dans l'établissement |
404 | établissement inconnu | :institutionId n'est pas l'établissement de la clé |
429 | trop de personnes cherchées aujourd’hui pour cet établissement… | Code org.daily-quota. Le budget quotidien de personnes cherchées — invitations et dépôts, essais à blanc compris — est épuisé : 300 pour un établissement à l'essai, 10 000 sinon. Il se renouvelle à minuit UTC |
503 | dépôt indisponible pour le moment | L'instance tourne sans base de données |
La classe est cherchée avant que le corps soit lu : une ref inconnue rend 404 même si le corps est fautif.
Une liste appliquée émet l'événement roster.imported : voir Webhooks.
L'ancienne adresse
PUT /api/integration/groups/:ref/roster répond encore avec une clé d'établissement, comme alias déprécié de cette route : chaque réponse porte Deprecation: true et un en-tête Link vers la route de /api.