Idempotency

Retry requests safely without creating duplicates.

Networks fail. An idempotency key lets you retry a request after a timeout without creating the same thing twice.

Which endpoints support it

EndpointIdempotency-Key
POST /collectionsSupported
POST /payoutsSupported
POST /recipientsNot supported
All GET requestsNot needed: reads never change anything

Using a key

Send a unique value, such as a UUID v4 you generate, in the Idempotency-Key header:

curl -X POST https://business-api.migrapay.com/v1/api/collections \
  -H "Authorization: Bearer $MIGRAPAY_API_KEY" \
  -H "Idempotency-Key: 4f1c2b8e-9d3a-4e7f-8b21-6a5c0d9e7f13" \
  -H "Content-Type: application/json" \
  -d '{ "currency": "NGN", "amount": 25000, "rail": "dynamic_virtual_account" }'

Keys belong to your business: another business using the same value never collides with yours.

Collections

If you send the same key again, MigraPay returns the collection created by the first request (the same id) instead of creating a new one.

  • Generate a new key for every new collection, and reuse it only to retry that exact request.
  • Collection keys do not expire. Never reuse one for a different collection.
  • Without the header, every request creates a new collection.

Payouts

Send an Idempotency-Key with every POST /payouts. Keys are kept for 24 hours.

You sendYou get
A new keyThe payout is created as normal.
The same key and the same bodyThe original response again, with the header Idempotent-Replayed: true. No second payout.
The same key and a different body409 IDEMPOTENCY_KEY_REUSED. Nothing is created.
The same key while the first request runs409 IDEMPOTENCY_KEY_IN_USE. Wait a moment and retry.
A key longer than 255 characters400 IDEMPOTENCY_KEY_INVALID.

If the first attempt failed (any non-2xx response), the key is released, so you can fix the request and retry with the same key.

The body comparison is exact: send the same fields in the same order when you retry.

Without a key

A payout sent without Idempotency-Key is not protected. If such a request times out, check whether it went through before sending it again: look in GET /payouts, or search GET /transactions?activity=transfer&q=… by the narration you sent.

Retrying a payout without a key, and without checking first, can pay the recipient twice.