Skip to main content
This is the currencies-specific integration guide. It answers one question in detail: given a currency, what is actually checked before an operation is allowed, and which failure tells you which thing was off.

The six switches

Every currency carries six independent booleans. They are not a hierarchy — a currency can be transferable but not convertible, or convertible but closed for new accounts.

Which check fires where

Read this table before designing an error-handling strategy — it tells you how many things must be true for one call to succeed. A same-currency payout therefore reads two switches. A cross-currency one reads four and then a corridor. Every one of these failures is the same status and the same code:
The message names the currency but not the capability, so when you handle this, log which operation you were attempting — otherwise you cannot tell a closed source from a closed destination.

FX corridors

Conversion needs one more thing that no endpoint exposes: an active corridor for the ordered pair of currencies. fxEnabled on both sides is necessary and not sufficient.
Corridors are directional. NGN → USD being wired does not imply USD → NGN.
There is no endpoint that lists FX corridors. You cannot precheck a specific pair, only that both currencies permit conversion at all. Handle fx_corridor_unavailable at the point of use, however thorough your precheck.

Routes versus corridors

Two endpoints answer “what can deliver to this currency”, and they are not interchangeable. Use corridors to build anything a person looks at. The expanded country list and resolved currency data are exactly what a picker needs, and the provider-neutral shape will not change under you. Use routes when you already know the currency and want routeId values with the least ceremony — a background job resolving a stored preference, say.
provider and serviceCode on the routes endpoint are internal routing detail. Corridors withhold them on purpose, and the accounts API refuses to expose the equivalent. Treat their presence here as an accident of implementation, not a contract.

Multi-country schemes

A route’s country coverage comes from one of two places, and the difference matters when you filter.
  • destinationCountry is set. The route serves that one country.
  • destinationCountry is null. Coverage comes from the scheme — sepa covers the SEPA area, cemac covers the CEMAC members — or, for mobile money, from the destination currency’s home country.
Passing ?country=DE to a currency’s routes keeps SEPA routes even though their destinationCountry is null, because the filter understands the scheme. Do not implement that logic yourself against destinationCountry; you will drop every multi-country route.

Minor units, per currency

minorUnits belongs to the currency, not to your code. Every amount in the API is an integer of these units carried as a string. A single hardcoded / 100 is wrong for UGX and wrong for every crypto asset — read minorUnits and store it beside the amount.

A precheck worth writing

That final comment is the whole point of this page: reference data gets you most of the way, and the last step belongs to the error handler.