boxioo Developers

Idempotence

Réessayez les requêtes POST en toute sécurité, sans créer de doublons.

Les réseaux tombent. Votre client expire avant de recevoir notre 201. Vous réessayez. Sans protection, ce retry crée un enregistrement en double.

Pour éviter ça, chaque POST accepte un header optionnel Idempotency-Key. Envoyez-le au premier essai et à chaque retry de la même requête — le serveur renvoie la réponse originale au second appel sans réexécuter l'action.

C'est le même mécanisme que Stripe, GitHub et Square.

Comment l'utiliser

Générez un UUID frais (ou toute chaîne aléatoire opaque entre 8 et 128 caractères) par action logique :

curl -X POST https://api.boxioo.com/v1/objects/contact \
  -H "Authorization: ApiKey bk_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 8a4f2e10-bb55-4c3f-9e2a-1a2b3c4d5e6f" \
  -d '{"fields":{"email":"alice@acme.com"}}'

Au premier appel : le serveur crée l'enregistrement et stocke la réponse sous cette clé.

À un retry avec la même clé + le même corps : le serveur rejoue la réponse en cache et ajoute le header :

Idempotent-Replay: true

Aucun second enregistrement n'est créé.

Durée de cache

Les réponses sont conservées 24 heures. Au-delà, la même clé peut être réutilisée pour créer une nouvelle ressource.

Même clé, corps différent

Si vous réutilisez une clé avec un corps de requête différent, le serveur rejette avec 409 idempotency_key_conflict. Ça attrape les erreurs de programmation (ex. réutiliser un UUID statique entre actions) plutôt que de les traiter comme des suppressions silencieuses de doublons.

Ce qui est mis en cache

Seules les réponses 2xx sont cachées. Si votre premier essai a renvoyé 400 ou 500, un retry réexécute bien le handler — c'est voulu, vous voulez des retries sur les échecs.

Quand NE PAS le mettre

  • Sur GET / DELETE / PATCH — déjà idempotents au niveau HTTP (on ignore le header sur ces méthodes).
  • Pour des actions non métier comme un ping ponctuel ou un appel de debug.

Bonne pratique

Générez la clé une fois par action logique, stockez-la à côté de l'action dans votre client (ex. une ligne en base), et réutilisez-la à chaque retry de cette même action. UUIDv4 convient ; un hash de (user_id, action_kind, ts) est aussi courant.

const idempotencyKey = crypto.randomUUID();
// On la sauvegarde à côté de l'action pour que les retries la réutilisent
await db.actions.insert({ id: idempotencyKey, status: 'pending' });
 
await callApi({ headers: { 'Idempotency-Key': idempotencyKey } });

On this page