Noyau API REST de génération de questionnaires QCM. Authentification par header x-api-key, server-to-server uniquement.
Chaque requête vers /api/* (sauf /api/health, /api/version, /api/openapi.json, /api/postman.json) doit inclure le header :
x-api-key: $HYPERQUIZ_API_KEY
La clé est secrète. Ne jamais l'exposer côté navigateur — proxy les appels via votre backend.
application/json; charset=utf-8.application/problem+json (RFC 7807). Champ code stable + requestId pour le support.X-Request-Id. Vous pouvez le fournir en entrée pour corréler vos logs.Retry-After indique le délai (secondes) avant nouvelle tentative.* autorisé. L'API est conçue pour des appels server-to-server.POST de génération ne sont pas idempotents (chaque appel produit un nouveau contenu).| HTTP | code | Signification |
|---|---|---|
400 | invalid_json | Body JSON non parsable. |
400 | invalid_body | Validation Zod échouée — voir `errors`. |
401 | missing_api_key | Header `x-api-key` absent. |
401 | invalid_api_key | Clé API non reconnue. |
402 | credits_exhausted | Crédits IA épuisés côté gateway. |
405 | method_not_allowed | Méthode HTTP non supportée pour cette ressource. |
429 | rate_limited | Limite IA atteinte — voir header `Retry-After`. |
500 | internal_error | Erreur serveur inattendue — voir `requestId`. |
500 | server_misconfigured | Configuration serveur manquante. |
/api/questionnaire QuestionnairesGénérer un questionnaire complet
Génère N questions QCM sur un thème en un seul appel IA. Les niveaux sont répartis de manière déterministe entre `minLevel` et `maxLevel`.
{
"theme": "Astronomie du système solaire",
"minLevel": 1,
"maxLevel": 10,
"count": 10,
"nbChoices": 4
}
{
"tuning": "<TuningContent>",
"questions": [
{
"id": "q1",
"category": "planetes",
"level": 3,
"question": "Quelle planète est la plus proche du Soleil ?",
"choices": [
"Vénus",
"Mars",
"Mercure",
"Terre"
],
"answer_index": 2,
"explanation": "Mercure orbite à environ 58 millions de km du Soleil.",
"validation": {
"ok": true,
"warnings": []
}
}
]
}
curl -X POST https://<host>/api/questionnaire \
-H "content-type: application/json" \
-H "x-api-key: $HYPERQUIZ_API_KEY" \
-d '{"theme":"Astronomie du système solaire","minLevel":1,"maxLevel":10,"count":10,"nbChoices":4}'const res = await fetch("https://<host>/api/questionnaire", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": process.env.HYPERQUIZ_API_KEY,
},
body: JSON.stringify({
"theme": "Astronomie du système solaire",
"minLevel": 1,
"maxLevel": 10,
"count": 10,
"nbChoices": 4
}),
});
if (!res.ok) throw new Error(`HTTP ${res.status} (${res.headers.get("x-request-id")})`);
const data = await res.json();import os, requests
r = requests.post(
"https://<host>/api/questionnaire",
headers={
"content-type": "application/json",
"x-api-key": os.environ["HYPERQUIZ_API_KEY"],
},
json={
"theme": "Astronomie du système solaire",
"minLevel": 1,
"maxLevel": 10,
"count": 10,
"nbChoices": 4
},
timeout=120,
)
r.raise_for_status()
data = r.json()/api/question QuestionnairesGénérer une question unique
Génère UNE seule question à un niveau imposé. Équivalent à `getQuestionnaire` avec `count = 1` et `minLevel = maxLevel = level`.
{
"theme": "Astronomie du système solaire",
"level": 5,
"nbChoices": 4
}
{
"tuning": "<TuningContent>",
"question": {
"id": "q1",
"category": "planetes",
"level": 5,
"question": "Quelle est la plus grande lune de Saturne ?",
"choices": [
"Europe",
"Titan",
"Ganymède",
"Encelade"
],
"answer_index": 1,
"explanation": "Titan est la plus grande lune de Saturne et la 2ᵉ du système solaire.",
"validation": {
"ok": true,
"warnings": []
}
}
}
curl -X POST https://<host>/api/question \
-H "content-type: application/json" \
-H "x-api-key: $HYPERQUIZ_API_KEY" \
-d '{"theme":"Astronomie du système solaire","level":5,"nbChoices":4}'const res = await fetch("https://<host>/api/question", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": process.env.HYPERQUIZ_API_KEY,
},
body: JSON.stringify({
"theme": "Astronomie du système solaire",
"level": 5,
"nbChoices": 4
}),
});
if (!res.ok) throw new Error(`HTTP ${res.status} (${res.headers.get("x-request-id")})`);
const data = await res.json();import os, requests
r = requests.post(
"https://<host>/api/question",
headers={
"content-type": "application/json",
"x-api-key": os.environ["HYPERQUIZ_API_KEY"],
},
json={
"theme": "Astronomie du système solaire",
"level": 5,
"nbChoices": 4
},
timeout=120,
)
r.raise_for_status()
data = r.json()/api/tuning TuningGénérer un TuningContent pour un thème
Génère un `TuningContent` JSON prêt à l'emploi pour un thème donné. Utile pour préparer un tuning, l'éditer, puis le renvoyer à `/api/questionnaire`.
{
"theme": "Astronomie du système solaire",
"hints": {
"sources": [
"NASA",
"ESA"
],
"tone": "vulgarisation"
}
}
{
"tuning": {
"summary": "Panorama du système solaire : planètes, lunes, missions.",
"themes": [
{
"name": "Planètes",
"weight": 4
}
],
"distribution": {
"planetes": 40,
"lunes": 20,
"asteroides": 20,
"missions": 20
},
"level_calibration": {
"facile": "...",
"moyen": "...",
"difficile": "...",
"expert": "..."
},
"forced_topics": [],
"forbidden_topics": [],
"authorized_sources": [
"NASA",
"ESA"
],
"forbidden_sources": [],
"pedagogical_notes": "..."
}
}
curl -X POST https://<host>/api/tuning \
-H "content-type: application/json" \
-H "x-api-key: $HYPERQUIZ_API_KEY" \
-d '{"theme":"Astronomie du système solaire","hints":{"sources":["NASA","ESA"],"tone":"vulgarisation"}}'const res = await fetch("https://<host>/api/tuning", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": process.env.HYPERQUIZ_API_KEY,
},
body: JSON.stringify({
"theme": "Astronomie du système solaire",
"hints": {
"sources": [
"NASA",
"ESA"
],
"tone": "vulgarisation"
}
}),
});
if (!res.ok) throw new Error(`HTTP ${res.status} (${res.headers.get("x-request-id")})`);
const data = await res.json();import os, requests
r = requests.post(
"https://<host>/api/tuning",
headers={
"content-type": "application/json",
"x-api-key": os.environ["HYPERQUIZ_API_KEY"],
},
json={
"theme": "Astronomie du système solaire",
"hints": {
"sources": [
"NASA",
"ESA"
],
"tone": "vulgarisation"
}
},
timeout=120,
)
r.raise_for_status()
data = r.json()