Idempotence
Le réseau coupe, votre serveur redémarre, le client clique deux fois : l'idempotence garantit qu'une même opération renvoyée plusieurs fois ne crée qu'une souscription et qu'un paiement.
Appels concernés
| Appel | Idempotency-Key |
|---|---|
POST /v1/souscriptions | obligatoire |
POST /v1/souscriptions/{id}/confirmer-paiement | obligatoire |
POST /v1/souscriptions/{id}/paiement | obligatoire |
| Les autres appels | Inutile : un devis en double est sans conséquence, et les lectures ne modifient rien. |
L'en-tête
Idempotency-Key: 6f1d0c3e-2b8a-4c55-9a1e-0d4b7f2a9c31- 8 à 128 caractères : lettres, chiffres,
-_:.; - générez-en une par opération (un UUID, par exemple), et gardez-la tant que l'opération n'a pas abouti ;
- elle est rattachée à la clé API qui l'envoie : la même valeur envoyée avec une autre clé API est une autre opération.
Comportement
| Situation | Réponse |
|---|---|
| Première requête | Traitée normalement. |
| Même clé, même corps | La réponse d'origine, rejouée à l'identique, avec l'en-tête Idempotent-Replayed: true. Rien n'est créé en plus. |
| Même clé, corps différent | Erreur idempotence_conflit (422). |
| Même clé, première requête encore en cours | Erreur idempotence_en_cours (409) : réessayez une seconde plus tard. |
| Première requête en erreur serveur (5xx) | La clé est libérée : renvoyez la même requête avec la même clé. |
| Après 24 heures | La clé expire et peut être oubliée. |
Réessayer sans risque
import crypto from 'node:crypto'
import { appelCoveraf } from './coveraf.js'
// Une clé par opération, générée UNE fois puis réutilisée à chaque essai.
const cle = crypto.randomUUID()
for (let essai = 1; essai <= 3; essai++) {
try {
return await appelCoveraf('POST', '/v1/souscriptions', demande, { idempotencyKey: cle })
} catch (e) {
const reessayable = !e.code || e.code === 'service_indisponible' || e.code === 'erreur_interne' || e.code === 'idempotence_en_cours'
if (!reessayable || essai === 3) throw e
await new Promise((ok) => setTimeout(ok, essai * 1000))
}
}Une erreur fréquente
Générer une nouvelle clé à chaque essai annule toute la protection : la seconde requête est vue comme une nouvelle opération. Générez la clé avant la boucle d'essais.