Idempotence
Le comportement exact de l'Idempotency-Key : format, portée, fenêtre de 24 heures, ce qui est comparé, ce qui est mémorisé, et ce qui se passe en cas de reprise, de conflit ou de concurrence.
L'en-tête Idempotency-Key rend une requête rejouable sans danger : si la réponse se perd sur le réseau, la même requête renvoyée avec la même clé rend la réponse déjà calculée au lieu de calculer et de facturer une seconde fois.
Format
- 1 à 255 octets, ASCII visible uniquement (
0x21à0x7E) : pas d'espace, pas de tabulation, pas de caractère accentué. - Aucune normalisation : la valeur envoyée est la valeur stockée, comparée octet pour octet.
- Un en-tête vide, trop long, contenant un caractère interdit ou répété est refusé en
400 invalid_idempotency_key, avant tout calcul.
Un UUID par opération logique est un bon choix. Générez-le une fois, avant le premier essai, et gardez-le pour toutes les reprises de cette opération.
Portée et fenêtre
| Propriété | Valeur |
|---|---|
| Portée | Le workspace et l'environnement de la clé API. Toutes les clés API d'un même workspace partagent cet espace ; Sandbox et Production sont séparés. |
| Fenêtre | 24 heures à partir de la première requête. |
| Après 24 heures | La clé redevient libre, y compris pour une requête différente. |
Ce qui est comparé
Deux requêtes sont « la même requête » quand elles portent sur la même opération (création ou rafraîchissement d'une cible donnée), la même entrée économique sous sa forme canonique et le même external_transaction_id. L'ordre des champs JSON, la casse et les espaces du descriptor, ou une fraction de seconde dans occurred_at ne changent rien. Un montant, une devise ou un identifiant différents font une autre requête.
Une même clé utilisée pour une création puis pour un rafraîchissement désigne deux requêtes différentes : la seconde rend 409 idempotency_key_reuse.
Ce qui se passe
| Situation | Réponse |
|---|---|
| Première requête avec cette clé | Traitée normalement |
Même clé, même requête, après un 200 | Le corps mémorisé de la première réponse, Noryo-Idempotency-Replayed: true. Rien n'est recalculé ni facturé. |
| Même clé, requête différente, dans les 24 heures | 409 idempotency_key_reuse |
| Même clé, même requête, pendant que la première est encore en cours | La seconde attend la fin de la première, puis rend sa réponse en rejeu ; si l'attente dure trop, 503 busy avec Retry-After |
Même clé, même requête, après un refus rendu au règlement (402, 403 production_not_enabled, 409 transaction_id_conflict, 410, 503) | Réévaluée comme une nouvelle tentative : un refus n'est pas mémorisé |
| Même clé, requête différente, après un tel refus | 409 idempotency_key_reuse : un refus ne libère pas la clé |
Même clé après un refus antérieur au règlement (400 de validation, 401, 403 insufficient_scope, 429) | La clé n'avait pas été réservée : elle reste libre |
| Même clé après 24 heures | Traitée comme une première requête |
Deux règles résument le tableau. Seul un succès est mémorisé : une erreur se rejoue en recalculant, ce qui permet de reprendre après une panne. Le lien entre une clé et sa requête ne change jamais pendant 24 heures, même après une erreur : une clé ne se recycle pas pour une autre charge.
Ce que contient un rejeu
- Le même corps,
usagecompris : une réponse facturée à l'origine affiche encorebillable: true. Ne la comptez pas une seconde fois. - L'en-tête
Noryo-Idempotency-Replayed: true. - Un nouveau
Noryo-Request-Id: chaque tentative a son identifiant, rejeu compris. - Un jeton de débit consommé, comme toute requête authentifiée.
Requêtes concurrentes
Deux requêtes identiques envoyées en même temps avec la même clé ne produisent jamais deux règlements. La seconde attend la première au lieu d'être refusée : elle reçoit ensuite le rejeu de la réponse. Si l'attente dépasse le délai que le serveur s'accorde, elle reçoit 503 busy avec un Retry-After : rien n'a été écrit ni facturé, et la même requête peut être renvoyée telle quelle.
{
"type": "https://developer.noryo.app/errors/busy",
"title": "Service busy",
"status": 503,
"code": "busy",
"detail": "The service is temporarily contended. Retry after the delay given by Retry-After.",
"request_id": "req_…"
}JSONChoisir ses clés
- Une clé par opération logique, jamais une clé par session ou par client.
- Plusieurs services dans un même workspace partagent l'espace des clés : préfixez-les, par exemple
facturation-<uuid>. - Une reprise réutilise la même clé ; une nouvelle opération en prend une nouvelle.
- Ne mettez dans la clé aucune donnée personnelle : elle n'est pas journalisée en clair, mais rien ne justifie d'y placer une information.
Publié le 2026-10-08 21:04 UTC (version 1).