Ce qui vaut pour toutes les routes de l'API : l'adresse, l'authentification, les types de données, la pagination, la taille des corps et les limites de débit. Chaque page de la référence s'appuie sur ces définitions.
Toutes les routes
Une seule API, /api, pour l'application, le logiciel d'un établissement et celui d'un éditeur partenaire. Cette table est générée depuis les déclarations qui gardent les routes : elle ne peut pas diverger de l'API.
La colonne « Exige » dit ce que l'appelant doit pouvoir faire. Une capacité d'établissement (schedule.read, institution.manage…) se mesure dans l'établissement désigné par l'adresse ; « ou » sépare des capacités dont une seule suffit.
| Méthode | Chemin | Exige | Rôle |
|---|---|---|---|
GET | /api/me | aucune | Qui appelle, et où il peut agir. |
GET | /api/institutions/:institutionId | institution.view | L’établissement, son statut, et ce que l’appelant peut y faire. |
GET | /api/institutions | un appelant identifié | Les établissements que l’appelant atteint : les siens, celui de sa clé, ceux qu’il a ouverts. |
POST | /api/institutions | une clé d’éditeur | Ouvre un établissement pour un client ; à l’essai (sandbox), il n’expire pas. |
GET | /api/partner/webhooks | une clé d’éditeur | Les alertes de l’éditeur : posées une fois, valables dans tous ses établissements. |
POST | /api/partner/webhooks | une clé d’éditeur | Pose une alerte ; son secret n’est montré qu’une fois. |
PATCH | /api/partner/webhooks/:webhookId | une clé d’éditeur | Modifie une alerte. |
DELETE | /api/partner/webhooks/:webhookId | une clé d’éditeur | Retire une alerte, dans tous les établissements. |
GET | /api/partner/usage | une clé d’éditeur | Ce que chaque établissement a consommé sur un mois (?month=AAAA-MM). |
GET | /api/institutions/:institutionId/room-kinds | institution.view | Les types de salle et leurs règles, pour composer un formulaire. |
GET | /api/institutions/:institutionId/lessons | schedule.read | L’emploi du temps sur une fenêtre (from, to), éventuellement pour une classe (groupId). |
POST | /api/institutions/:institutionId/lessons | schedule.write | Pose un cours dans une salle, pour une classe et son auditoire. |
POST | /api/institutions/:institutionId/lessons/series | schedule.write | Pose un cours chaque semaine jusqu’à une date, avec sa classe et son enseignant. |
PUT | /api/institutions/:institutionId/lessons | schedule.write | Dépose un emploi du temps, cours par cours, chacun sous sa référence : rejouable, il n’efface rien. |
GET | /api/institutions/:institutionId/lessons/conflicts | schedule.read | Les chevauchements : une salle réservée deux fois, une classe attendue à deux endroits. |
DELETE | /api/institutions/:institutionId/lessons/by-ref/:ref | schedule.write | Annule un cours déposé, par la référence qu’il porte chez vous. |
GET | /api/institutions/:institutionId/lessons/:lessonId | schedule.read | Un cours. |
DELETE | /api/institutions/:institutionId/lessons/:lessonId | schedule.write | Annule un cours. |
PUT | /api/institutions/:institutionId/lessons/:lessonId/audiences | schedule.write | Diffuse un cours à des classes d’autres centres. |
PUT | /api/institutions/:institutionId/lessons/:lessonId/teacher | schedule.write | Désigne l’enseignant du cours, ou son remplaçant pour ce cours ; nul le retire. |
GET | /api/institutions/:institutionId/lessons/:lessonId/attendance | attendance.read | La feuille de présence d’un cours clos, ligne par ligne. |
GET | /api/institutions/:institutionId/lessons/:lessonId/attendance.csv | attendance.read | La feuille en CSV, sous le nom de fichier que l’établissement archivera. |
GET | /api/institutions/:institutionId/lessons/:lessonId/attendance.html | attendance.read | La feuille à imprimer. |
POST | /api/institutions/:institutionId/lessons/:lessonId/attendance/close | schedule.write | Arrête la feuille sans attendre le balayage ; déjà close, elle est rendue telle quelle. |
GET | /api/institutions/:institutionId/centres | institution.view | Les centres — pour un directeur de centre, les siens. |
POST | /api/institutions/:institutionId/centres | institution.manage ou partner.manage | Déclare un centre. |
PATCH | /api/institutions/:institutionId/centres/:centreId | institution.manage | Renomme un centre, ou change sa référence et sa ville. |
DELETE | /api/institutions/:institutionId/centres/:centreId | institution.manage | Retire un centre. |
GET | /api/institutions/:institutionId/centres/:centreId/directors | institution.manage | Les directeurs d’un centre. |
POST | /api/institutions/:institutionId/centres/:centreId/directors | institution.manage | Nomme directeur de ce centre un membre, par son adresse. |
PUT | /api/institutions/:institutionId/centres/:centreId/directors/:accountId | institution.manage | Nomme directeur de ce centre un membre, par son identifiant. |
DELETE | /api/institutions/:institutionId/centres/:centreId/directors/:accountId | institution.manage | Retire sa direction à un directeur de centre. |
GET | /api/institutions/:institutionId/keys | institution.manage ou partner.manage | Les accès logiciels de l’établissement, et les portées qu’on peut leur donner. |
POST | /api/institutions/:institutionId/keys | institution.manage ou partner.manage | Crée un accès ; la clé n’est montrée qu’une fois. |
DELETE | /api/institutions/:institutionId/keys/:keyId | institution.manage ou partner.manage | Révoque un accès : il cesse aussitôt de fonctionner. |
GET | /api/institutions/:institutionId/keys/:keyId/activity | institution.manage | Ce qu’un accès a fait : le journal, interrogé par acteur. |
GET | /api/institutions/:institutionId/overview | institution.manage | Ses personnes, ses salles, et celles qui sont ouvertes en ce moment. |
GET | /api/institutions/:institutionId/capacity | institution.manage | Les places réservées par les cours d’une période, au regard des quotas (from, to). |
GET | /api/institutions/:institutionId/room-policies | institution.manage | Les quotas par type de salle : ce que l’accord a fixé, et ce qui vient du catalogue. |
PUT | /api/institutions/:institutionId/room-policies/:kind | l’exploitant | Règle le quota d’un type de salle — l’exploitant seul, selon l’accord. |
DELETE | /api/institutions/:institutionId/room-policies/:kind | l’exploitant | Rend un type de salle au catalogue : retire l’écart, sans poser de plafond « illimité ». |
GET | /api/institutions/:institutionId/journal | institution.manage | Le journal de l’établissement : qui a fait quoi, passages de l’assistance compris. |
GET | /api/institutions/:institutionId/rooms | institution.manage ou studies.manage ou studies.centres | Les salles de l’établissement, par page, avec leur titulaire — pour un directeur de centre, celles de ses centres. |
PATCH | /api/institutions/:institutionId/rooms/:code | institution.manage | Verrouille ou déverrouille une salle (locked). |
DELETE | /api/institutions/:institutionId/rooms/:code | institution.manage | Supprime une salle. |
GET | /api/institutions/:institutionId/retention | institution.manage | Combien de jours garder les présences et les feuilles ; nul : tout garder. |
PUT | /api/institutions/:institutionId/retention | institution.manage | Fixe ces durées. |
GET | /api/institutions/:institutionId/classes | studies.manage ou studies.centres | Les classes, par page (search, archived). |
POST | /api/institutions/:institutionId/classes | studies.manage ou studies.centres | Crée une classe — un directeur de centre, dans l’un de ses centres. |
GET | /api/institutions/:institutionId/classes/:classId | studies.manage ou studies.centres | Une classe, et sa salle attitrée. |
PUT | /api/institutions/:institutionId/classes/:classId/room | studies.manage ou studies.centres | La salle attitrée de la classe : ses cours la prennent par défaut, ses apprenants y entrent sans invitation. room: null la retire. |
PATCH | /api/institutions/:institutionId/classes/:classId | studies.manage ou studies.centres | Renomme une classe, change son centre, l’archive. |
DELETE | /api/institutions/:institutionId/classes/:classId | studies.manage ou studies.centres | Supprime une classe. |
GET | /api/institutions/:institutionId/classes/:classId/members | studies.manage ou studies.centres | Les inscrits d’une classe, par page. |
POST | /api/institutions/:institutionId/classes/:classId/members | studies.manage ou studies.centres | Inscrit des personnes de l’établissement, par leur courriel ; les inconnues sont rendues. |
DELETE | /api/institutions/:institutionId/classes/:classId/members/:accountId | studies.manage ou studies.centres | Retire une personne d’une classe. |
POST | /api/institutions/:institutionId/classes/:classId/import | studies.manage ou studies.centres | Importe une liste (CSV : courriel ou téléphone, nom). À blanc par défaut ; dryRun=0 applique. |
GET | /api/institutions/:institutionId/dashboard | studies.manage ou studies.centres | Le tableau de bord : assiduité, heures, décrochage, confort et données, par centre et par classe (from, to). |
GET | /api/institutions/:institutionId/webhooks | institution.manage | Les alertes de l’établissement, et les événements qu’on peut suivre. |
POST | /api/institutions/:institutionId/webhooks | institution.manage | Pose une alerte ; son secret de signature n’est montré qu’une fois. |
PATCH | /api/institutions/:institutionId/webhooks/:webhookId | institution.manage | Modifie une alerte : adresse, événements, nom, ou la suspend (enabled). |
DELETE | /api/institutions/:institutionId/webhooks/:webhookId | institution.manage | Retire une alerte. |
GET | /api/institutions/:institutionId/webhooks/:webhookId/deliveries | institution.manage | Ce qui est parti, et son sort (limit, 50 par défaut, 200 au plus). |
POST | /api/institutions/:institutionId/entries | partner.manage | Un lien d’entrée dans une salle, à ouvrir dans une iframe sur une origine enregistrée. |
PUT | /api/institutions/:institutionId/classes/by-ref/:ref/roster | roster.write | Dépose la liste des inscrits d’une classe. À blanc par défaut : écrire ?dryRun=false. |
GET | /api/institutions/:institutionId/members | institution.manage | Les membres, par page, avec leur rôle. |
GET | /api/institutions/:institutionId/teachers | institution.manage ou studies.manage ou studies.centres | Les enseignants de l’établissement : ceux qu’on désigne pour un cours. |
POST | /api/institutions/:institutionId/members | institution.manage ou studies.manage ou studies.centres | Invite une personne par son courriel ou son téléphone ; rend son lien d’activation s’il faut en créer le compte. |
PATCH | /api/institutions/:institutionId/members/:accountId | institution.manage | Change le rôle d’un membre. Le Promoteur, lui, transmet son titre. |
DELETE | /api/institutions/:institutionId/members/:accountId | institution.manage | Retire une personne de l’établissement ; son compte demeure. |
POST | /api/institutions/:institutionId/members/:accountId/activation-link | institution.manage | Un nouveau lien d’activation, à partager : il ne vaut qu’une fois. |
POST | /api/institutions/:institutionId/members/:accountId/promoter | institution.transfer | Le Promoteur transmet son titre ; il devient Administrateur. |
PATCH | /api/me | un appelant identifié | Son nom, et l’accord de son rôle (masculine, feminine). |
GET | /api/me/tickets | un appelant identifié | Mes demandes d’assistance, avec le lien de suivi de chacune. |
POST | /api/me/tickets | un appelant identifié | Ouvre une demande d’assistance sous son compte. share=true la partage avec l’établissement actif. |
GET | /api/me/classes | un appelant identifié | Mes classes, dans tous mes établissements, et la salle attitrée de chacune. |
GET | /api/me/lessons | un appelant identifié | Mes prochains cours : ceux que j’enseigne, dans tous mes établissements (from, to). |
PUT | /api/me/password | un appelant identifié | Change son mot de passe ; l’actuel est demandé. |
PUT | /api/me/identifiers | un appelant identifié | Change son courriel ou son téléphone ; le mot de passe est demandé. |
POST | /api/me/email/proof | un appelant identifié | Renvoie le lien qui confirme son courriel. Il ne part qu’à l’adresse, et n’est jamais rendu ici. |
POST | /api/email/confirm | aucune | Consomme le lien reçu par courriel : l’adresse est désormais prouvée. 410 si le lien ne vaut plus. |
GET | /api/me/invitations | un appelant identifié | Les établissements qui m’invitent, et que je n’ai pas encore rejoints. |
POST | /api/me/invitations/:orgId | un appelant identifié | Accepte l’invitation de cet établissement : j’y entre, avec le rôle et les classes prévus. |
DELETE | /api/me/invitations/:orgId | un appelant identifié | Décline l’invitation de cet établissement. |
GET | /api/institutions/:institutionId/onboarding | institution.manage | Où en est l’accueil guidé : centres, enseignants, salles, cours planifiés. |
GET | /api/institutions/:institutionId/export/attendance.csv | institution.export | Toutes les feuilles de présence en un fichier — possible même en pause. |
POST | /api/institutions/:institutionId/closure | institution.close | Demande la fermeture : l’accès passe en pause, les données sont effacées dans trente jours. |
DELETE | /api/institutions/:institutionId/closure | institution.close | Annule une fermeture demandée ; l’accès reste en pause jusqu’à sa réouverture. |
GET | /api/institutions/:institutionId/support-tickets | institution.manage | Les demandes d’assistance partagées avec l’établissement (search, limit, offset). |
GET | /api/institutions/:institutionId/support-tickets/:ticketId | institution.manage | Une demande partagée et son fil, en lecture. |
GET | /api/rooms/:code/team | un appelant identifié | Le titulaire de la salle et ses co-animateurs. |
PUT | /api/rooms/:code/team/:accountId | un appelant identifié | Fait d’une personne de l’établissement un co-animateur de la salle. |
POST | /api/rooms/:code/team | un appelant identifié | Fait d’une personne de l’établissement un co-animateur, par son courriel ou son téléphone. |
DELETE | /api/rooms/:code/team/:accountId | un appelant identifié | Retire un co-animateur ; le titulaire, lui, transmet d’abord la salle. |
POST | /api/rooms/:code/owner | un appelant identifié | Transmet la salle à une personne de l’établissement (identifiant, courriel ou téléphone) ; l’ancien titulaire reste co-animateur. |
Les anciennes adresses /api/integration/… et /api/partner/… répondent encore, comme alias dépréciés de ces routes : chaque réponse porte l'en-tête Deprecation: true et un en-tête Link vers la route qui la remplace, par exemple Link: </api/institutions/…/lessons>; rel="successor-version". Elles n'acceptent que leur propre sorte de clé — mhk_… pour la première, mhp_… pour la seconde — et disparaîtront à la prochaine version.
Adresse de base
Toutes les routes sont relatives au domaine de votre instance, par exemple https://reunion.votre-etablissement.fr. En production, l'API n'est servie qu'en HTTPS.
Version
La version de l'API se dit dans un en-tête, pas dans l'adresse : une ressource garde la même adresse d'une version à l'autre, et c'est votre programme qui dit quel contrat il attend.
Api-Version: 1
- Absent, l'en-tête vaut la version courante,
1. Un lien ouvert dans un navigateur — une feuille de présence, un export — n'en porte pas, et fonctionne. - Envoyez-le quand même depuis vos programmes : le jour où une version 2 sortira, un programme qui demande
1continuera de recevoir le contrat qu'il connaît. - Une version que l'instance ne sert pas est refusée, plutôt que servie à la place d'une autre sans le dire :
| Code | Corps | code |
|---|---|---|
400 | version d’API inconnue : « 2 » — versions servies : 1 | api.version |
Le corps du refus porte aussi supported, la liste des versions servies. Chaque réponse de l'API porte l'en-tête Api-Version, la version qui l'a servie. La version est un entier : on fige un contrat, pas un correctif.
Authentification
Une seule porte, et un seul justificatif par requête : la session d'une personne, la clé du logiciel d'un établissement (mhk_…) ou celle d'un éditeur partenaire (mhp_…). Une requête qui porte à la fois le cookie de session et un en-tête Authorization est refusée (400, code auth.ambiguous) : elle n'est pas départagée.
| Appelant | Justificatif | Atteint |
|---|---|---|
| Une personne | Cookie de session meetinghub.sid | Les établissements dont elle est membre, selon son rôle |
| Le logiciel d'un établissement | Authorization: Bearer mhk_… | Son établissement, selon les portées de la clé |
| Un éditeur partenaire | Authorization: Bearer mhp_… | Les établissements qu'il a ouverts. Voir Éditeurs partenaires |
L'établissement d'un appel se lit dans l'adresse : /api/institutions/:institutionId/…. Un établissement que l'appelant n'atteint pas répond 404, code not-found, comme s'il n'existait pas. Une route qui demande une capacité que l'appelant n'a pas dans cet établissement répond 403, code forbidden, et le message nomme ce qu'il faudrait : cet accès ne permet pas cela — il faut : schedule.read.
Une écriture faite avec le cookie de session doit venir des pages de MeetingHub : une écriture qui porte l'en-tête Origin d'un autre site est refusée (403, code origin.refused). Un client sans en-tête Origin, comme curl, n'est pas concerné.
La clé d'intégration
Authorization: Bearer mhk_Abdvt1rV_47R9xK2pQ…
| Élément | Forme |
|---|---|
| Préfixe fixe | mhk_ ; mhp_ pour une clé d'éditeur partenaire |
| Préfixe de la clé | 8 caractères, lisible en clair : il identifie la clé dans un journal |
| Séparateur | _ |
| Secret | 43 caractères |
| Alphabet | lettres A-Z et a-z, chiffres, - et _ |
La clé est vérifiée à chaque requête : une révocation prend effet à la requête suivante. Les réponses d'échec sont décrites sur la page Clés d'intégration.
GET /api/me
Rend l'appelant et ce qu'il peut faire. Aucune capacité n'est demandée ; sans justificatif, la réponse est { "actor": { "kind": "anonymous" } }.
Réponse 200, pour une clé d'établissement :
{
"actor": { "kind": "institution-key", "id": "…", "name": "ENT — émargement" },
"institutions": [{ "id": "6c1d3a52-…", "name": "Lycée bilingue", "status": "active" }],
"capabilities": ["institution.view", "attendance.read"]
}
| Champ | Type | Description |
|---|---|---|
actor.kind | string | person, institution-key, partner-key ou anonymous |
actor.id | uuid | L'identifiant de la clé, de l'éditeur partenaire ou du compte |
actor.name | string | Le nom de la clé, celui de l'éditeur partenaire, ou le courriel de la personne — son téléphone à défaut |
institutions | object[] | Les établissements que l'appelant atteint, avec leur id, leur name et leur status : trial, active ou paused. Pour une personne, role remplace status |
capabilities | string[] | Pour une clé : ce qu'elle ouvre, ses portées dites en capacités (attendance:read → attendance.read). Pour un éditeur partenaire : institution.view et partner.manage |
user | object | Pour une personne seulement : son compte, tel que le rend la connexion ci-dessous |
Ouvrir une session d'administrateur
POST /api/auth/signin — sans authentification. C'est ainsi qu'un administrateur appelle l'API avec sa session, par exemple pour poser une clé.
| Champ du corps | Type | Obligatoire | Description |
|---|---|---|---|
identifier | string | oui | Le courriel du compte, ou son téléphone. email est encore lu à sa place |
password | string | oui | Le mot de passe du compte |
Réponse 200, avec l'en-tête Set-Cookie: meetinghub.sid=… :
{
"user": {
"id": "5a74f72e-81af-402c-a2af-a5ebd35b7bba",
"email": "direction@mon-lycee.fr",
"phone": null,
"displayName": "Direction",
"platformAdmin": false,
"orgId": "6c1d3a52-7a0e-4f0b-9c55-0a54c3e1f2b8",
"orgRole": "admin",
"capabilities": ["institution.view", "institution.manage", "…"],
"institution": { "id": "6c1d3a52-…", "name": "Lycée bilingue", "status": "active", "…": "…" }
}
}
| Champ | Type | Description |
|---|---|---|
user.id | uuid | Identifiant du compte |
user.email | string ou null | Courriel du compte, en minuscules |
user.phone | string ou null | Téléphone du compte, au format international |
user.displayName | string | Nom affiché |
user.platformAdmin | boolean | true pour l'exploitant du service ; false pour un compte d'établissement |
user.orgId | uuid | L'établissement actif de la session : celui qu'ouvrent les écrans |
user.orgRole | string ou null | Le rôle dans cet établissement : promoter, admin, studies, teacher ou learner |
user.capabilities | string[] | Ce que le compte peut faire dans cet établissement |
user.institution | object ou null | Cet établissement, son nom et son statut |
Le cookie est à renvoyer avec chaque requête. Sur /api, l'établissement actif ne décide de rien : c'est l'adresse qui désigne l'établissement, et le rôle qu'on y tient qui ouvre les routes.
| Code | Corps | Cause |
|---|---|---|
401 | identifiants invalides | Identifiant ou mot de passe faux |
429 | trop de tentatives, patientez un instant | Plus de 20 tentatives en 15 minutes depuis la même adresse IP |
Types de données
Tous les corps sont du JSON encodé en UTF-8, sauf l'export CSV et la page imprimable d'une feuille de présence. Une requête avec un corps doit porter Content-Type: application/json.
| Type | Forme | Exemple |
|---|---|---|
string | Chaîne de caractères | "Salle 204" |
integer | Nombre entier | 120 |
number | Nombre, entier ou décimal | 90 |
boolean | true ou false | true |
uuid | Chaîne au format UUID, en minuscules | "5a74f72e-81af-402c-a2af-a5ebd35b7bba" |
datetime | Chaîne au format ISO 8601 | "2026-10-14T08:00:00.000Z" |
object | Objet JSON, décrit champ par champ | { "ref": "salle-204" } |
T[] | Tableau d'éléments de type T | ["attendance:read"] |
Un champ qui peut valoir null est noté « string ou null » dans la colonne Type.
Dates. En réponse, toutes les dates sont en UTC, avec les millisecondes et le suffixe Z. En requête, écrivez-les au même format : une date sans fuseau serait lue dans le fuseau du serveur.
Identifiants. Les objets de MeetingHub sont désignés par un uuid. Un uuid mal formé dans un chemin rend 404, comme un uuid inconnu. Vos propres objets — cours, salles, classes — sont désignés par votre identifiant, appelé ref : une string de 1 à 200 caractères, espaces de bord retirés. Au-delà de 200 caractères, elle est tronquée.
Champs inconnus. Un champ que la route n'attend pas est ignoré, sans erreur. Un champ attendu mais d'un autre type que celui documenté est traité comme absent.
Pagination
Les listes longues — le journal d'une clé et la liste des membres — se lisent par tranches, avec trois paramètres de requête :
| Paramètre | Type | Défaut | Bornes | Description |
|---|---|---|---|---|
limit | integer | 20 | 1 à 100 | Nombre d'éléments rendus. Une valeur hors bornes est ramenée à la borne |
offset | integer | 0 | 0 ou plus | Nombre d'éléments à sauter |
search | string | vide | 120 caractères | Filtre textuel, insensible à la casse |
La réponse porte les éléments et le total :
| Champ | Type | Description |
|---|---|---|
rows | T[] | Les éléments de la tranche |
total | integer | Le nombre total d'éléments qui répondent au filtre |
Taille des corps
| Porte | Taille maximale d'un corps JSON |
|---|---|
/api, et ses anciens alias | 4 Mo |
/api/auth | 4 Ko |
Un corps plus gros rend 413, un JSON illisible 400 : voir Corps illisible ou trop gros.
Limites de débit
| Porte | Limite | Comptée par |
|---|---|---|
/api, et ses anciens alias | 300 requêtes par minute | appelant : la clé, l'éditeur partenaire ou le compte ; l'adresse IP sans justificatif |
POST /api/auth/signin | 20 tentatives par 15 minutes | adresse IP |
Au-delà, la réponse est 429, avec un en-tête Retry-After qui donne, en secondes, le temps à attendre avant la prochaine tentative. L'exploitant d'une instance peut relever ces limites ; il ne peut pas les baisser sous ces valeurs.