Fiat Trading
Hold Nigerian naira, convert it to and from crypto, collect it by bank transfer, and pay it out to Nigerian bank accounts.
Ask us to switch it on before you start, or every call below returns a feature-not-enabled error.
All amounts in this document are major units. Naira, not kobo. Whole USDT, not micro-units. Whole BTC, not satoshis.
What is new
Three things that were not possible before:
NGN as a currency you can hold. Your balance response now includes a naira line alongside BTC, USDT and USDC.
NGN trading pairs. The existing /api/trading endpoints now accept NGN/USDT, NGN/USDC and NGN/BTC in both directions.
NGN as a payout source. from_asset: "ngn" pays a Nigerian bank account straight from your naira balance, with no crypto leg.
Collections through NGN virtual accounts also exist and are documented below.
Authentication
Every endpoint uses the standard API auth:
Converting between naira and crypto
Conversions run on the trading endpoints. NGN pairs use the same request and response shapes as crypto pairs, so if you already trade with us there is nothing new to learn.
Two calls: quote, then order. The quote locks a rate; the order executes against it.
Rules
One side of the pair must be NGN.
side is relative to base_currency. SELL gives away the base, BUY receives it.
quantity is always an amount of base_currency.
The simplest mental model: set base_currency to what you are spending, use side: "SELL", and put the amount you are spending in quantity.
Minimum ₦500, maximum ₦10,000,000 per conversion.
quantity_in_base_units is not supported on NGN pairs. Send major units.
Step 1: get a quote
Response carries the quote id, the price, and expires_at. Quotes are short-lived, so execute promptly.
Step 2: execute
quote_id is required for NGN pairs. Without it the order is rejected: the rate has to be locked before we move money.
A quote can only be executed once. Pass reference if you want to supply your own idempotency key; otherwise the quote id serves as one.
The six pairs
you spend | you receive | base_currency | quote_currency | side |
|---|---|---|---|---|
NGN | USDT | NGN | USDT | SELL |
NGN | USDC | NGN | USDC | SELL |
NGN | BTC | NGN | BTC | SELL |
USDT | NGN | USDT | NGN | SELL |
USDC | NGN | USDC | NGN | SELL |
BTC | NGN | BTC | NGN | SELL |
How settlement differs by pair
Worth knowing, because it affects timing.
NGN to and from stablecoins settle inline. We source the asset before crediting you, so when the call returns the conversion is complete.
NGN to and from BTC deliver from our own inventory immediately, and we rebalance our books afterwards. From your side it is complete when the call returns. You will not see the rebalancing and it does not affect your balance.
Paying out to a Nigerian bank
Same three-step payout flow you already use, with from_asset: "ngn". No crypto leg, no conversion, no deposit address.
Step 1: quote
source must be offchain for NGN. There is no onchain naira.
Send either amount (what you spend) or settlement_amount (what the recipient receives), not both. If you send both, amount wins and settlement_amount is ignored.
Step 2: initialize
Supply the beneficiary bank details. This is also where the payout is priced, so the fee becomes known at this step.
Step 3: finalize
This is the point of no return. It freezes the funds and submits to our provider.
Cross border from naira
to_currency does not have to be NGN. You can pay a Ghanaian cedi account from a naira balance by setting to_currency: "ghs" and country: "GH". The FX happens on our side.
Collecting naira
A virtual account is a dedicated Nigerian bank account number tied to one of your customers. Money paid into it credits your NGN balance.
Create one
reference must be unique to you and acts as the idempotency key. NGN is currently the only supported currency.
The customer must be complete first
This is the most common reason a virtual account request fails, so get it right before you call.
We are required to verify the identity behind every naira account, so the customer record has to carry all of the following before we can issue one:
field | notes |
|---|---|
first_name | |
last_name | |
email | |
phone_number | |
date_of_birth | must be 18 or over |
id_type | must be "bvn" |
id_number | the 11 digit BVN |
The BVN lives on the customer, not on the virtual account request. Set it when you create the customer, or patch an existing one:
We verify the BVN against the national registry when the account is created. A BVN that does not match the customer's details is rejected.
If anything is missing you get one error naming every missing field at once, so you can fix them in a single pass rather than discovering them one at a time:
Nothing is wrong with your virtual account payload. Go and update the customer.
Other operations
method | path | purpose |
|---|---|---|
GET | /api/virtual-accounts | List your accounts |
GET | /api/virtual-accounts/:id | Fetch one |
GET | /api/virtual-accounts/:id/transactions | Deposits into that account |
PATCH | /api/virtual-accounts/:id/alias | Change the display name |
GET | /api/virtual-accounts/supported-currencies | Currently returns NGN |
In sandbox, POST /api/virtual-accounts/:id/simulate-deposit fakes an inbound transfer so you can test without moving real money. It is rejected in production.
Balances
Your existing balance endpoint returns naira alongside your crypto balances. No new call to make.
Naira is reported in major units, so a 1000 balance means one thousand naira.
Errors worth handling
situation | what you get |
|---|---|
NGN not enabled for you | feature-not-enabled |
Customer missing BVN or other required fields | validation error naming every missing field |
BVN does not match the customer's details | verification failure |
Amount below ₦500 or above ₦10,000,000 | validation error |
Order sent without quote_id | validation error |
Quote expired or already used | failed precondition |
Not enough balance | failed precondition |
quantity_in_base_units on an NGN pair | validation error |
Common mistakes
Sending kobo. Every naira amount is in whole naira. 5000 is five thousand naira, not fifty.
Reusing a quote. One execution per quote. Get a fresh one for each conversion.
Sitting on a quote. They expire in seconds. Request the quote when you are ready to execute, not at the start of a checkout flow.
Assuming side refers to the pair. It refers to base_currency. If in doubt, put what you are spending in base_currency and use SELL.
Creating a customer without a BVN, then asking for a virtual account. The BVN goes on the customer record via id_type and id_number. Add it up front and you avoid a round trip.