ELRM developer Bac à sable

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, en snake_case, fait pour être testé par votre code. Le message, lui, est destiné aux humains et peut changer.
  • details : contexte structuré, propre à chaque code (vide sinon).
  • trace_id : repris dans l'en-tête X-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–504 et les erreurs réseau, avec attente exponentielle et une Idempotency-Key pour les écritures.
  • Ne réessayez jamais un 401, 403, 404, 422 sans changer la requête.
  • Journalisez X-Trace-Id avec chaque appel échoué : c'est ce que nous vous demanderons en premier.