Tous les endpoints POST qui créent une ressource acceptent un header Idempotency-Key (ou champ idempotencyKey dans le body en repli).

Pourquoi utiliser une Idempotency-Key

Quand votre serveur appelle l’API et perd la connexion entre la requête et la réponse, vous ne savez pas si la ressource a été créée. Sans idempotence :
  • Pas de retry → vous perdez la commande
  • Retry naïf → double création (deux payment intents pour le même panier)
Avec idempotence :
  • Vous envoyez la même Idempotency-Key
  • Si la précédente avait réussi, l’API renvoie la réponse 2xx initiale (la ressource existante, pas une nouvelle) — jamais un 409
  • Si la précédente avait échoué, l’API crée vraiment cette fois
Le rejeu d’une clé déjà aboutie renvoie toujours la réponse 2xx d’origine, sans erreur de conflit ni contrôle de cohérence du payload.

Format

  • Pour les payouts et transferts internes : [A-Za-z0-9_.\-:], 120 caractères maximum. Pour les payment intents, aucune contrainte de format n’est imposée. La valeur est sensible à la casse.
  • Recommandé : préfixer par votre identifiant métier pour faciliter le débogage
    • order-42-payout (votre order ID + scope)
    • monthly-payout-2026-12 (suffixe date)
    • batch-2026-12-payroll
  • Évitez les UUID purs aléatoires pour les retries : il faut que vous puissiez régénérer la même clé sur retry

TTL

Une Idempotency-Key est conservée 24h dans le cache Redis, doublée d’une colonne @unique permanente en base. La clé reste donc rattachée à sa ressource au-delà de la fenêtre de cache.

SDK Node

Le SDK auto-génère une Idempotency-Key aléatoire pour chaque POST si vous n’en fournissez pas. Pour profiter des reprises sûres (sans risque de doublon), fournissez la vôtre :
await izipay.payouts.create({
  assetCode: 'USDT.TRC20',
  amount: '500',
  destinationAddress: 'TXxxx…',
  idempotencyKey: `monthly-payout-${orderId}`,
});
Le SDK relance automatiquement sur 5xx/429 en utilisant la même Idempotency-Key.

API directe (sans SDK)

POST /v1/payouts
Authorization: Bearer sk_live_…
Idempotency-Key: monthly-payout-42
Content-Type: application/json

{ "assetCode": "USDT.TRC20", "amount": "500", "destinationAddress": "TXxxx…" }

Cas particuliers

CasComportement
Même clé, même payloadRenvoie la réponse 2xx initiale (ressource existante)
Même clé, payload différentRenvoie la réponse 2xx initiale ; aucun contrôle de mismatch de payload
Même clé, ressource toujours en créationRenvoie la réponse 2xx initiale avec la ressource en cours
Clé absenteCréation normale, requête non idempotente (chaque appel = nouvelle ressource)
Ne réutilisez jamais la même Idempotency-Key pour deux intentions métier différentes. C’est aussi grave qu’une collision UUID.

Best practices

  1. Inclure votre identifiant métier dans la clé
  2. Persister la clé côté votre DB avant d’envoyer la requête, de sorte qu’un crash + retry utilise la même
  3. Scoper par opération : order-42-intentorder-42-payout
  4. Logger la clé dans vos logs pour faciliter le debug