Aller au contenu
Support

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

AppelIdempotency-Key
POST /v1/souscriptionsobligatoire
POST /v1/souscriptions/{id}/confirmer-paiementobligatoire
POST /v1/souscriptions/{id}/paiementobligatoire
Les autres appelsInutile : un devis en double est sans conséquence, et les lectures ne modifient rien.

L'en-tête

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

SituationRéponse
Première requêteTraitée normalement.
Même clé, même corpsLa 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érentErreur idempotence_conflit (422).
Même clé, première requête encore en coursErreur 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 heuresLa clé expire et peut être oubliée.

Réessayer sans risque

Node.js
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.