Requests
- Send JSON bodies with
Content-Type: application/json. Bodies are limited to 1 MB. - Unknown fields in a body are ignored, so double-check field names against the API reference.
- All endpoints are under
/v1. Breaking changes will ship under a new version prefix.
Response envelope
Every response has the same shape, so you can checkok before reading anything else.
Amounts
Amounts are decimal strings in major units, never floats or minor units:"1500" is 1,500 XOF and "12.50" is 12.50 EUR. Each currency has a maximum number of decimals — 0 for XOF, XAF and NGN, 2 for other fiat, 6 for stablecoins (see Currencies). Extra decimals are rejected with amount_decimal_not_allowed.
Use a decimal library on your side (for example decimal.js or Python’s Decimal) to avoid rounding errors.
Identifiers and timestamps
- Resources have an
id. Payins, payouts and conversions also have areference(tx_…); either one works in lookups. - Timestamps are ISO 8601 in UTC, e.g.
2026-10-27T10:15:00.000Z.
Pagination
List endpoints are cursor-paginated, most recent first.nextCursor is null.
Idempotency
Network failures happen: a request can succeed on our side while your client times out. Send anIdempotency-Key header on the requests that move money so retries are safe:
- Generate a new UUID per operation and store it with your record before calling the API.
- Retrying with the same key returns the original payout or conversion (
200) instead of creating a second one. - As an extra safety net, an identical payout (same recipient, amount, currency and network) sent within 60 seconds with a different or no key is rejected with
409 duplicate_within_window.error.details.existingReferencepoints to the first payout.
Sandbox payouts are simulated and don’t check idempotency keys: every request creates a new one.
Request IDs
Every response has anX-Request-Id header. Log it next to your own records, and include it when you contact support — it lets us find the exact request.
You can also send your own X-Request-Id (8 to 128 characters: letters, digits, ., _, :, -). If it’s valid, we use it as the request ID and echo it back, so you can correlate requests with your own logs. Otherwise we generate one.
Rate limits
Each API key can make 120 requests per minute. Every response carries the current state:
Above the limit you get
429 with error.code: "rate_limited" and a retry-after header (seconds). Wait that long before retrying. Prefer webhooks over polling to stay well under the limit.