Construis ton app, ton widget ou ton script sur les données de CoolRoom : devoirs, notes, emploi du temps, cours, exercices… Toujours avec l'accord de l'élève, en lecture seule, avec des limites qu'il choisit.
Adresse de l'APIhttps://api.coolroom.app/api/open/v1
Démarrer
1. Crée une clé
Dans l'appli : Réglages › API et applications › Créer une clé. Coche les données, choisis l'expiration et les limites. Copie la clé : elle commence par crk_ et ne s'affiche qu'une fois.
2. Appelle l'API
Envoie-la dans l'en-tête Authorization de chaque requête. Les réponses sont en JSON, les dates en ISO 8601 (UTC).
3. Pour une app publique
Ne demande jamais de clé à tes utilisateurs : utilise le lien « Se connecter avec CoolRoom ». L'élève accepte en un clic et ton app reçoit sa clé.
La doc en un zip
Toute cette page en Markdown, prête à donner à une IA : un fichier par partie, plus tout en un seul fichier (coolroom-api.md). Toujours à jour avec la page.
const res = await fetch('https://api.coolroom.app/api/open/v1/homework', {
headers: { Authorization: `Bearer ${process.env.COOLROOM_KEY}` },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.message}`);
for (const c of data.classes) console.log(c.className, c.homework.length);
Authentification
Chaque route de /api/open/v1 demande une clé, dans Authorization: Bearer crk_… (ou X-API-Key: crk_…). Une clé lit les données d'un seul compte, seulement ses scopes, et jamais rien d'autre de CoolRoom. L'API est en lecture seule : aucune route n'écrit, n'envoie ni ne supprime de données de l'élève.
HTTP
Authorization: Bearer crk_Xb7Qm2LpV0x9…
Une clé, c'est un mot de passe : jamais dans le code d'une page web publique, jamais dans un dépôt Git.
CoolRoom ne garde que l'empreinte (SHA-256) de la clé : si elle est perdue, l'élève en crée une autre.
L'élève voit chaque clé dans Réglages › API et applications et peut la retirer à tout moment.
Ton app reçoit exactement ce que l'élève voit dans l'appli : mêmes classes, mêmes droits. Jamais ses mots de passe ni ses identifiants Pronote.
Se connecter avec CoolRoom
Le moyen le plus rapide pour un élève : ton app ouvre un lien, l'élève voit le nom de ton app, ce qu'elle veut lire et pour combien de temps, puis touche Autoriser. CoolRoom renvoie vers ton app avec un code à usage unique, que ton serveur (ou ton app, avec PKCE) échange contre la clé.
GET/api/public/connectsans clé
1. Le lien « Se connecter avec CoolRoom »
Ouvre-le dans le navigateur de l’élève. CoolRoom vérifie les paramètres puis montre l’écran d’autorisation (l’élève se connecte s’il faut). Un lien cassé répond 400 avec la raison.
Paramètres
app_nameobligatoire
Le nom de ton app (2 à 60 caractères), montré à l’élève.
redirect_uriobligatoire
Où renvoyer l’élève : https://…, http://localhost…, ou le schéma de ton app (monapp://callback). Sans #.
scopeobligatoire
Les scopes, séparés par des virgules.
state
Renvoyé tel quel : vérifie-le au retour (200 caractères au plus).
code_challenge
PKCE : base64url(SHA-256(code_verifier)). Recommandé, obligatoire pour une app sans serveur.
code_challenge_method
S256 (le seul accepté).
expires_in
Durée de vie de la clé en secondes (3 600 à 31 622 400). Sans : jusqu’à ce que l’élève la retire.
redirectUri doit être exactement celle du lien. codeVerifier est obligatoire si le lien avait un code_challenge. Garde apiKey en lieu sûr : elle n’est plus jamais redonnée.
[
{
"key": "homework",
"label": "Devoirs",
"description": "Les devoirs de tes classes et ce que tu as fini"
}
]
PKCE en JavaScript
Pour une app mobile ou une page sans serveur : crée un secret au hasard, garde-le, envoie son empreinte dans le lien, puis le secret à l'échange. Même si quelqu'un vole le code, il ne peut rien en faire.
JavaScript
// 1. Avant d’ouvrir le lien
const b64url = (buf) => btoa(String.fromCharCode(...new Uint8Array(buf)))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
const verifier = b64url(crypto.getRandomValues(new Uint8Array(32)));
const challenge = b64url(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier)));
const state = b64url(crypto.getRandomValues(new Uint8Array(16)));
sessionStorage.setItem('coolroom', JSON.stringify({ verifier, state }));
location.href = 'https://api.coolroom.app/api/public/connect?' + new URLSearchParams({
app_name: 'Agenda Plus',
redirect_uri: 'https://agenda-plus.example/callback',
scope: 'homework,timetable',
state,
code_challenge: challenge,
code_challenge_method: 'S256',
});
// 2. Sur https://agenda-plus.example/callback
const q = new URLSearchParams(location.search);
const saved = JSON.parse(sessionStorage.getItem('coolroom'));
if (q.get('state') !== saved.state) throw new Error('state');
if (q.get('error')) throw new Error(q.get('error')); // access_denied
const res = await fetch('https://api.coolroom.app/api/public/connect/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
code: q.get('code'),
redirectUri: 'https://agenda-plus.example/callback',
codeVerifier: saved.verifier,
}),
});
const { apiKey, user } = await res.json();
Limites
Chaque clé a ses limites, choisies à la création (dans l'appli, ou par les paramètres du lien) :
Par heure
1 à 3 600 requêtes (600 par défaut). Au-delà : 429 avec Retry-After.
En tout
Facultatif. Une fois atteint : 429 quota_exceeded, pour toujours.
Expiration
1 heure à 366 jours, ou jamais. Après : 401 key_expired.
Clés par compte
20 clés actives au plus.
Chaque réponse dit où tu en es : X-RateLimit-Limit, X-RateLimit-Remaining (dans l'heure) et X-Total-Remaining (si la clé a une limite totale).
Ton app peut aussi se limiter elle-même : PATCH /key pour réduire ses scopes, son expiration ou ses limites, DELETE /key pour rendre la clé (un bouton « Déconnecter » dans ton app). Jamais pour en avoir plus. PATCH /key · DELETE /key
Erreurs
Une erreur répond toujours avec la même forme. Teste code, affiche message (en français).
Un paramètre manque ou ne va pas (le message dit lequel).
400
invalid_scope
Un scope inconnu dans le lien de connexion.
400
invalid_grant
Code de connexion inconnu, déjà utilisé, expiré, ou redirectUri / codeVerifier différents.
401
missing_key
Pas de clé dans la requête.
401
invalid_key
Clé inconnue ou mal formée (une clé commence par crk_).
401
key_revoked
L’élève (ou ton app) a révoqué la clé.
401
key_expired
La clé a passé sa date d’expiration.
403
insufficient_scope
La clé n’a pas le scope de cette route.
403
cannot_widen
PATCH /key ne peut que réduire une clé.
403
forbidden
L’élève n’a pas accès à cette chose dans l’appli non plus.
404
not_found
Introuvable, ou pas à cet élève.
405
method_not_allowed
L’API est en lecture seule.
409
too_many_keys
L’élève a déjà 20 clés actives.
429
rate_limited
Limite par heure atteinte : attends Retry-After secondes.
429
quota_exceeded
La clé a utilisé toutes ses requêtes (limite totale).
500
server_error
Erreur de notre côté. Réessaie plus tard.
Scopes
Les données qu'une clé peut lire. Dans le lien, sépare-les par des virgules (scope=homework,grades) ; all les demande toutes.
Scope
Donne accès à
profile
Profil · Nom, bio, type de compte, langue.
email
Adresse email · Ajoute l’adresse email au profil (avec profile).
classes
Classes · Les classes, leurs membres et leurs annonces.
homework
Devoirs · Les devoirs de chaque classe, faits ou non, votes et notes.
grades
Notes · Les notes, les moyennes de classe et les objectifs.
timetable
Emploi du temps · Les cours, salles, profs, annulations et retenues.
school_life
Vie scolaire · Absences et retards.
mail
Messagerie · Les mails de l’ENT (Pronote, Skolengo), en lecture.
school_accounts
Comptes scolaires · Les comptes reliés et leur synchro. Jamais les identifiants.
chat
Chat de classe · Les messages des chats de classe.
cours
Cours · La bibliothèque de cours, chaque cours en Markdown, le programme.
exercises
Exercices · Entraînements : résultats carte par carte, erreurs, points faibles.
flashcards
Flash cards · Les paquets de cartes et les parties jouées.
progress
Niveau et CC · Niveau, XP, CC, série, saison.
notifications
Notifications · Les 100 dernières notifications.
ai
IA · La conversation avec l’IA de CoolRoom.
family
Famille · Pour un compte parent : notes, devoirs et emploi du temps des enfants reliés.
Routes
Toutes les routes, avec leur requête et un exemple de réponse. Les élèves et les identifiants des exemples sont inventés. De nouveaux champs peuvent arriver dans v1 ; aucun ne disparaîtra ni ne changera de nom.
La clé elle-mêmetoute clé
Sans scope : toute clé valide peut lire ses limites, les réduire, ou se révoquer (un bouton « Déconnecter » dans ton app).
GET/api/open/v1/key
Lire la clé
Ses scopes, son expiration, ses limites et ce qui reste dans l’heure.
Ton app se limite elle-même : moins de scopes, une expiration plus proche, des limites plus basses. Jamais l’inverse (403 cannot_widen). Ce que tu n’envoies pas ne change pas.
Paramètres
scopescorps
Une partie des scopes actuels.
expiresAtcorps
Date ISO 8601, dans le futur et avant l’expiration actuelle.
[
{
"id": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e",
"title": "Sortie au musée jeudi",
"body": "Rendez-vous 8 h devant le lycée, prévoyez un pique-nique.",
"authorName": "Tom Durand",
"authorRole": "CLASS_MASTER",
"createdAt": "2026-10-20T18:05:00Z",
"seen": true,
"canDelete": false
}
]
Chat de classechat
Les messages, du plus ancien au plus récent, par pages.
GET/api/open/v1/classes/{classId}/chat
Les messages
type : TEXT, LESSON, FLASHCARDS, GIVEAWAY, MEDIA, STICKER, ASSISTANT… Les photos et vidéos ne sont pas servies par l’API (media donne seulement leurs infos).
En utilisant l'API, tu respectes les élèves : n'utilise leurs données que pour ce que ton app leur annonce, ne les revends jamais, ne les garde pas plus longtemps qu'il ne faut, et supprime-les quand l'élève retire l'accès. Les conditions d'utilisation de CoolRoom s'appliquent. Conditions d'utilisation