API REST
Vue d'ensemble
MathQuest expose une API REST complète pour toutes les opérations. L'API utilise JSON pour les requêtes et réponses, avec validation Zod pour la sécurité des données.
Base URL : /api/v1
Authentification : JWT via cookies (teacherToken, authToken)
Authentification
POST /api/v1/auth
Point d'entrée générique pour l'authentification avec différents action.
Actions disponibles
Connexion enseignant :
{
"action": "teacher_login",
"email": "teacher@school.com",
"password": "password123"
}
Inscription enseignant :
{
"action": "teacher_register",
"username": "prof_math",
"email": "teacher@school.com",
"password": "password123",
"name": "Dupont",
"prenom": "Jean"
}
Connexion élève :
{
"action": "login",
"email": "student@school.com",
"password": "password123"
}
Réponse de succès :
{
"success": true,
"user": {
"id": "uuid",
"username": "prof_math",
"email": "teacher@school.com",
"role": "TEACHER",
"avatarEmoji": "🎓"
},
"token": "jwt_token_here"
}
POST /api/v1/auth/logout
Déconnexion de l'utilisateur.
Réponse :
{
"success": true,
"message": "Logged out successfully"
}
POST /api/v1/auth/upgrade
Mise à niveau d'un compte invité vers un compte permanent.
{
"cookieId": "guest_session_id",
"email": "student@school.com",
"password": "new_password",
"targetRole": "STUDENT",
"adminPassword": "admin_secret"
}
POST /api/v1/auth/reset-password
Demande de réinitialisation de mot de passe.
{
"email": "user@domain.com"
}
POST /api/v1/auth/reset-password/confirm
Confirmation de réinitialisation avec nouveau mot de passe.
{
"token": "reset_token_from_email",
"newPassword": "new_secure_password"
}
POST /api/v1/auth/send-email-verification
Envoi d'un email de vérification.
{
"email": "user@domain.com"
}
POST /api/v1/auth/verify-email
Vérification de l'email avec token.
{
"token": "verification_token_from_email"
}
POST /api/v1/auth/resend-email-verification
Renvoi de l'email de vérification.
{
"email": "user@domain.com"
}
GET /api/v1/auth/status
Vérification du statut d'authentification.
Réponse :
{
"authenticated": true,
"user": {
"id": "uuid",
"username": "prof_math",
"role": "TEACHER"
}
}
POST /api/v1/auth/register
Création d'un nouveau compte utilisateur.
Authentification : Non requise
{
"username": "eleve123",
"email": "student@school.com",
"password": "password123",
"role": "STUDENT",
"avatar": "🐼"
}
POST /api/v1/auth/login
Connexion utilisateur.
Authentification : Non requise
{
"email": "student@school.com",
"password": "password123"
}
PUT /api/v1/auth/profile
Mise à jour du profil utilisateur.
Authentification : Requise
{
"username": "nouveau_nom",
"avatar": "🎭"
}
POST /api/v1/auth/upgrade-to-teacher
Mise à niveau d'un élève vers enseignant.
Authentification : Requise (élève)
{
"adminPassword": "admin_secret"
}
Gestion des parties
POST /api/v1/games
Création d'une nouvelle instance de jeu.
Authentification : Optionnelle (enseignant ou élève)
{
"name": "Quiz Mathématiques CM2",
"gameTemplateId": "uuid-du-template",
"playMode": "quiz",
"settings": {
"allowLateJoin": true,
"showCorrectAnswers": false
},
"differedAvailableFrom": "2025-09-20T08:00:00Z",
"differedAvailableTo": "2025-09-20T18:00:00Z"
}
Modes de jeu :
quiz: Quiz en temps réeltournament: Tournoi avec système de score avancépractice: Mode entraînementclass: Mode classe
Réponse :
{
"success": true,
"gameInstance": {
"id": "uuid",
"name": "Quiz Mathématiques CM2",
"accessCode": "ABC123",
"status": "waiting",
"playMode": "quiz",
"createdAt": "2025-09-19T10:00:00Z"
}
}
POST /api/v1/games/:accessCode/join
Rejoindre une partie existante (canonical, path-based).
Paramètre de chemin : accessCode (code d'accès de la partie)
Corps de la requête :
{
"userId": "uuid-player-id"
}
Réponse (exemple) :
{
"success": true,
"participant": {
"id": "uuid",
"userId": "uuid-player-id",
"status": "ACTIVE"
},
"gameInstance": {
"accessCode": "ABC123",
"status": "active"
}
}
``` "userId": "uuid-utilisateur",
"username": "Alice",
"avatar": "🎨"
}
Réponse :
{
"success": true,
"participant": {
"id": "uuid",
"userId": "uuid-utilisateur",
"username": "Alice",
"avatar": "🎨",
"liveScore": 0,
"joinedAt": "2025-09-19T10:05:00Z"
},
"gameInstance": {
"id": "uuid",
"name": "Quiz Mathématiques CM2",
"status": "active"
}
}
GET /api/v1/games/:gameId
Récupération des détails d'une partie.
Authentification : Requise (participant ou enseignant)
Réponse :
{
"id": "uuid",
"name": "Quiz Mathématiques CM2",
"accessCode": "ABC123",
"status": "active",
"playMode": "quiz",
"currentQuestionIndex": 2,
"settings": {},
"participants": [
{
"id": "uuid",
"username": "Alice",
"avatar": "🎨",
"liveScore": 850,
"status": "ACTIVE"
}
],
"leaderboard": [
{ "username": "Alice", "score": 850 },
{ "username": "Bob", "score": 720 }
]
}
GET /api/v1/games/:gameId/state
Récupération de l'état complet de la partie (avec questions).
Authentification : Requise (enseignant uniquement)
PUT /api/v1/games/:gameId/status
Mise à jour du statut d'une partie.
Authentification : Requise (enseignant)
{
"status": "active"
}
Statuts possibles :
waiting: En attente de participantsactive: Partie en courscompleted: Partie terminéecancelled: Partie annulée
PUT /api/v1/games/:gameId/rename
Renommage d'une partie.
{
"name": "Nouveau nom du quiz"
}
GET /api/v1/games/active
Liste des parties actives de l'enseignant.
Authentification : Requise (enseignant)
Réponse :
{
"games": [
{
"id": "uuid",
"name": "Quiz Mathématiques",
"accessCode": "ABC123",
"participantCount": 15,
"status": "active",
"createdAt": "2025-09-19T10:00:00Z"
}
]
}
Contrôle des parties (Enseignant)
Les endpoints de contrôle des parties sont basés sur le accessCode de la partie (paramètre de chemin). Toutes les opérations ci-dessous nécessitent une authentification professeur (teacher).
GET /api/v1/game-control/:accessCode
Récupère l'état complet de contrôle pour une partie donnée (state utilisé par le dashboard enseignant).
Authentification : Requise (enseignant)
Exemple : GET /api/v1/game-control/ABC123
Réponse (extrait) :
{ "gameState": { /* état complet affiché au professeur */ } }
POST /api/v1/game-control/:accessCode/question
Sélectionne / fixe la question courante (index de la liste de questions du quiz).
Authentification : Requise (enseignant)
Corps de la requête :
{ "questionIndex": 0 }
Réponse : nouvel état de la partie / données de la question diffusée aux élèves.
POST /api/v1/game-control/:accessCode/end-question
Met fin à la question courante et déclenche le traitement des réponses (scoring, leaderboard).
Authentification : Requise (enseignant)
Corps : aucun (POST sans body)
POST /api/v1/game-control/:accessCode/end-game
Clôt la partie et notifie les participants.
Authentification : Requise (enseignant)
Corps : aucun (POST sans body)
Note : la documentation précédente listait des endpoints body-based (
/game-control/start,/next-question,/end) acceptant{ gameId }. Les endpoints canoniques actuellement utilisés par le backend et le frontend sont basés sur:accessCodecomme illustré ci-dessus.
Modèles de jeu
GET /api/v1/game-templates
Liste des modèles de jeu disponibles.
Authentification : Requise (enseignant)
Paramètres de requête :
gradeLevel: Niveau scolaire (CP, CE1, etc.)discipline: Discipline (mathématiques, français, etc.)themes: Thèmes spécifiques
Réponse :
{
"templates": [
{
"id": "uuid",
"name": "Mathématiques - Géométrie",
"gradeLevel": "CM2",
"discipline": "mathématiques",
"themes": ["géométrie", "aires"],
"description": "Quiz sur les figures géométriques",
"questionCount": 15,
"createdAt": "2025-09-01T09:00:00Z"
}
]
}
POST /api/v1/game-templates
Création d'un nouveau modèle de jeu.
Authentification : Requise (enseignant)
{
"name": "Mon Quiz Personnalisé",
"gradeLevel": "CM1",
"discipline": "mathématiques",
"themes": ["addition", "soustraction"],
"description": "Quiz personnalisé pour CM1",
"questionIds": ["uuid-q1", "uuid-q2", "uuid-q3"]
}
GET /api/v1/game-templates/:templateId
Détails d'un modèle spécifique.
PUT /api/v1/game-templates/:templateId
Modification d'un modèle.
DELETE /api/v1/game-templates/:templateId
Suppression d'un modèle.
Quiz Templates (teacher-only endpoints)
Les opérations CRUD et de gestion des questions pour les templates de quiz.
POST /api/v1/quiz-templates
Création d'un nouveau quiz template.
Authentification : Requise (enseignant)
Corps (exemple) :
{ "name": "Mon Quiz Personnalisé", "gradeLevel": "CM1", "discipline": "mathématiques", "themes": ["addition", "soustraction"], "description": "Quiz personnalisé pour CM1", "questionUids": ["uuid-q1","uuid-q2"] }GET /api/v1/quiz-templates/:id
Récupération d'un template (option
?includeQuestions=true).GET /api/v1/quiz-templates
Liste / filtrage des templates (
discipline,themes,gradeLevel,page,pageSize).PUT /api/v1/quiz-templates/:id
Mise à jour d'un template.
DELETE /api/v1/quiz-templates/:id
Suppression d'un template.
POST /api/v1/quiz-templates/:id/questions
Ajout d'une question au template.
Corps (exemple) :
{ "questionUid": "uuid-q3", "sequence": 4 }DELETE /api/v1/quiz-templates/:id/questions/:questionUid
Suppression d'une question du template.
PUT /api/v1/quiz-templates/:id/questions-sequence
Mise à jour de l'ordre des questions dans le template.
Corps (exemple) :
{ "updates": [{ "questionUid": "uuid-q1", "sequence": 0 }, { "questionUid": "uuid-q2", "sequence": 1 }] }
Questions
GET /api/v1/questions
Recherche et filtrage de questions.
Authentification : Non requise (questions publiques)
Paramètres de requête :
gradeLevel: Niveau scolairediscipline: Disciplinethemes: Liste de thèmesdifficulty: Difficulté (1-5)limit: Nombre maximum de résultatsoffset: Décalage pour pagination
Réponse :
{
"questions": [
{
"uid": "uuid",
"title": "Calcul mental",
"text": "Combien font 15 + 27 ?",
"questionType": "numeric",
"discipline": "mathématiques",
"gradeLevel": "CE2",
"difficulty": 2,
"timeLimit": 30,
"numericQuestion": {
"correctAnswer": 42,
"tolerance": 0,
"unit": null
}
}
],
"total": 150,
"limit": 20,
"offset": 0
}
GET /api/v1/questions/:uid
Détails d'une question spécifique.
Remarque : Le backend identifie les questions par leur uid (UUID). Utilisez :uid dans les exemples d'URL.
POST /api/v1/questions
Création d'une nouvelle question.
Authentification : Requise (enseignant)
Question à choix multiples :
{
"title": "Capitale de la France",
"text": "Quelle est la capitale de la France ?",
"questionType": "multiple-choice",
"discipline": "géographie",
"gradeLevel": "CM1",
"difficulty": 1,
"timeLimit": 20,
"multipleChoiceQuestion": {
"answerOptions": ["Paris", "Lyon", "Marseille", "Toulouse"],
"correctAnswers": [true, false, false, false]
}
}
Question numérique :
{
"title": "Calcul",
"text": "Combien font 12 × 8 ?",
"questionType": "numeric",
"discipline": "mathématiques",
"gradeLevel": "CE2",
"difficulty": 2,
"timeLimit": 30,
"numericQuestion": {
"correctAnswer": 96,
"tolerance": 0,
"unit": null
}
}
GET /api/v1/questions/personal
Récupération des questions personnelles de l'enseignant.
Authentification : Requise (enseignant)
Réponse :
{
"questions": [
{
"uid": "uuid",
"title": "Ma question personnalisée",
"text": "Quelle est la réponse ?",
"questionType": "multiple-choice",
"discipline": "Personnel",
"gradeLevel": "CM1",
"difficulty": 3,
"timeLimit": 45,
"multipleChoiceQuestion": {
"answerOptions": ["A", "B", "C", "D"],
"correctAnswers": [true, false, false, false]
},
"createdAt": "2025-12-19T10:00:00Z",
"updatedAt": "2025-12-19T10:00:00Z"
}
]
}
POST /api/v1/questions/bulk-upsert
Import en masse de questions personnelles.
Authentification : Requise (enseignant)
Description : Permet de créer ou mettre à jour plusieurs questions personnelles en une seule requête. Les questions sont automatiquement marquées comme "Personnel" pour la discipline.
Payload :
{
"questions": [
{
"editorUid": "temp-id-1",
"text": "Quelle est la capitale de la France ?",
"questionType": "singleChoice",
"title": "Géographie",
"answerOptions": ["Paris", "Lyon", "Marseille", "Toulouse"],
"correctAnswers": [true, false, false, false],
"difficulty": 2,
"gradeLevel": "CM1",
"themes": ["géographie", "capitale"],
"durationMs": 30000
},
{
"uid": "existing-question-uuid",
"text": "Combien font 15 + 27 ?",
"questionType": "numeric",
"correctAnswer": 42,
"tolerance": 0,
"difficulty": 1,
"gradeLevel": "CE2"
}
]
}
Réponse :
{
"success": true,
"created": 1,
"updated": 1,
"mapping": {
"temp-id-1": "generated-uuid-123"
}
}
DELETE /api/v1/questions/personal
Suppression de toutes les questions personnelles de l'enseignant.
Authentification : Requise (enseignant)
Réponse :
{
"success": true,
"deleted": 15
}
Images partagées
GET /api/v1/shared-images/filters
Retourne les valeurs disponibles pour filtrer la bibliothèque d'images (disciplines, niveaux, types).
Authentification : Non requise
Réponse (exemple) :
{
"disciplines": ["mathématiques","français"],
"levels": ["CP","CE1","CM2"],
"types": ["illustration","photo","diagramme"]
}
GET /api/v1/shared-images
Liste des images partagées avec pagination et filtres.
Paramètres de requête : page, limit, search, discipline, level, type
Réponse (exemple) :
{
"images": [ { "id": "uuid", "title": "Triangle", "variants": [/* ... */] } ],
"total": 120,
"page": 1,
"totalPages": 3,
"hasMore": true
}
Utilisateurs
GET /api/v1/users/profile
Récupération du profil utilisateur.
Authentification : Requise
PUT /api/v1/users/profile
Mise à jour du profil utilisateur.
{
"username": "nouveau_nom",
"avatar": "🎭"
}
GET /api/v1/users/my-tournaments
Liste des tournois de l'utilisateur.
Authentification : Requise
Validation d'accès aux pages
POST /api/v1/validatePageAccess
Validation de l'accès à une page spécifique.
Authentification : Requise (enseignant)
{
"pageType": "dashboard",
"accessCode": "ABC123"
}
Types de page :
dashboard: Tableau de bord de projectionprojection: Interface de projectionpractice: Mode entraînementtournament: Interface tournoi
Réponse :
{
"valid": true,
"gameInstance": {
"id": "uuid",
"name": "Quiz Mathématiques",
"status": "active"
}
}
Gestion des enseignants
GET /api/v1/teachers/dashboard
Données du tableau de bord enseignant.
Authentification : Requise (enseignant)
GET /api/v1/teachers/students
Liste des élèves de l'enseignant.
Gestion des élèves
GET /api/v1/student/dashboard
Données du tableau de bord élève.
Authentification : Requise (élève)
GET /api/v1/student/games
Liste des parties de l'élève.
Sessions d'entraînement
GET /api/v1/practice/sessions
Liste des sessions d'entraînement.
POST /api/v1/practice/sessions
Création d'une session d'entraînement.
{
"name": "Entraînement Mathématiques",
"gradeLevel": "CM1",
"discipline": "mathématiques",
"themes": ["addition", "soustraction"],
"questionCount": 10
}
Monitoring et Santé
GET /api/v1/health
Vérification basique de la santé du système.
Authentification : Non requise
Réponse :
{
"status": "healthy",
"timestamp": "2025-12-19T12:00:00.000Z",
"uptime": 3600.5,
"environment": "development"
}
GET /api/v1/health/resources
Informations sur l'utilisation des ressources système (mémoire, CPU).
Authentification : Non requise
Réponse :
{
"timestamp": 1734609600000,
"memoryUsageMB": 45.67,
"heapUsedMB": 32.45,
"heapTotalMB": 40.12,
"externalMB": 1.23,
"cpuUsagePercent": "2.34",
"uptime": 3600.5,
"raw": {
"rss": 47841280,
"heapUsed": 33947648,
"heapTotal": 42065920,
"external": 1289744,
"arrayBuffers": 1289744,
"cpuUser": 2345678,
"cpuSystem": 1234567
}
}
GET /api/v1/health/detailed
Informations détaillées sur le système et le processus Node.js.
Authentification : Non requise
Réponse :
{
"timestamp": 1734609600000,
"uptime": 3600.5,
"memory": {
"rss": 47841280,
"heapUsed": 33947648,
"heapTotal": 42065920,
"external": 1289744,
"arrayBuffers": 1289744,
"rssMB": "45.67",
"heapUsedMB": "32.45",
"heapTotalMB": "40.12"
},
"cpu": {
"user": 2345678,
"system": 1234567,
"userSeconds": "2.35",
"systemSeconds": "1.23"
},
"process": {
"pid": 12345,
"version": "v18.17.0",
"platform": "linux",
"arch": "x64",
"nodeVersion": "18.17.0",
"v8Version": "10.2.154.26"
},
"handles": {
"active": 12,
"requests": 3
}
}
Métriques
GET /api/v1/metrics
Snapshot actuel des métriques système.
Authentification : Non requise
Note : Activé uniquement si ENABLE_METRICS=true
Réponse :
{
"enabled": true,
"timestamp": 1734609600000,
"currentMinute": 1734609600,
"alerts": [],
"metrics": {
"games": {
"active": 5,
"totalCreated": 1234,
"avgDuration": 1800
},
"users": {
"online": 45,
"total": 1234
}
}
}
GET /api/v1/metrics/history
Historique des métriques sur les N dernières minutes.
Authentification : Non requise
Paramètres :
minutes(optionnel, défaut: 10, max: 60)
Réponse :
{
"enabled": true,
"minutes": 10,
"buckets": [
{
"timestamp": 1734609540000,
"games": { "active": 3 },
"users": { "online": 42 }
}
],
"current": 1734609600,
"timestamp": 1734609600000
}
Mes Tournois
GET /api/v1/my-tournaments
Liste des parties créées et rejointes par l'utilisateur.
Authentification : Optionnelle
Paramètres :
mode(optionnel: 'tournament', 'quiz', 'practice', défaut: 'tournament')cookie_id(optionnel, pour utilisateurs invités)
Réponse :
{
"pending": [],
"active": [
{
"id": "uuid",
"name": "Quiz Mathématiques",
"accessCode": "ABC123",
"status": "active",
"participantCount": 15,
"createdAt": "2025-12-19T10:00:00Z",
"role": "teacher"
}
],
"ended": []
}
Joueurs
GET /api/v1/players/cookie/:cookieId
Récupération d'un utilisateur par son cookie ID.
Authentification : Non requise
Réponse :
{
"user": {
"id": "uuid",
"username": "eleve123",
"email": "student@school.com",
"role": "STUDENT",
"avatarEmoji": "🐼"
}
}
Taxonomie
GET /api/v1/questions/taxonomy
Récupération de toutes les métadonnées de taxonomie (liste des niveaux, disciplines, thèmes).
Authentification : Non requise
Authentification : Non requise
Réponse :
{
"gradeLevels": ["CP", "CE1", "CE2"],
"metadata": {
"CP": {
"disciplines": ["mathématiques", "français"],
"themes": {
"mathématiques": ["nombres", "addition"]
}
}
}
}
GET /api/v1/questions/taxonomy/:level
Récupération des métadonnées de taxonomie pour un niveau spécifique (ex: CP, CE1).
Authentification : Non requise
Authentification : Non requise
Paramètres :
level: Niveau scolaire (ex: "CP", "CE1")
Réponse :
{
"gradeLevel": "CP",
"content": {
"disciplines": ["mathématiques", "français"],
"themes": {
"mathématiques": ["nombres", "addition"]
}
}
}
Debug (Développement)
GET /api/v1/debug/sockets/:accessCode
Inspection des rooms Socket.IO pour une partie (développement uniquement).
Authentification : Non requise
Note : Indisponible en production
Réponse :
{
"accessCode": "ABC123",
"rooms": {
"game": { "name": "game_ABC123", "socketIds": ["socket1", "socket2"] },
"lobby": { "name": "lobby_ABC123", "socketIds": ["socket3"] },
"dashboard": { "name": "dashboard_ABC123", "socketIds": ["socket4"] },
"projection": { "name": "projection_ABC123", "socketIds": [] }
},
"allRooms": ["game_ABC123", "lobby_ABC123"],
"ts": 1734609600000
}
POST /api/v1/debug/seed-question
Création d'une question déterministe pour les tests E2E (développement uniquement).
Authentification : Non requise
Note : Indisponible en production
{
"questionType": "multiple-choice",
"title": "Question de test",
"text": "Quelle est la réponse ?",
"answerOptions": ["A", "B", "C", "D"],
"correctAnswers": [true, false, false, false],
"durationMs": 30000,
"discipline": "mathématiques",
"difficulty": 1,
"gradeLevel": "CM1",
"tags": ["test"]
}
Réponse :
{
"success": true,
"question": { /* question object */ },
"uid": "question_uid"
}
Codes d'erreur
Erreurs communes
400 Bad Request :
{
"error": "Invalid request data",
"details": "Validation failed for field 'email'"
}
401 Unauthorized :
{
"error": "Authentication required"
}
403 Forbidden :
{
"error": "Insufficient permissions"
}
404 Not Found :
{
"error": "Resource not found"
}
409 Conflict :
{
"error": "Resource already exists"
}
429 Too Many Requests :
{
"error": "Rate limit exceeded"
}
500 Internal Server Error :
{
"error": "Internal server error"
}
Limites et quotas
- Requêtes par minute : 1000 par IP
- Taille maximale du payload : 10MB
- Timeout des requêtes : 30 secondes
- Taille maximale des fichiers : 5MB (pour les images/avatar)
Webhooks et callbacks
MathQuest ne propose pas actuellement de webhooks externes, mais toutes les opérations importantes sont tracées dans les logs pour audit.
Versionnage de l'API
L'API est versionnée avec /v1/. Les changements non rétrocompatibles feront l'objet d'une nouvelle version majeure.
SDK et bibliothèques
Actuellement, aucun SDK officiel n'est fourni. L'API peut être utilisée directement avec n'importe quelle bibliothèque HTTP (axios, fetch, etc.).