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:
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.
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.destinationCountryis set. The route serves that one country.destinationCountryis null. Coverage comes from thescheme—sepacovers the SEPA area,cemaccovers the CEMAC members — or, for mobile money, from the destination currency’s home country.
?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.