Erreurs
Chaque erreur est un objet Problem Details (RFC 9457) dont seul le code est un contrat machine. Le format, le catalogue complet des codes par statut, et la conduite à tenir pour chacun.
Toute erreur de Noryo Merchant API est un document Problem Details (RFC 9457), servi en application/problem+json.
{
"type": "https://developer.noryo.app/errors/idempotency_key_reuse",
"title": "Idempotency key reused",
"status": 409,
"code": "idempotency_key_reuse",
"detail": "this Idempotency-Key is bound to a different request for the remainder of its TTL",
"request_id": "req_01a07784-d343-75f8-b0ae-b0629b305cd4"
}JSONLes champs
| Champ | Contenu | Stable ? |
|---|---|---|
type | L'adresse de la page du code dans le catalogue des erreurs | Le lien peut changer de domaine ; le code, non |
title | Un titre court, en anglais, pour un humain | Non : peut être reformulé |
status | Le statut HTTP de la réponse, pour tous les codes | |
code | Le code machine, en snake_case | Oui : c'est le contrat |
detail | Une phrase en anglais, parfois plus précise que le titre | Non : peut être reformulée |
request_id | L'identifiant de la tentative, identique à l'en-tête Noryo-Request-Id |
Une 410 ajoute enrichment_id, et une 503 engine_error aussi : il y désigne la tentative échouée, pas un résultat. Aucun autre membre n'est ajouté.
Bâtissez votre logique sur code, et sur le statut HTTP. title et detail sont écrits pour des humains et peuvent être reformulés à tout moment sans changement de version : un client qui les analyse cassera à la première relecture.
Les corps d'erreur ne portent jamais de SQLSTATE, de nom de table, de trace d'appels, de nom d'hôte interne, ni la valeur de votre clé ou de votre Idempotency-Key. Un 500 ne porte que code et request_id comme informations utiles.
Le catalogue
Chaque code a sa page dans le catalogue des erreurs.
| Statut | Code | Quand | Conduite |
|---|---|---|---|
| 400 | invalid_request | Corps hors schéma, champ inconnu, external_transaction_id sur un rafraîchissement, hôte inconnu | Corriger la requête |
| 400 | invalid_json | Corps qui n'est pas du JSON valide | Corriger la requête |
| 400 | identifier_required | Création sans Idempotency-Key ni external_transaction_id ; rafraîchissement sans Idempotency-Key | Ajouter l'identifiant |
| 400 | invalid_idempotency_key | En-tête Idempotency-Key vide, trop long, répété ou hors ASCII visible | Corriger la clé |
| 400 | invalid_input | Non rendu par les routes actuelles | Aucune |
| 400 | refresh_requires_transaction_id | Non rendu par les routes actuelles : le rafraîchissement d'un enrichissement sans external_transaction_id rend 409 refresh_not_available | Voir Rafraîchir |
| 400 | target_enrichment_required | Non rendu par les routes actuelles : le chemin nomme toujours la cible | Aucune |
| 400 | unsupported_canonicalization | Non rendu par les routes actuelles | Contacter le support avec le request_id |
| 401 | invalid_api_key | Clé absente, mal formée, inconnue, révoquée ou de mauvais préfixe | Corriger la clé |
| 402 | sandbox_quota_exhausted | Dotation Sandbox épuisée | Passer en Production |
| 402 | no_active_subscription | Aucun abonnement actif ne couvre l'opération | Régulariser le compte |
| 403 | insufficient_scope | La clé n'a pas le scope de la route | Utiliser une clé avec le bon scope |
| 403 | account_inactive | Organisation ou workspace inactif | Contacter Noryo |
| 403 | production_not_enabled | La clé n'est pas autorisée en Production | Voir Passage en production |
| 404 | enrichment_not_found | enrichment_id inconnu, mal formé, d'un autre workspace ou environnement | Vérifier l'identifiant, la clé, l'environnement |
| 404 | transaction_not_found | Rafraîchissement d'une transaction sans résultat enregistré | Créer un enrichissement d'abord |
| 409 | idempotency_key_reuse | Même Idempotency-Key, autre requête, dans les 24 heures | Nouvelle clé pour une nouvelle requête |
| 409 | transaction_id_conflict | Même external_transaction_id, autre entrée économique | Corriger l'entrée ou l'identifiant |
| 409 | input_mismatch | Rafraîchissement dont l'entrée diffère de celle de la transaction | Renvoyer l'entrée d'origine |
| 409 | refresh_not_available | Enrichissement d'origine sans external_transaction_id | Relire en GET, ou créer avec un identifiant |
| 410 | result_content_expired | Contenu purgé après 90 jours | Voir Rétention et 410 |
| 413 | request_entity_too_large | Corps de plus de 16 Kio | Réduire le corps |
| 415 | unsupported_media_type | Content-Type autre que application/json | Envoyer du JSON |
| 429 | rate_limited | Seau de débit vide | Reprendre après Retry-After |
| 500 | internal_error | Erreur inattendue | Reprendre avec la même clé ; citer le request_id |
| 503 | engine_error | Le moteur de résolution n'a pas répondu ; rien n'est facturé ni mémorisé | Reprendre avec la même clé |
| 503 | busy | Contention passagère, ou requête identique en cours | Reprendre après Retry-After |
| 503 | pricing_not_activated | Facturation pas encore activée pour l'opération | Reprendre après Retry-After |
Politique de reprise
| Statut | Reprendre ? |
|---|---|
429 | Oui, après Retry-After |
503 | Oui, avec la même Idempotency-Key : rien n'a été facturé ni mémorisé |
500 | Oui, avec la même Idempotency-Key |
409 | Non : corrigez la charge utile ou la clé |
Autres 4xx | Non |
Le détail est dans Reprises.
L'identifiant de tentative
Chaque réponse porte Noryo-Request-Id, et chaque corps d'erreur le répète dans request_id. Une tentative a exactement un identifiant : le même dans l'en-tête, dans le corps et dans les journaux de Noryo, y compris sur un 500. Citez-le au support et nous retrouvons la tentative exacte. Voir Identifiants de requête.
Publié le 2026-10-09 10:18 UTC (version 2).