Aller au contenu principal

Patterns

Génération de clés d'idempotence

UUID v4 vs hash(payload + tenant + timestamp)

Une clé d'idempotence garantit qu'un POST retryé n'exécute l'action qu'une fois. Deux stratégies. UUID v4 : généré côté client, stocké en header `Idempotency-Key`. Avantage : trivial, totalement aléatoire. Inconvénient : exige que le client persiste la clé entre tentatives (sinon nouveau retry = nouvelle clé = duplicate). Hash déterministe : `sha256(tenant_id || payload_canonical || time_window)` où `time_window` est par exemple le timestamp arrondi à 5 minutes. Avantage : pas besoin de stockage côté client, deux requêtes identiques génèrent la même clé. Inconvénient : risque de collision si deux requêtes légitimes ont exactement le même payload dans la même fenêtre. Scell.io accepte l'UUID v4 fourni par le client (recommandé) et stocke la réponse pour 24h. Si l'header est absent, Scell.io génère un hash interne pour les endpoints critiques (création facture, recharge balance).

À retenir

  • UUID v4 : recommandé, le client persiste la clé entre retries
  • Hash déterministe : sha256(tenant_id || canonical_payload || time_bucket)
  • Header Scell.io : `Idempotency-Key: <uuid>`
  • Stockage serveur : 24h, réponse rejouée à l'identique sur retry
  • Endpoints critiques : POST /invoices, POST /signatures, POST /balance/reload

Exemple de code

import { randomUUID, createHash } from 'node:crypto';

// Stratégie 1 : UUID v4 (recommandé)
const idempotencyKey = randomUUID();
await persistKey(operationId, idempotencyKey); // store for retries

// Stratégie 2 : Hash déterministe (fallback sans stockage client)
function deterministicKey(tenantId: string, payload: object): string {
  const canonical = JSON.stringify(payload, Object.keys(payload).sort());
  const timeBucket = Math.floor(Date.now() / (5 * 60 * 1000));
  return createHash('sha256')
    .update(`${tenantId}|${canonical}|${timeBucket}`)
    .digest('hex');
}

await fetch('https://api.scell.io/api/v1/invoices', {
  method: 'POST',
  headers: { 'Idempotency-Key': idempotencyKey, 'X-API-Key': process.env.SCELL_KEY! },
  body: JSON.stringify(payload),
});

Voir aussi

Vos préférences cookies

Nous utilisons des cookies pour améliorer votre expérience. Les cookies essentiels sont toujours actifs. Politique cookies.