Developers

The CoolRoom API

Build your app, widget or script on CoolRoom's data: homework, grades, timetable, lessons, exercises… Always with the student's consent, read only, with limits they choose.

API addresshttps://api.coolroom.app/api/open/v1

Get started

  1. 1. Make a key

    In the app: Réglages › API et applications › Créer une clé. Tick the data, pick the expiry and the limits. Copy the key: it starts with crk_ and is shown only once.

  2. 2. Call the API

    Send it in the Authorization header of each request. Answers are JSON, dates ISO 8601 (UTC).

  3. 3. For a public app

    Never ask your users for a key: use the “Sign in with CoolRoom” link. The student approves in one tap and your app gets its key.

The docs in one zip

This whole page in Markdown, ready to hand to an AI: one file per part, plus everything in one file (coolroom-api.md). Always in sync with the page.

Your first request

curl
curl "https://api.coolroom.app/api/open/v1/homework" \
  -H "Authorization: Bearer crk_…"
JavaScript
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);

Authentication

Every /api/open/v1 route needs a key, in Authorization: Bearer crk_… (or X-API-Key: crk_…). A key reads one account's data, only its scopes, and nothing else of CoolRoom. The API is read only: no route writes, sends or deletes any of the student's data.

HTTP
Authorization: Bearer crk_Xb7Qm2LpV0x9…
  • A key is a password: never in a public web page's code, never in a Git repository.
  • CoolRoom only keeps the key's fingerprint (SHA-256): if it is lost, the student makes another.
  • The student sees every key in Réglages › API et applications and can remove it at any time.
  • Your app gets exactly what the student sees in the app: same classes, same rights. Never their passwords or their Pronote logins.

Sign in with CoolRoom

The fastest way for a student: your app opens a link, the student sees your app's name, what it wants to read and for how long, then taps Autoriser. CoolRoom sends them back to your app with a one-time code, which your server (or your app, with PKCE) swaps for the key.

GET{redirect_uri}no key

2. Back to your app

Approved: ?code=…&state=…. Refused: ?error=access_denied&state=…. The code works once, for 10 minutes.

Request
https://agenda-plus.example/callback?code=Qm9uam91ciBkw6l2ZWxvcHBldXI&state=k8Jd2
POST/api/public/connect/tokenno key

3. Swap the code for the key

redirectUri must be exactly the link’s. codeVerifier is required when the link had a code_challenge. Keep apiKey safe: it is never given again.

Parameters
coderequiredThe code you got.
redirectUrirequiredThe same as in the link.
codeVerifierThe PKCE secret (43 to 128 characters).
Request
curl -X POST "https://api.coolroom.app/api/public/connect/token" \
  -H "Content-Type: application/json" \
  -d '{"code":"Qm9uam91ciBkw6l2ZWxvcHBldXI","redirectUri":"https://agenda-plus.example/callback","codeVerifier":"dBjftJeZ4CVP-mJ92K9eQ_Ft_3zsHpPhEbbsvh3JJPA"}'
Response · 200
{
  "apiKey": "crk_Xb7Qm2LpV0x9…",
  "keyId": "0f3b2a1c-9e8d-4c7b-a6f5-e4d3c2b1a090",
  "scopes": [
    "homework",
    "timetable"
  ],
  "expiresAt": "2026-11-20T08:12:40Z",
  "hourlyLimit": 600,
  "totalLimit": null,
  "user": {
    "id": "7b1e4c2a-5d3f-4e8a-9c61-2f0d8b3a4e15",
    "displayName": "Léa Martin",
    "accountType": "STUDENT"
  }
}
GET/api/public/connect/scopesno key

The scope list

Each scope with its French name and line, as the student sees them.

Request
curl "https://api.coolroom.app/api/public/connect/scopes"
Response · 200
[
  {
    "key": "homework",
    "label": "Devoirs",
    "description": "Les devoirs de tes classes et ce que tu as fini"
  }
]

PKCE in JavaScript

For a mobile app or a page without a server: make a random secret, keep it, send its fingerprint in the link, then the secret in the swap. Even if someone steals the code, they can't use it.

JavaScript
// 1. Before opening the link
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. On 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();

Limits

Each key has its limits, chosen when it is made (in the app, or by the link's parameters):

Per hour1 to 3,600 requests (600 by default). Beyond: 429 with Retry-After.
In allOptional. Once reached: 429 quota_exceeded, for good.
Expiry1 hour to 366 days, or never. After: 401 key_expired.
Keys per account20 active keys at most.

Every answer says where you stand: X-RateLimit-Limit, X-RateLimit-Remaining (this hour) and X-Total-Remaining (when the key has a total limit).

Your app can also limit itself: PATCH /key to narrow its scopes, expiry or limits, DELETE /key to give the key back (a “Disconnect” button in your app). Never to get more. PATCH /key · DELETE /key

Errors

An error always has the same shape. Test code, show message (in French).

JSON
{
  "status": 403,
  "code": "insufficient_scope",
  "message": "Cette clé n’a pas le scope « grades » (Notes)",
  "path": "/api/open/v1/grades",
  "timestamp": "2026-10-21T17:30:00Z"
}
StatuscodeWhen
400invalid_requestA parameter is missing or wrong (the message says which).
400invalid_scopeAn unknown scope in the connect link.
400invalid_grantConnect code unknown, used, expired, or a different redirectUri / codeVerifier.
401missing_keyNo key in the request.
401invalid_keyUnknown or malformed key (a key starts with crk_).
401key_revokedThe student (or your app) revoked the key.
401key_expiredThe key is past its expiry date.
403insufficient_scopeThe key lacks this route’s scope.
403cannot_widenPATCH /key can only narrow a key.
403forbiddenThe student can’t see this in the app either.
404not_foundNot found, or not this student’s.
405method_not_allowedThe API is read only.
409too_many_keysThe student already has 20 active keys.
429rate_limitedHourly limit reached: wait Retry-After seconds.
429quota_exceededThe key used all its requests (total limit).
500server_errorOur side failed. Try again later.

Scopes

The data a key can read. In the link, separate them with commas (scope=homework,grades); all asks for every one.

ScopeGives access to
profileProfile · Name, bio, account type, language.
emailEmail address · Adds the email address to the profile (with profile).
classesClasses · Classes, their members and their announcements.
homeworkHomework · Each class’s homework, done or not, votes and notes.
gradesGrades · Grades, class averages and goals.
timetableTimetable · Lessons, rooms, teachers, cancellations and detentions.
school_lifeSchool life · Absences and late arrivals.
mailMail · School mail (Pronote, Skolengo), read only.
school_accountsSchool accounts · Linked accounts and their sync. Never the logins.
chatClass chat · Class chat messages.
coursLessons · The lesson library, each lesson in Markdown, the curriculum.
exercisesExercises · Training: results card by card, mistakes, weak points.
flashcardsFlash cards · Card decks and the games played.
progressLevel and CC · Level, XP, CC, streak, season.
notificationsNotifications · The last 100 notifications.
aiAI · The conversation with CoolRoom’s AI.
familyFamily · For a parent account: linked children’s grades, homework and timetable.

Routes

Every route, with its request and an example answer. The students and ids in the examples are made up. New fields may come within v1; none will disappear or be renamed.

The key itselfany key

No scope needed: any valid key can read its limits, narrow them, or revoke itself (a “Disconnect” button in your app).

GET/api/open/v1/key

Read the key

Its scopes, expiry, limits and what is left this hour.

Request
curl "https://api.coolroom.app/api/open/v1/key" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "id": "0f3b2a1c-9e8d-4c7b-a6f5-e4d3c2b1a090",
  "name": "Agenda Plus",
  "prefix": "crk_Xb7Qm2Lp",
  "scopes": [
    "homework",
    "timetable"
  ],
  "createdAt": "2026-10-21T08:12:40Z",
  "expiresAt": "2026-11-20T08:12:40Z",
  "hourlyLimit": 600,
  "hourlyRemaining": 597,
  "totalLimit": null,
  "usedRequests": 214
}
PATCH/api/open/v1/key

Narrow the key

Your app limits itself: fewer scopes, an earlier expiry, lower limits. Never the reverse (403 cannot_widen). What you leave out stays.

Parameters
scopesbodyA subset of the current scopes.
expiresAtbodyISO 8601 date, in the future and before the current expiry.
hourlyLimitbodyFrom 1 to the current limit.
totalLimitbodyRequests in all, at most the current limit.
Request
curl -X PATCH "https://api.coolroom.app/api/open/v1/key" \
  -H "Authorization: Bearer $COOLROOM_KEY" \
  -H "Content-Type: application/json" \
  -d '{"scopes":["homework"],"hourlyLimit":100,"totalLimit":5000}'
Response · 200
{
  "id": "0f3b2a1c-9e8d-4c7b-a6f5-e4d3c2b1a090",
  "name": "Agenda Plus",
  "prefix": "crk_Xb7Qm2Lp",
  "scopes": [
    "homework"
  ],
  "createdAt": "2026-10-21T08:12:40Z",
  "expiresAt": "2026-11-20T08:12:40Z",
  "hourlyLimit": 100,
  "hourlyRemaining": 97,
  "totalLimit": 5000,
  "usedRequests": 214
}
DELETE/api/open/v1/key

Revoke the key

The key stops at once, for good.

Request
curl -X DELETE "https://api.coolroom.app/api/open/v1/key" \
  -H "Authorization: Bearer $COOLROOM_KEY"

Response · 204 · No content.

Profileprofile

The account behind the key.

GET/api/open/v1/me

The account

accountType is STUDENT or PARENT. email and emailVerified are only filled with the email scope (null otherwise).

Request
curl "https://api.coolroom.app/api/open/v1/me" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "id": "7b1e4c2a-5d3f-4e8a-9c61-2f0d8b3a4e15",
  "displayName": "Léa Martin",
  "bio": "Seconde 4, team SVT",
  "accountType": "STUDENT",
  "locale": "fr",
  "avatarIconId": "fox",
  "memberSince": "2026-09-02T17:21:05Z",
  "email": "[email protected]",
  "emailVerified": true
}

Classesclasses

The student’s classes. The invite code is never given.

GET/api/open/v1/classes

My classes

myRole: MEMBER, CO_ADMIN or CLASS_MASTER. status: APPROVED, LOCKED, ARCHIVED…

Request
curl "https://api.coolroom.app/api/open/v1/classes" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "id": "c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c",
    "name": "2nde 4",
    "description": "La meilleure classe du lycée",
    "etablissementId": "e7ab1100-4c3d-4e2f-9a8b-7c6d5e4f3a2b",
    "etablissementName": "Lycée Jean Zay",
    "classMasterName": "Tom Durand",
    "status": "APPROVED",
    "memberCount": 28,
    "myRole": "MEMBER",
    "subjectColors": {
      "Mathématiques": "#3B82F6",
      "SVT": "#22C55E"
    },
    "languages": {
      "LV2": [
        "ESPAGNOL LV2",
        "ALLEMAND LV2"
      ]
    }
  }
]
GET/api/open/v1/classes/{classId}

One class

Same shape as one item of /classes.

Parameters
classIdpathrequiredOne of the student’s classes.
Request
curl "https://api.coolroom.app/api/open/v1/classes/c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "id": "c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c",
  "name": "2nde 4",
  "memberCount": 28,
  "myRole": "MEMBER",
  "…": "…"
}
GET/api/open/v1/classes/{classId}/members

Members

status: ONLINE, FOCUS, IN_LESSON, AWAY or OFFLINE. lastSeenAt is rounded to 5 minutes, null after a week.

Request
curl "https://api.coolroom.app/api/open/v1/classes/c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c/members" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "userId": "a2b3c4d5-e6f7-4a8b-9c0d-1e2f3a4b5c6d",
    "displayName": "Tom Durand",
    "avatarIconId": "owl",
    "avatarPhotoVersion": null,
    "bio": "Délégué",
    "role": "CLASS_MASTER",
    "online": true,
    "muted": false,
    "inFocus": false,
    "status": "ONLINE",
    "lastSeenAt": "2026-10-21T15:40:00Z",
    "frame": null
  }
]
GET/api/open/v1/classes/{classId}/announcements

Announcements

The class’s announcements, newest first.

Request
curl "https://api.coolroom.app/api/open/v1/classes/c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c/announcements" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "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
  }
]

Class chatchat

Messages, oldest to newest, by pages.

GET/api/open/v1/classes/{classId}/chat

Messages

type: TEXT, LESSON, FLASHCARDS, GIVEAWAY, MEDIA, STICKER, ASSISTANT… Photos and videos are not served by the API (media only gives their details).

Parameters
beforequeryISO date: messages before it (previous page).
limitquery1 to 100.
Request
curl "https://api.coolroom.app/api/open/v1/classes/c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c/chat?limit=50" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "pinned": null,
  "messages": [
    {
      "id": "d4e5f6a7-b8c9-4d0e-8f1a-2b3c4d5e6f7a",
      "type": "TEXT",
      "author": {
        "id": "a2b3c4d5-e6f7-4a8b-9c0d-1e2f3a4b5c6d",
        "displayName": "Tom Durand",
        "avatarIconId": "owl",
        "avatarPhotoVersion": null,
        "frame": null
      },
      "body": "Quelqu’un a compris l’exo 14 ?",
      "createdAt": "2026-10-21T16:02:33Z",
      "quote": null,
      "reactions": [
        {
          "emoji": "👀",
          "count": 3,
          "names": [
            "Léa",
            "Inès",
            "Hugo"
          ],
          "reactedByMe": true
        }
      ],
      "mentionedRaw": null,
      "pinned": false,
      "mine": false,
      "deck": null,
      "giveaway": null,
      "lesson": null,
      "sources": null,
      "media": null,
      "sticker": null
    }
  ],
  "typing": []
}

Homeworkhomework

source: OFFICIAL (Pronote, school portal) or MANUAL (added by a student). status: OFFICIEL, CONFIRME or A_VERIFIER. done and snoozed belong to the student.

GET/api/open/v1/homework

Homework, by class

Every class, or one with ?classId=.

Parameters
classIdqueryOne class only.
Request
curl "https://api.coolroom.app/api/open/v1/homework" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "classes": [
    {
      "classId": "c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c",
      "className": "2nde 4",
      "homework": [
        {
          "id": "9d2f7a10-3b4c-4d5e-8f6a-7b8c9d0e1f2a",
          "subject": "Mathématiques",
          "title": "Exercices 12 à 15 p. 84",
          "description": "Faire les exercices sur les fonctions affines.",
          "dueAt": "2026-10-23T06:00:00Z",
          "source": "OFFICIAL",
          "status": "OFFICIEL",
          "isExam": false,
          "done": false,
          "completedAt": null,
          "snoozed": false,
          "submitterId": null,
          "submitterName": null,
          "confirmations": 0,
          "disagreements": 0,
          "myVote": null,
          "latestNote": "Le 15 b) est corrigé en classe",
          "latestNoteAuthor": "Tom",
          "photoVersion": null
        }
      ]
    }
  ]
}
GET/api/open/v1/homework/{homeworkId}

One homework

The homework and all its notes.

Request
curl "https://api.coolroom.app/api/open/v1/homework/9d2f7a10-3b4c-4d5e-8f6a-7b8c9d0e1f2a" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "homework": {
    "id": "9d2f7a10-3b4c-4d5e-8f6a-7b8c9d0e1f2a",
    "subject": "Mathématiques",
    "title": "Exercices 12 à 15 p. 84",
    "description": "Faire les exercices sur les fonctions affines.",
    "dueAt": "2026-10-23T06:00:00Z",
    "source": "OFFICIAL",
    "status": "OFFICIEL",
    "isExam": false,
    "done": false,
    "completedAt": null,
    "snoozed": false,
    "submitterId": null,
    "submitterName": null,
    "confirmations": 0,
    "disagreements": 0,
    "myVote": null,
    "latestNote": "Le 15 b) est corrigé en classe",
    "latestNoteAuthor": "Tom",
    "photoVersion": null
  },
  "notes": [
    {
      "id": "e5f6a7b8-c9d0-4e1f-8a2b-3c4d5e6f7a8b",
      "authorId": "a2b3c4d5-e6f7-4a8b-9c0d-1e2f3a4b5c6d",
      "authorName": "Tom",
      "authorAvatarIconId": "owl",
      "authorPhotoVersion": null,
      "body": "Le 15 b) est corrigé en classe",
      "createdAt": "2026-10-21T12:30:00Z",
      "mine": false,
      "canDelete": false
    }
  ],
  "canEdit": false,
  "canVote": false,
  "confirmationThreshold": 3
}

Gradesgrades

The student’s grades, newest first. Numbers are decimals.

GET/api/open/v1/grades

Grades

revealed: already opened in the app. The value is always given.

Request
curl "https://api.coolroom.app/api/open/v1/grades" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "id": "3a4b5c6d-7e8f-4a1b-9c2d-3e4f5a6b7c8d",
    "subject": "Physique-Chimie",
    "title": "Contrôle : les ondes",
    "value": 15.5,
    "outOf": 20,
    "classAverage": 12.25,
    "classMin": 6,
    "classMax": 18.5,
    "coefficient": 2,
    "period": "Trimestre 1",
    "date": "2026-10-17",
    "revealed": true,
    "masked": false
  }
]
GET/api/open/v1/grades/goals

Goals

Empty subject = the overall average.

Request
curl "https://api.coolroom.app/api/open/v1/grades/goals" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "subject": "",
    "target": 14
  },
  {
    "subject": "Mathématiques",
    "target": 15
  }
]

Timetabletimetable

Times are UTC (Z). detention: a detention.

GET/api/open/v1/timetable

Lessons between two dates

From from to to included, 62 days at most (Paris time).

Parameters
fromqueryrequiredYYYY-MM-DD.
toqueryrequiredYYYY-MM-DD.
Request
curl "https://api.coolroom.app/api/open/v1/timetable?from=2026-10-19&to=2026-10-25" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
    "subject": "Histoire-Géographie",
    "teacher": "M. Laurent",
    "room": "B204",
    "startAt": "2026-10-22T07:00:00Z",
    "endAt": "2026-10-22T08:00:00Z",
    "canceled": false,
    "note": null,
    "detention": false
  },
  {
    "id": "7c8d9e0f-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
    "subject": "Anglais",
    "teacher": "Mme Smith",
    "room": "A12",
    "startAt": "2026-10-22T08:00:00Z",
    "endAt": "2026-10-22T09:00:00Z",
    "canceled": true,
    "note": "Prof absente",
    "detention": false
  }
]

School lifeschool_life

kind: ABSENCE or DELAY. Detentions are in the timetable.

GET/api/open/v1/school-life

Absences and late arrivals

Newest first.

Request
curl "https://api.coolroom.app/api/open/v1/school-life" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "id": "f6a7b8c9-d0e1-4f2a-9b3c-4d5e6f7a8b9c",
    "kind": "DELAY",
    "title": "Retard",
    "reason": "Transport",
    "detail": null,
    "giver": null,
    "startAt": "2026-10-20T07:05:00Z",
    "endAt": null,
    "scheduledAt": null,
    "durationMinutes": 10,
    "justified": true
  }
]

Mailmail

School mail, read only. Reading here doesn’t mark them read.

GET/api/open/v1/mail

Inbox

type: TEACHER, ADMIN, SYSTEM or OTHER. q searches the subject, sender and text.

Parameters
qquerySearch.
typequeryFilter by sender.
Request
curl "https://api.coolroom.app/api/open/v1/mail?type=TEACHER" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "messages": [
    {
      "id": "a7b8c9d0-e1f2-4a3b-8c4d-5e6f7a8b9c0d",
      "provider": "PRONOTE",
      "providers": [
        "PRONOTE"
      ],
      "subject": "Conseil de classe",
      "snippet": "Bonjour, le conseil de classe aura lieu le…",
      "senderName": "Mme Bernard",
      "senderType": "TEACHER",
      "receivedAt": "2026-10-21T10:15:00Z",
      "read": false,
      "messageCount": 1,
      "sharedAt": null
    }
  ],
  "unreadCount": 1,
  "countsByType": {
    "TEACHER": 4,
    "ADMIN": 2,
    "SYSTEM": 0,
    "OTHER": 1
  }
}
GET/api/open/v1/mail/{mailId}

One mail and its thread

Can take a few seconds the first time (CoolRoom fetches the text from Pronote or Skolengo).

Request
curl "https://api.coolroom.app/api/open/v1/mail/a7b8c9d0-e1f2-4a3b-8c4d-5e6f7a8b9c0d" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "mail": {
    "id": "a7b8c9d0-e1f2-4a3b-8c4d-5e6f7a8b9c0d",
    "subject": "Conseil de classe",
    "senderName": "Mme Bernard",
    "…": "…"
  },
  "thread": [
    {
      "author": "Mme Bernard",
      "sentAt": "2026-10-21T10:15:00Z",
      "content": "Bonjour, le conseil de classe aura lieu le 4 décembre.",
      "fromMe": false
    }
  ]
}

School accountsschool_accounts

Linked accounts and their sync. Logins never leave the server.

GET/api/open/v1/school-accounts

Linked accounts

provider: PRONOTE, SKOLENGO or PRONOTE_ENT_AURA. status: PENDING, CONNECTED, ERROR or DISCONNECTED.

Request
curl "https://api.coolroom.app/api/open/v1/school-accounts" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "id": "b8c9d0e1-f2a3-4b4c-9d5e-6f7a8b9c0d1e",
    "provider": "PRONOTE",
    "status": "CONNECTED",
    "schoolLabel": "Lycée Jean Zay",
    "lastSyncAt": "2026-10-21T16:00:00Z",
    "lastLogonRefreshAt": "2026-10-21T16:04:00Z",
    "lastError": null,
    "syncMail": true,
    "syncHomework": true,
    "syncGrades": true,
    "syncTimetable": true,
    "available": [
      "GRADES",
      "HOMEWORK",
      "MAIL",
      "SCHOOL_LIFE",
      "TIMETABLE"
    ],
    "unavailable": []
  }
]

Lessonscours

Each class’s lesson library. Each lesson is Markdown.

GET/api/open/v1/cours/classes/{classId}

The library

Subjects, folders, lessons (without their text), links and tags.

Request
curl "https://api.coolroom.app/api/open/v1/cours/classes/c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "classId": "c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c",
  "className": "2nde 4",
  "subjects": [
    {
      "key": "svt",
      "name": "SVT",
      "icon": "microscope",
      "lessonCount": 7,
      "folderCount": 2,
      "fromTimetable": true,
      "lastUpdated": "2026-10-15T09:40:00Z"
    }
  ],
  "folders": [
    {
      "id": "1d2e3f4a-5b6c-4d7e-8f9a-0b1c2d3e4f5a",
      "subjectKey": "svt",
      "parentId": null,
      "title": "Chapitre 2",
      "icon": null,
      "aiMade": false,
      "position": 0
    }
  ],
  "lessons": [
    {
      "id": "5e550a11-8c2d-4b7a-9f3e-1d2c3b4a5f60",
      "subjectKey": "svt",
      "subjectName": "SVT",
      "folderId": null,
      "title": "La cellule, unité du vivant",
      "tags": [
        "chapitre-2",
        "cellule"
      ],
      "visibility": "CLASS",
      "status": "COMPLETE",
      "givenOn": "2026-10-14",
      "createdAt": "2026-10-14T16:02:11Z",
      "updatedAt": "2026-10-15T09:40:00Z",
      "revision": 3,
      "readingMinutes": 6,
      "author": {
        "id": "7b1e4c2a-5d3f-4e8a-9c61-2f0d8b3a4e15",
        "displayName": "Léa Martin",
        "avatarIconId": "fox",
        "avatarPhotoVersion": null
      },
      "badges": [
        "NEW"
      ]
    }
  ],
  "links": [],
  "tags": [
    {
      "path": "cellule",
      "count": 3
    }
  ],
  "canManage": false
}
GET/api/open/v1/cours/classes/{classId}/programme

The curriculum

Each chapter of the official curriculum: COMPLETE, PARTIAL or MISSING given the class’s lessons.

Request
curl "https://api.coolroom.app/api/open/v1/cours/classes/c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c/programme" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "classId": "c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c",
  "level": "SECONDE",
  "levelGuessed": false,
  "canManage": false,
  "levels": [
    "SIXIEME",
    "CINQUIEME",
    "QUATRIEME",
    "TROISIEME",
    "SECONDE",
    "PREMIERE",
    "TERMINALE"
  ],
  "subjects": [
    {
      "subjectKey": "svt",
      "subjectName": "SVT",
      "programmeKey": "SVT",
      "total": 8,
      "complete": 2,
      "partial": 1,
      "chapters": [
        {
          "id": "2e3f4a5b-6c7d-4e8f-9a0b-1c2d3e4f5a6b",
          "title": "La cellule",
          "state": "COMPLETE",
          "lessons": [
            {
              "id": "5e550a11-8c2d-4b7a-9f3e-1d2c3b4a5f60",
              "title": "La cellule, unité du vivant",
              "pinned": false
            }
          ],
          "requestId": null
        }
      ]
    }
  ]
}
GET/api/open/v1/cours/lessons/{lessonId}

One lesson

The lesson in Markdown (CoolRoom blocks included), its path, authors and links.

Request
curl "https://api.coolroom.app/api/open/v1/cours/lessons/5e550a11-8c2d-4b7a-9f3e-1d2c3b4a5f60" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "classId": "c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c",
  "lesson": {
    "id": "5e550a11-8c2d-4b7a-9f3e-1d2c3b4a5f60",
    "subjectKey": "svt",
    "subjectName": "SVT",
    "folderId": null,
    "title": "La cellule, unité du vivant",
    "tags": [
      "chapitre-2",
      "cellule"
    ],
    "visibility": "CLASS",
    "status": "COMPLETE",
    "givenOn": "2026-10-14",
    "createdAt": "2026-10-14T16:02:11Z",
    "updatedAt": "2026-10-15T09:40:00Z",
    "revision": 3,
    "readingMinutes": 6,
    "author": {
      "id": "7b1e4c2a-5d3f-4e8a-9c61-2f0d8b3a4e15",
      "displayName": "Léa Martin",
      "avatarIconId": "fox",
      "avatarPhotoVersion": null
    },
    "badges": [
      "NEW"
    ]
  },
  "markdown": "# La cellule, unité du vivant\n\n## Le noyau\n\nLe noyau contient l’ADN…",
  "path": [
    "Chapitre 2"
  ],
  "contributors": [
    {
      "id": "7b1e4c2a-5d3f-4e8a-9c61-2f0d8b3a4e15",
      "displayName": "Léa Martin",
      "avatarIconId": "fox",
      "avatarPhotoVersion": null
    }
  ],
  "links": [],
  "canEdit": false,
  "canDelete": false,
  "canManage": false,
  "social": {
    "thanks": 4,
    "thanked": true,
    "reported": false,
    "reports": 0,
    "hidden": false
  }
}

Exercisesexercises

Training and Learning: each training card, what the student got right or wrong, their mistakes and weak points.

GET/api/open/v1/exercises/classes/{classId}/results

Results card by card

Each card played: seen, right, missed (lapses), in the mistakes notebook or not, next review (dueOn). Most recent first.

Request
curl "https://api.coolroom.app/api/open/v1/exercises/classes/c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c/results" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "classId": "c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c",
  "total": 42,
  "inMistakes": 3,
  "due": 5,
  "results": [
    {
      "itemKey": "svt-cellule-q3",
      "lessonId": "5e550a11-8c2d-4b7a-9f3e-1d2c3b4a5f60",
      "lessonTitle": "La cellule, unité du vivant",
      "seen": 4,
      "correct": 2,
      "lapses": 2,
      "inMistakes": true,
      "reps": 0,
      "intervalDays": 1,
      "dueOn": "2026-10-22",
      "lastAnswerAt": "2026-10-21T17:10:00Z"
    }
  ]
}
GET/api/open/v1/exercises/classes/{classId}/mistakes

The mistakes notebook

The missed cards (20 at most), with the question and the right answer. kind: FLASH, QCM, VF, CLOZE, ORDER, MATCH…

Request
curl "https://api.coolroom.app/api/open/v1/exercises/classes/c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c/mistakes" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "scope": "errors",
  "title": "Mes erreurs",
  "subtitle": "Les cartes ratées reviennent jusqu’à deux bonnes réponses d’affilée",
  "timed": false,
  "secondsPerItem": 0,
  "items": [
    {
      "key": "svt-cellule-q3",
      "lessonId": "5e550a11-8c2d-4b7a-9f3e-1d2c3b4a5f60",
      "lessonTitle": "La cellule, unité du vivant",
      "kind": "QCM",
      "anchor": "le-noyau",
      "source": "LESSON",
      "prompt": "Où se trouve l’ADN dans une cellule animale ?",
      "answer": null,
      "options": [
        "Dans le noyau",
        "Dans la membrane",
        "Dans le cytoplasme seulement"
      ],
      "correct": [
        0
      ],
      "explanation": "L’ADN est dans le noyau (et un peu dans les mitochondries).",
      "sequence": null,
      "pairs": null,
      "truth": null,
      "game": "quiz"
    }
  ]
}
GET/api/open/v1/exercises/classes/{classId}/weak

Weak points

The lessons the student misses most.

Request
curl "https://api.coolroom.app/api/open/v1/exercises/classes/c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c/weak" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "lessonId": "5e550a11-8c2d-4b7a-9f3e-1d2c3b4a5f60",
    "seen": 12,
    "missed": 5,
    "errors": 3
  }
]
GET/api/open/v1/exercises/classes/{classId}

Training summary

Cards due, mistakes, revision plans before a test and the class challenge.

Request
curl "https://api.coolroom.app/api/open/v1/exercises/classes/c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "due": 5,
  "errors": 3,
  "weekLessons": 4,
  "challenge": {
    "goal": 300,
    "done": 212,
    "players": 17,
    "reached": false,
    "rewardCc": 20
  },
  "plans": [
    {
      "id": "3f4a5b6c-7d8e-4f9a-0b1c-2d3e4f5a6b7c",
      "title": "Contrôle SVT",
      "examOn": "2026-10-28",
      "daysLeft": 7,
      "lessons": [
        {
          "id": "5e550a11-8c2d-4b7a-9f3e-1d2c3b4a5f60",
          "title": "La cellule, unité du vivant",
          "subjectKey": "svt"
        }
      ],
      "total": 30,
      "seen": 18,
      "mastered": 9,
      "doneToday": false,
      "examDay": false,
      "sessionDays": [
        "2026-10-20"
      ]
    }
  ],
  "suggestions": []
}
GET/api/open/v1/exercises/classes/{classId}/learn

Learn

Each lesson with games, and how much of each is learnt.

Request
curl "https://api.coolroom.app/api/open/v1/exercises/classes/c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c/learn" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "lessons": [
    {
      "lessonId": "5e550a11-8c2d-4b7a-9f3e-1d2c3b4a5f60",
      "title": "La cellule, unité du vivant",
      "subjectKey": "svt",
      "subjectName": "SVT",
      "givenOn": "2026-10-14",
      "total": 24,
      "seen": 20,
      "mastered": 11,
      "due": 3,
      "games": [
        {
          "game": "quiz",
          "label": "Quiz",
          "count": 8,
          "mastered": 5
        }
      ],
      "decks": []
    }
  ]
}
GET/api/open/v1/exercises/lessons/{lessonId}

A lesson’s cards

All the lesson’s training cards and the student’s counts.

Request
curl "https://api.coolroom.app/api/open/v1/exercises/lessons/5e550a11-8c2d-4b7a-9f3e-1d2c3b4a5f60" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "lessonId": "5e550a11-8c2d-4b7a-9f3e-1d2c3b4a5f60",
  "items": [
    {
      "key": "svt-cellule-q3",
      "lessonId": "5e550a11-8c2d-4b7a-9f3e-1d2c3b4a5f60",
      "lessonTitle": "La cellule, unité du vivant",
      "kind": "QCM",
      "anchor": "le-noyau",
      "source": "LESSON",
      "prompt": "Où se trouve l’ADN dans une cellule animale ?",
      "answer": null,
      "options": [
        "Dans le noyau",
        "Dans la membrane",
        "Dans le cytoplasme seulement"
      ],
      "correct": [
        0
      ],
      "explanation": "L’ADN est dans le noyau (et un peu dans les mitochondries).",
      "sequence": null,
      "pairs": null,
      "truth": null,
      "game": "quiz"
    }
  ],
  "sections": [
    {
      "anchor": "le-noyau",
      "title": "Le noyau",
      "ai": true
    }
  ],
  "sectionsToGenerate": 0,
  "errors": 1,
  "due": 2,
  "seen": 20,
  "mastered": 11
}

Flash cardsflashcards

The student’s decks, the ones shared with them, and their games.

GET/api/open/v1/flashcards/decks

Decks

kind: VOCAB or DEFINITION. myBest: best game, null if never played.

Request
curl "https://api.coolroom.app/api/open/v1/flashcards/decks" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "mine": [
    {
      "id": "4a5b6c7d-8e9f-4a0b-1c2d-3e4f5a6b7c8d",
      "title": "Verbes irréguliers",
      "subject": "Anglais",
      "emoji": "🇬🇧",
      "cardCount": 40,
      "owner": {
        "id": "7b1e4c2a-5d3f-4e8a-9c61-2f0d8b3a4e15",
        "displayName": "Léa Martin",
        "avatarIconId": "fox",
        "avatarPhotoVersion": null
      },
      "mine": true,
      "sharedIn": [
        {
          "classId": "c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c",
          "className": "2nde 4"
        }
      ],
      "myBest": {
        "correct": 37,
        "total": 40
      },
      "myPlays": 6,
      "updatedAt": "2026-10-18T19:00:00Z",
      "lessonId": null,
      "kind": "VOCAB"
    }
  ],
  "shared": [],
  "stats": {
    "points": 1240,
    "runs": 18,
    "cardsReviewed": 610,
    "accuracy": 87,
    "perfectRuns": 2,
    "decksCreated": 3
  }
}
GET/api/open/v1/flashcards/decks/{deckId}

One deck and its cards

Card images are not served by the API.

Request
curl "https://api.coolroom.app/api/open/v1/flashcards/decks/4a5b6c7d-8e9f-4a0b-1c2d-3e4f5a6b7c8d" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "deck": {
    "id": "4a5b6c7d-8e9f-4a0b-1c2d-3e4f5a6b7c8d",
    "title": "Verbes irréguliers",
    "…": "…"
  },
  "cards": [
    {
      "id": "5b6c7d8e-9f0a-4b1c-2d3e-4f5a6b7c8d9e",
      "position": 0,
      "frontText": "to begin",
      "backText": "began, begun",
      "frontImageVersion": null,
      "backImageVersion": null
    }
  ]
}
GET/api/open/v1/flashcards/runs

Games played

The last 200, newest first.

Request
curl "https://api.coolroom.app/api/open/v1/flashcards/runs" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "id": "6c7d8e9f-0a1b-4c2d-3e4f-5a6b7c8d9e0f",
    "deckId": "4a5b6c7d-8e9f-4a0b-1c2d-3e4f5a6b7c8d",
    "deckTitle": "Verbes irréguliers",
    "correct": 37,
    "total": 40,
    "durationMs": 182000,
    "playedAt": "2026-10-18T19:04:00Z"
  }
]

Level and CCprogress

Student accounts only.

GET/api/open/v1/progress

Progress

level.into / level.needed: XP in the current level / for the next one.

Request
curl "https://api.coolroom.app/api/open/v1/progress" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
{
  "level": {
    "level": 9,
    "xp": 4210,
    "into": 310,
    "needed": 600
  },
  "cc": 185,
  "loginStreak": 12,
  "bestLoginStreak": 21,
  "season": {
    "season": {
      "id": "7d8e9f0a-1b2c-4d3e-4f5a-6b7c8d9e0f1a",
      "name": "Saison d’automne",
      "beta": false,
      "startsAt": "2026-09-01T00:00:00Z",
      "endsAt": "2026-12-20T00:00:00Z",
      "colorA": "#31AAA9",
      "colorB": "#A82020",
      "backgroundVersion": null
    },
    "level": {
      "level": 14,
      "xp": 2100,
      "into": 100,
      "needed": 200
    },
    "seenLevel": 14,
    "passMax": 50
  },
  "stats": {
    "questsDone": 34,
    "homeworkVerified": 12,
    "homeworkDone": 88,
    "flashGames": 18,
    "cosmeticsOwned": 7,
    "ccEarned": 640
  }
}

Notificationsnotifications

The last 100, newest first.

GET/api/open/v1/notifications

Notifications

type: NEW_HOMEWORK, NEW_GRADE, NEW_MAIL, LESSON_CHANGED, MENTION, CHAT_MESSAGE… relatedId: the thing it is about (homework, grade…).

Request
curl "https://api.coolroom.app/api/open/v1/notifications" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "id": "8e9f0a1b-2c3d-4e4f-5a6b-7c8d9e0f1a2b",
    "type": "NEW_HOMEWORK",
    "category": "DEVOIRS",
    "title": "Nouveau devoir en Mathématiques",
    "body": "Exercices 12 à 15 p. 84, pour jeudi",
    "relatedId": "9d2f7a10-3b4c-4d5e-8f6a-7b8c9d0e1f2a",
    "classId": "c1a55e00-2b7d-4f1e-8a3c-6d9e0f1a2b3c",
    "read": false,
    "silent": false,
    "createdAt": "2026-10-21T16:00:05Z"
  }
]

AIai

The student’s conversation with CoolRoom’s AI.

GET/api/open/v1/ai/chat

The conversation

role: user or assistant. degree: the chosen help level (1 to 3).

Request
curl "https://api.coolroom.app/api/open/v1/ai/chat" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "id": "9f0a1b2c-3d4e-4f5a-6b7c-8d9e0f1a2b3c",
    "role": "user",
    "content": "Explique-moi la mitose simplement",
    "degree": 2,
    "createdAt": "2026-10-21T17:20:00Z"
  },
  {
    "id": "0a1b2c3d-4e5f-4a6b-7c8d-9e0f1a2b3c4d",
    "role": "assistant",
    "content": "La mitose, c’est quand une cellule se divise en deux cellules identiques…",
    "degree": 2,
    "createdAt": "2026-10-21T17:20:09Z"
  }
]

Family (parent accounts)family

For a parent account: linked children and their data. 403 for a student account.

GET/api/open/v1/family/children

Linked children

status: APPROVED once the child agreed.

Request
curl "https://api.coolroom.app/api/open/v1/family/children" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "linkId": "1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
    "userId": "7b1e4c2a-5d3f-4e8a-9c61-2f0d8b3a4e15",
    "displayName": "Léa Martin",
    "avatarIconId": "fox",
    "avatarPhotoVersion": null,
    "status": "APPROVED",
    "createdAt": "2026-09-05T18:00:00Z",
    "approvedAt": "2026-09-05T18:03:00Z",
    "classNames": [
      "2nde 4"
    ]
  }
]
GET/api/open/v1/family/children/{studentId}/grades

A child’s grades

Same shape as /grades.

Request
curl "https://api.coolroom.app/api/open/v1/family/children/7b1e4c2a-5d3f-4e8a-9c61-2f0d8b3a4e15/grades" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "id": "3a4b5c6d-7e8f-4a1b-9c2d-3e4f5a6b7c8d",
    "subject": "Physique-Chimie",
    "title": "Contrôle : les ondes",
    "value": 15.5,
    "outOf": 20,
    "classAverage": 12.25,
    "classMin": 6,
    "classMax": 18.5,
    "coefficient": 2,
    "period": "Trimestre 1",
    "date": "2026-10-17",
    "revealed": true,
    "masked": false
  }
]
GET/api/open/v1/family/children/{studentId}/homework

A child’s homework

With each homework’s class.

Request
curl "https://api.coolroom.app/api/open/v1/family/children/7b1e4c2a-5d3f-4e8a-9c61-2f0d8b3a4e15/homework" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "id": "9d2f7a10-3b4c-4d5e-8f6a-7b8c9d0e1f2a",
    "subject": "Mathématiques",
    "title": "Exercices 12 à 15 p. 84",
    "description": "Faire les exercices sur les fonctions affines.",
    "dueAt": "2026-10-23T06:00:00Z",
    "status": "OFFICIEL",
    "isExam": false,
    "done": true,
    "completedAt": "2026-10-21T19:30:00Z",
    "className": "2nde 4"
  }
]
GET/api/open/v1/family/children/{studentId}/timetable

A child’s timetable

Like /timetable: from and to, 62 days at most.

Request
curl "https://api.coolroom.app/api/open/v1/family/children/7b1e4c2a-5d3f-4e8a-9c61-2f0d8b3a4e15/timetable?from=2026-10-19&to=2026-10-25" \
  -H "Authorization: Bearer $COOLROOM_KEY"
Response · 200
[
  {
    "id": "6b7c8d9e-0f1a-4b2c-8d3e-4f5a6b7c8d9e",
    "subject": "Histoire-Géographie",
    "teacher": "M. Laurent",
    "room": "B204",
    "startAt": "2026-10-22T07:00:00Z",
    "endAt": "2026-10-22T08:00:00Z",
    "canceled": false,
    "note": null,
    "detention": false
  }
]

By using the API you respect students: use their data only for what your app tells them, never sell it, don't keep it longer than needed, and delete it when the student removes access. CoolRoom's conditions of use apply. Terms of use