Idempotence
Envoyez un header Idempotency-Key sur toute requête mutante (POST, PUT, PATCH, DELETE). Il vous permet de réessayer sans risque après une coupure réseau.
Si vous l'omettez, SOAMTAR dérive une clé de votre merchant_ref (ou, à défaut, du corps de la requête) : des réessais identiques restent dédupliqués. Un header explicite est toujours prioritaire et vous donne un contrôle précis sur ce qui compte comme « la même opération ».
Pourquoi
Sans idempotence, un timeout réseau pendant un POST/payments vous oblige à choisir entre :
- réessayer — risque de créer le paiement deux fois (et de demander au client de payer deux fois) ;
- abandonner — risque de perdre un paiement qui a réussi côté SOAMTAR.
Avec l'idempotence, vous réessayez sans danger : SOAMTAR reconnaît la clé et rejoue la même réponse que la première fois, sans recréer la ressource.
Format
Idempotency-Key: <chaîne unique, 255 caractères max>Recommandé : un UUID v4 généré de votre côté. Une clé est valide 24 h après sa première utilisation.
Comportement
| Cas | Réponse |
|---|---|
| Clé jamais vue | Action exécutée, réponse mise en cache |
| Clé déjà vue + même corps | Réponse en cache rejouée + header Idempotent-Replay: true |
| Clé déjà vue + corps différent | 409 idempotency_conflict |
| Clé en cours de traitement (concurrence) | 409 idempotency_conflict |
L'empreinte est un hash SHA-256 de (method, path, body, query). Un seul caractère différent provoque un conflit.
Ce qui est mis en cache
| Statut | En cache ? |
|---|---|
2xx, 3xx | Oui — la requête a abouti |
4xx | Oui — l'erreur est déterministe (validation), la rejouer la reproduit |
5xx | Non — l'incident est transitoire, le réessai est autorisé |
En pratique : réessayez avec la même clé après un 5xx ; après un 4xx, corrigez la requête et utilisez une nouvelle clé.
Exemple
Premier appel :
curl -X POST https://app.so-amtar.com/v1/payments \
-H "Authorization: Bearer sk_test_xxx" \
-H "Idempotency-Key: 4f1c2c8a-9d4e-4b8f-9a1c-2c8a9d4e4b8f" \
-H "Content-Type: application/json" \
-d '{"merchant_ref":"ORDER-42","amount":"150.00","currency":"SLE","provider":"orange_money_sl","phone":"+23276000001"}'
# => 201 + transaction TXN-A1B2C3D4E5Réessai (après un timeout réseau) avec la même clé et le même corps :
curl -X POST https://app.so-amtar.com/v1/payments \
-H "Authorization: Bearer sk_test_xxx" \
-H "Idempotency-Key: 4f1c2c8a-9d4e-4b8f-9a1c-2c8a9d4e4b8f" \
...
# => 201 + la même transaction TXN-A1B2C3D4E5
# => header Idempotent-Replay: true
# => une seule demande de paiement est envoyée sur le téléphone du clientAvec un corps différent :
# Même clé, montant modifié
curl -X POST .../v1/payments \
-H "Idempotency-Key: 4f1c2c8a-9d4e-4b8f-9a1c-2c8a9d4e4b8f" \
-d '{"merchant_ref":"ORDER-42","amount":"175.00",...}'
# => 409 idempotency_conflictBonnes pratiques
- Une clé par opération métier, pas par requête HTTP. Si le client appuie deux fois sur « Payer », générez la clé au premier appui et réutilisez-la.
- Conservez la clé de votre côté jusqu'au résultat final (success/failed/cancelled), pas seulement le temps de la requête.
- Remboursements : envoyez toujours une clé explicite sur
POST/v1/refunds(par ex.refund-<commande>-<n>). Un remboursement n'a pas demerchant_ref, et deux remboursements partiels légitimes du même montant doivent recevoir deux clés différentes, tandis qu'un réessai du même remboursement doit réutiliser sa clé. - Évitez les horodatages comme clé : deux réessais à la milliseconde près généreraient deux clés différentes.