API
API
BrainNotFound n'expose pas d'API publique. Cette page décrit les points d'entrée internes utilisés par l'interface, pour qui veut scripter une intégration ou comprendre le fonctionnement. Ils peuvent changer d'une version à l'autre.
Authentification
Toutes les routes, sauf connexion, inscription et mot de passe oublié, exigent une session ouverte (cookie de session Flask). Les requêtes POST exigent un jeton CSRF (csrf_token dans le formulaire), que l'interface insère dans chaque page.
Les droits sont vérifiés à chaque requête selon le rôle : une route d'administration renvoie 403 ou redirige si l'objet demandé est hors de votre périmètre.
Identifiants
Les URL utilisent un identifiant opaque (uid) ou, pour les quiz et entretiens, le slug s'il est défini. Les anciens identifiants numériques sont encore acceptés pour les quiz et redirigent vers l'adresse actuelle.
Principales routes
Quiz
| Méthode | Route | Rôle |
|---|---|---|
GET, POST |
/admin/quiz/create |
Créer un quiz |
GET, POST |
/admin/quiz/<id>/edit |
Modifier |
POST |
/admin/quiz/<id>/toggle |
Activer / désactiver |
POST |
/admin/quiz/<id>/duplicate |
Dupliquer (copie inactive) |
POST |
/admin/quiz/<id>/delete |
Supprimer |
POST |
/admin/quiz/<id>/regrade |
Relancer la correction IA des questions ouvertes |
GET |
/admin/quiz/<id>/export-csv |
Résultats en CSV |
GET, POST |
/admin/quiz/generate |
Générateur IA |
POST |
/admin/quiz/upload-image |
Envoi d'image (voir ci-dessous) |
GET, POST |
/quiz/<id>/take |
Passer un quiz (apprenant) |
Utilisateurs
| Méthode | Route | Rôle |
|---|---|---|
GET, POST |
/admin/user/create |
Créer un compte |
GET, POST |
/admin/user/<id>/edit |
Modifier |
POST |
/admin/user/<id>/delete |
Supprimer |
POST |
/admin/user/<id>/send-reset |
Envoyer le lien de choix du mot de passe |
POST |
/admin/user/<id>/reset-link |
Obtenir ce lien (JSON) sans l'envoyer |
GET, POST |
/admin/users/import |
Import CSV (csv_file, default_group, default_password) |
POST |
/admin/users/bulk-change-group |
Ajout, retrait ou remplacement de groupe en masse |
POST |
/admin/users/bulk-delete |
Suppression en masse |
Groupes
| Méthode | Route | Rôle |
|---|---|---|
GET, POST |
/admin/group/create |
Créer un groupe |
GET |
/admin/group/<id> |
Page du groupe |
POST |
/admin/group/<id>/members/add |
Ajouter une personne existante |
POST |
/admin/group/<id>/members/<user>/role |
Passer intervenant ou apprenant |
POST |
/admin/group/<id>/members/<user>/remove |
Retirer du groupe |
POST |
/admin/group/<id>/regenerate-code |
Nouveau code d'accès |
GET |
/admin/group/<id>/export-results |
Résultats du groupe en CSV |
Établissements (super-administrateurs)
| Méthode | Route | Rôle |
|---|---|---|
GET, POST |
/admin/tenants/create |
Créer |
GET, POST |
/admin/tenants/<id>/edit |
Modifier (quotas, abonnement, alertes) |
GET, POST |
/admin/tenants/<id>/delete |
Supprimer (confirmation par le nom, confirm_name) |
POST |
/admin/tenants/<id>/admins/add |
Nommer un administrateur |
Entretiens
| Méthode | Route | Rôle |
|---|---|---|
GET, POST |
/interview/admin/interviews/create |
Créer |
GET |
/interview/admin/interviews/<id>/export |
Résultats en CSV |
GET |
/interview/admin/interviews/<id>/export-json |
Définition de l'entretien en JSON |
GET, POST |
/interview/admin/interviews/import |
Import d'un JSON exporté |
GET, POST |
/interview/<id>/start |
Démarrer une session (apprenant) |
Paramètres et sauvegardes (super-administrateurs)
| Méthode | Route | Rôle |
|---|---|---|
GET, POST |
/admin/settings |
Paramètres du site |
POST |
/admin/settings/ai-models |
Tester la clé et lister les modèles (JSON) |
POST |
/admin/settings/backups/download-now |
Générer et télécharger une sauvegarde |
POST |
/admin/settings/run-backup |
Lancer une sauvegarde (FTP ou serveur) |
POST |
/admin/settings/restore-upload |
Restaurer une archive envoyée (confirm=RESTAURER) |
Données personnelles
| Méthode | Route | Rôle |
|---|---|---|
GET |
/profile/export-data |
Export des données du compte connecté |
POST |
/profile/delete-account |
Suppression de son propre compte |
Envoi d'image
POST /admin/quiz/upload-image
Content-Type: multipart/form-data
image=@schema.png
quiz_id=<id du quiz> (ou "temp" pendant la création)
Formats acceptés : PNG, JPG, GIF, WEBP, vérifiés sur le contenu du fichier. Le quota de stockage de l'établissement s'applique. La réponse JSON contient le nom du fichier et le code Markdown à insérer ; en cas d'erreur, un champ error et un code 400, 403 ou 413.
Les images sont servies par /admin/uploads/quiz-<id>/<fichier>, après contrôle d'accès.
WebSocket (Socket.IO)
La correction et les entretiens passent par Socket.IO, sur /socket.io. À la connexion, un utilisateur authentifié rejoint son salon privé (user_<id>) ; les événements lui sont envoyés là.
const socket = io();
socket.on('grading_completed', (data) => {
console.log(data.total_score, '/', data.max_score);
});
Correction d'un quiz
| Événement | Contenu |
|---|---|
connected |
room, user_id |
grading_started |
response_id, total (nombre de questions ouvertes) |
grading_progress |
response_id, progress, total, question_text, score, max_score |
grading_completed |
response_id, total_score, max_score, percentage, needs_review |
grading_error |
response_id, error |
needs_review vaut true quand au moins une réponse est restée « à corriger ».
Entretiens
Émis par le client :
| Événement | Contenu |
|---|---|
join_interview |
session_id (session de l'utilisateur connecté uniquement) |
send_message |
session_id, content |
leave_interview |
session_id |
Émis par le serveur :
| Événement | Contenu |
|---|---|
joined_interview |
session_id |
typing_indicator |
typing |
message_received |
session_id, content, interaction_count, max_interactions |
interview_ended |
session_id, reason, message |
evaluation_started |
session_id, total_criteria |
evaluation_progress |
session_id, progress, total, criterion_name, score, max_score |
evaluation_completed |
session_id, total_score, max_score, percentage |
evaluation_error |
session_id, error |
error |
message |
Les origines autorisées pour les WebSockets sont celles de ALLOWED_HOSTS (même origine si vide).
Limites de débit
Appliquées par adresse IP, sur les requêtes POST uniquement :
| Route | Limite |
|---|---|
/login |
10 par minute |
/register |
5 par minute |
/reset-password/<jeton> |
5 par minute |
/forgot-password |
3 par minute |
/resend-verification |
3 par minute |
Au-delà, la réponse est un code 429. Il n'y a pas de limite globale : un établissement entier derrière une seule adresse IP n'est pas bloqué.
Codes d'erreur
| Code | Signification |
|---|---|
| 400 | Requête invalide (paramètre manquant, jeton CSRF absent ou expiré) |
| 403 | Hors de votre périmètre, ou hôte absent de ALLOWED_HOSTS |
| 404 | Ressource introuvable |
| 413 | Fichier trop volumineux ou quota de stockage atteint |
| 429 | Trop de tentatives (voir ci-dessus) |
| 500 | Erreur serveur (détail dans docker compose logs web) |
Une page non authentifiée redirige vers /login plutôt que de renvoyer 401.