Concepts
Idempotency
Retry safely: the same request never runs twice.
A network error does not tell you whether your request reached Monerail. Retrying a payout blindly could pay twice. To prevent this, send an Idempotency-Key header on every POST:
curl https://api.monerail.com/v1/payouts \
-H "Authorization: Bearer $MONERAIL_KEY" \
-H "Idempotency-Key: payout-inv-118" \
-H "Content-Type: application/json" \
-d '{"amount": 150000, "currency": "XAF", "recipient": {"type": "mobile_money", "name": "Kossi Mensah", "phone": "237670000777", "operator": "MTN"}}'How it works
- The first request with a key runs normally. Monerail saves its status code and response for 24 hours.
- A later request with the same key, on the same endpoint, with the same body (byte for byte) returns the saved response, without running again, with the header
Idempotent-Replayed: true.4xxerrors are saved and replayed too. - The same key with a different body, or on another endpoint, fails with
422 idempotency_key_reused. - If the first request is still running, a second one fails with
409 idempotency_key_in_use. Wait a moment and retry. - A
5xxerror is not saved: retrying with the same key runs the request again. Monerail answers5xxonly when no money was sent. If a problem occurs after the operation was sent to a payment partner or the card issuer, you get202with the object (processingorpending) instead, and that202is saved: a retry replays it and never sends the money twice. - A replayed webhook endpoint creation returns the endpoint without its
secret, which is only in the original response.
Keys are scoped to your business and mode, up to 255 characters. Use something tied to the operation in your system (payout-inv-118) or a UUID you store with it. GET and DELETE requests do not need a key.
When to retry
| Response | Retry? |
|---|---|
| Network error, timeout | Yes, with the same key |
202 |
No: the operation is on its way. Wait for the webhook, or retrieve the object. |
409 idempotency_key_in_use |
Yes, after a short wait |
429 |
Yes, after Retry-After seconds |
500, 502, 503 |
Yes, with the same key, with backoff |
400, 401, 402, 403, 404, 422 |
No: fix the request first |