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.
- 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
| Cas | Comportement |
|---|
| Même clé, même payload | Renvoie la réponse 2xx initiale (ressource existante) |
| Même clé, payload différent | Renvoie la réponse 2xx initiale ; aucun contrôle de mismatch de payload |
| Même clé, ressource toujours en création | Renvoie la réponse 2xx initiale avec la ressource en cours |
| Clé absente | Cré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
- Inclure votre identifiant métier dans la clé
- Persister la clé côté votre DB avant d’envoyer la requête, de sorte qu’un crash + retry utilise la même
- Scoper par opération :
order-42-intent ≠ order-42-payout
- Logger la clé dans vos logs pour faciliter le debug