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

plain
POST /v1/checkout/create
{
  "merchantTransactionId": "ORDER-2847",
  "amount": "50.00",
  ...
}

→ Watenga creates checkout. Returns checkoutId.

Network error — you never receive the response.

Retry the same request

plain
POST /v1/checkout/create
{
  "merchantTransactionId": "ORDER-2847",
  "amount": "50.00",
  ...
}

→ Watenga recognises ORDER-2847. Returns the same checkoutId from before.
→ No new checkout is created. No duplicate charge.

Different amount with the same ID

plain
POST /v1/checkout/create
{
  "merchantTransactionId": "ORDER-2847",
  "amount": "99.00",
  ...
}

→ Watenga returns error: DUPLICATE_REQUEST
→ The merchantTransactionId is already associated with $50.00.

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:

bash
curl -X POST https://api.watenga.africa/v1/checkout/create \
  -H "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "merchantTransactionId": "ORD-8472",
    "amount": "50.00",
    "currency": "USD",
    "returnUrl": "https://yoursite.com/thank-you",
    "notificationUrl": "https://yoursite.com/webhooks/watenga"
  }'

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.

Which Endpoints Support Idempotency

EndpointIdempotency FieldNotes
POST /v1/checkout/createmerchantTransactionIdRequired. Primary idempotency key.
POST /v1/payment-linksSafe to retry — creates new link each time
POST /v1/payouts/requestWatenga deduplicates by amount + time window
POST /v1/transactions/:id/refundIdempotent by transaction ID — safe to retry

Testing Idempotency in Sandbox

To verify idempotency is working in your integration:

  1. Create a checkout with merchantTransactionId: 'TEST-IDEM-001'
  2. Note the checkoutId returned
  3. Create another checkout with the same merchantTransactionId
  4. Confirm you receive the same checkoutId
  5. Try with a different amount — confirm you receive DUPLICATE_REQUEST error

This test should be part of your integration test suite before going live.

javascript
const watenga = new Watenga('sk_test_YOUR_SANDBOX_KEY');

const first = await watenga.checkout.create({
  merchantTransactionId: 'TEST-IDEM-001',
  amount: 10.0,
  currency: 'USD',
  returnUrl: 'https://example.com',
  notificationUrl: 'https://example.com/webhook',
});

const second = await watenga.checkout.create({
  merchantTransactionId: 'TEST-IDEM-001',
  amount: 10.0,
  currency: 'USD',
  returnUrl: 'https://example.com',
  notificationUrl: 'https://example.com/webhook',
});

console.assert(first.checkoutId === second.checkoutId, 'Idempotency is working');
See also: Error codes (DUPLICATE_REQUEST) and Create checkout API.

Get notified when InnBucks and OneMoney go live.