Idempotency
Prevent duplicate charges when network errors interrupt your payment requests.
What Is Idempotency
Idempotency means that making the same API call multiple times produces the same result as making it once. For payment APIs, idempotency is critical: if your server sends a payment request and a network error occurs before you receive the response, you do not know whether the payment succeeded. If you simply retry, you might charge the customer twice.
Watenga solves this with the merchantTransactionId field. Every payment creation request must include a unique merchantTransactionId. If Watenga receives two requests with the same merchantTransactionId from the same merchant, the second request returns the result of the first — no duplicate charge is created.
How It Works
First request
POST /v1/checkout/create
{
"merchant_transaction_id": "ORDER-2847",
"amount": "50.00",
...
}
→ Watenga creates checkout. Returns checkout_id.Network error — you never receive the response.
Retry the same request
POST /v1/checkout/create
{
"merchant_transaction_id": "ORDER-2847",
"amount": "50.00",
...
}
→ Watenga recognises ORDER-2847. Returns the same checkout_id from before.
→ No new checkout is created. No duplicate charge.Different amount with the same ID
POST /v1/checkout/create
{
"merchant_transaction_id": "ORDER-2847",
"amount": "99.00",
...
}
→ Watenga returns error: DUPLICATE_REQUEST
→ The merchant_transaction_id is already associated with $50.00.First POST with ORDER-2847
Creates checkout → checkout_id
Network error before response
Retry POST with same ORDER-2847
Returns same checkout_id — no duplicate
POST with ORDER-2847 but different amount
DUPLICATE_REQUEST error
Generating Good Idempotency Keys
A good merchantTransactionId is unique, stable, and meaningful to your system. The best approach is to use your own order or invoice ID:
curl -X POST https://api.watenga.africa/v1/checkout/create \
-H "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"merchant_transaction_id": "ORD-8472",
"amount": "50.00",
"currency": "USD",
"return_url": "https://yoursite.com/thank-you"
}'Never use a random string as your merchantTransactionId — if you generate a new random ID on each retry you lose the idempotency benefit entirely. Never use a timestamp — timestamps are not unique under load. Always use your own order, invoice, or reference ID from your database.
Idempotency-Key header
In addition to merchantTransactionId body deduplication on checkout, Watenga supports the standard Idempotency-Key HTTP header on financial mutations (checkout, refunds, TrustPay, and related admin routes). Send the same key when retrying after a network timeout; Watenga returns the original HTTP response for 24 hours.
For integrations using live secret keys (sk_live_*), operators may enable REQUIRE_IDEMPOTENCY_KEY_LIVE=true on the API so missing keys receive IDEMPOTENCY_KEY_REQUIRED. Official SDKs and Watenga.js already send keys on checkout; merchant dashboard and developer console attach keys automatically for financial mutations.
Which Endpoints Support Idempotency
| Endpoint | Idempotency Field | Notes |
|---|---|---|
POST /v1/checkout/create | merchantTransactionId + Idempotency-Key | Body ID dedupes checkout; header dedupes full HTTP replay (recommended). |
POST /v1/payment-links | — | Safe to retry — creates new link each time |
POST /v1/transactions/:id/refund | Idempotency-Key | Required with an API key (the SDKs send one); send the same key to retry the same refund. |
Testing Idempotency in Sandbox
To verify idempotency is working in your integration:
- Create a checkout with
merchantTransactionId: 'TEST-IDEM-001' - Note the
checkout_idreturned - Create another checkout with the same
merchantTransactionId - Confirm you receive the same
checkout_id - Try with a different amount — confirm you receive
DUPLICATE_REQUESTerror
This test should be part of your integration test suite before going live.
const watenga = new Watenga('sk_test_YOUR_SANDBOX_KEY');
const first = await watenga.checkout.create({
merchant_transaction_id: 'TEST-IDEM-001',
amount: 10.0,
currency: 'USD',
return_url: 'https://example.com',
});
const second = await watenga.checkout.create({
merchant_transaction_id: 'TEST-IDEM-001',
amount: 10.0,
currency: 'USD',
return_url: 'https://example.com',
});
console.assert(first.checkout_id === second.checkout_id, 'Idempotency is working');Get notified when InnBucks and OneMoney go live.