Erreurs#
Un seul format, des codes stables, et un identifiant de trace sur chaque réponse.
Format#
Toute erreur applicative renvoie un objet error :
{
"error": {
"code": "invalid_state",
"message": "Le dossier n'est pas à une étape qui permet cette action.",
"details": { "stage": "devis_en_preparation", "allowed_actions": [] },
"trace_id": "8f1c0e2a4b9d4c7e"
}
}
code: identifiant stable, ensnake_case, fait pour être testé par votre code. Lemessage, lui, est destiné aux humains et peut changer.details: contexte structuré, propre à chaque code (vide sinon).trace_id: repris dans l'en-têteX-Trace-Id. À nous transmettre pour toute question sur une requête précise.
Les erreurs d'authentification et de quota ont un format volontairement réduit, sans détail :
{ "error": "unauthorized" }
Codes HTTP#
| Statut | Signification | Quoi faire |
|---|---|---|
400 |
Requête incompréhensible | Corriger la requête |
401 |
Jeton absent, invalide, révoqué, expiré, IP non autorisée | Vérifier la clé et l'environnement ; ne pas réessayer en boucle |
403 |
Portée manquante, ou aucun client rattaché à la clé | Demander la portée / le rattachement à ELRM |
404 |
Ressource inconnue ou qui n'est pas la vôtre (ou route inexistante) | Vérifier l'identifiant |
409 |
Conflit d'état ou d'idempotence | Lire code et details (voir ci-dessous) |
412 |
If-Match ne correspond plus |
Relire la ressource, puis réessayer |
413 |
Corps trop volumineux (256 Ko) ; details.max_bytes donne la limite |
Réduire |
422 |
Corps ou paramètres invalides | Lire details.issues |
428 |
If-Match requis et absent |
Ajouter l'en-tête |
429 |
Quota dépassé | Attendre Retry-After secondes |
500 |
Erreur interne | Réessayer plus tard ; nous transmettre le trace_id |
503 |
Bac à sable : action sortante neutralisée | Attendu sur le bac à sable, rien à faire |
Codes applicatifs#
code |
Statut | Contexte |
|---|---|---|
unauthorized |
401 | Jeton refusé, quel qu'en soit le motif |
forbidden |
403 | Portée manquante ou aucun client rattaché |
rate_limited |
429 | Quota par minute dépassé |
not_found |
404 | Ressource inexistante, pas la vôtre, ou route inconnue |
validation_error |
422 | Corps invalide ; details.issues liste chaque champ en cause |
invalid_state |
409 | Action impossible à l'étape courante ; details.stage et details.allowed_actions |
idempotency_key_reuse |
409 | Même Idempotency-Key, corps différent |
idempotency_key_invalid |
409 | Idempotency-Key de plus de 120 caractères |
precondition_required |
428 | If-Match absent sur une écriture qui l'exige |
precondition_failed |
412 | If-Match périmé ; details.current_etag donne la valeur actuelle |
request_too_large |
413 | Corps au-delà de la limite |
sandbox_outbound_blocked |
503 | Bac à sable uniquement |
internal_error |
500 | Erreur interne, tracée côté ELRM |
L'énumération est additive : de nouveaux codes peuvent apparaître. Traitez tout code inconnu selon son statut HTTP.
Erreurs de validation#
422 validation_error détaille chaque champ, au format Pydantic :
{
"error": {
"code": "validation_error",
"message": "Request validation failed",
"details": {
"issues": [
{ "loc": ["body", "lignes", 0, "nb_apprenants"], "msg": "Input should be greater than or equal to 1", "type": "greater_than_equal" }
]
},
"trace_id": "…"
}
}
Les corps sont stricts : un champ inconnu est refusé (extra_forbidden). En particulier, tout champ de prix dans un corps de dossier répond 422, les montants sont calculés par l'organisme.
Bonnes pratiques#
- Réessayez sur
429,500,502–504et les erreurs réseau, avec attente exponentielle et uneIdempotency-Keypour les écritures. - Ne réessayez jamais un
401,403,404,422sans changer la requête. - Journalisez
X-Trace-Idavec chaque appel échoué : c'est ce que nous vous demanderons en premier.