Crypto
Customers can pay with stablecoins on any of our checkouts. Each supported asset is offered on a specific network (for example USDT on Tron, USDC on Base), the customer sends the exact quoted amount to a deposit address we generate, and the payment confirms once it lands on-chain. It works the same across inline, standard, and invoice checkout.
Rolling out gradually
Crypto is being enabled account by account. If you do not see the Pay with Crypto option on your API keys in the dashboard, contact support to request access.
Enabling crypto
Crypto is configured per API key, in the dashboard under the key's payment methods:
- Toggle Crypto (USDC / USDT) on for the key.
- Choose how you want to be settled:
- Settle in Naira: we convert the crypto and pay you through your existing settlement (bank or ZevPay balance). No wallet needed.
- Settle in crypto: we pay out the same asset to your verified crypto wallet. You need a verified wallet for each asset you accept; add them under Settlement, then Crypto wallets. New and changed wallets pass a short security review before payouts flow to them.
Both modes settle on our standard T+1 schedule, like every other method.
How it appears to customers
When crypto is available on a session, each asset shows as its own option in the method list with its logo and an explicit network label, for example "USDT · Tron (TRC20)". After picking an asset the customer sees:
- The exact amount of the asset to send, locked to a quote.
- A deposit address with a QR code, plus a memo when the network requires one.
- A clear warning that funds must be sent as that asset on that network only.
The page then waits for the on-chain confirmation and completes automatically. If the quote window lapses before payment, the session expires the same way other methods do.
Assets and networks
An asset is only ever identified together with its network. The same token on two networks is two different destinations, and a transfer sent on the wrong network cannot be recovered. Everywhere in the API, the dashboard, and webhooks, the unit is the pair ASSET:NETWORK.
| Asset | Network identifier | Shown to customers as | Address format | Memo |
|---|---|---|---|---|
USDT | TRON | USDT · Tron (TRC20) | T… (34 chars) | No |
USDC | BASE | USDC · Base | 0x… (42 chars) | No |
Network identifiers are stable, uppercase, and ours: TRON, BASE, ETHEREUM, BSC, SOLANA are the values we use, whatever a wallet or exchange calls them (TRC20, ERC20, BEP20 and so on are shown to customers as the label, never used as the identifier).
Where you will meet the pair:
crypto_assetson initialize, the inline SDK, and invoices:"USDT:TRON". The bare form"USDT"means every network we offer for that asset at the time of the request. If your integration must be deterministic, always pin the network.- Initialize response
crypto_assets: each entry carriesassetCodeandnetworkseparately, plus adisplayNamefor display only. - Webhooks (
charge.success):crypto.assetandcrypto.network. Reconcile on both, never on the asset alone. - Dashboard, key settings: each accepted asset is a row per network, and each payout wallet is registered for one
(asset, network). A USDT payout can only go to a wallet on the same network the customer paid on.
When we add a network for an existing asset, it appears as a new row in this table, a new entry in your key's accepted-assets list, and a new item in crypto_assets responses. Nothing about an existing pair changes, so integrations that key on the pair keep working unchanged.
When crypto is offered
An asset appears on a checkout only when all of these hold:
- The API key has crypto enabled with a settlement mode set.
- Your account has crypto access.
- The checkout's value meets the minimum for that asset. Each asset has a platform minimum in its own units; a checkout worth less than the minimum (at the live rate) will not offer that asset.
- For settle-in-crypto keys: you have a verified, payout-eligible wallet for the asset.
The decision is made when the session is created, and the offered assets are fixed for that session's lifetime.
Steering crypto per checkout
Crypto is added to a session automatically whenever the conditions above hold and your request passes no payment_methods, so nothing changes for existing integrations. An explicit payment_methods list is honoured exactly: include "crypto" (or pass crypto_assets) to offer it, and a list without either never shows crypto. When you want more control:
- Pass
payment_methods: ["crypto"]for a crypto-only checkout (the fiat tiles are not shown). - Pass
crypto_assets: ["USDT:TRON"]to offer only that asset on that network, or["USDT"]for every network of the asset. The list can only narrow the assets enabled on your key. Identifiers are listed under Assets and networks. - Both work on initialize, on the inline SDK (
paymentMethods: ['crypto'],cryptoAssets: [...]), and on invoices.
If you ask for crypto and it is not eligible on that checkout, initialize fails with 400 rather than silently falling back to fiat. The full decision table is on the Payment Methods page.
Integration
No extra integration is needed beyond what you already have. Crypto rides the same session and webhook machinery:
- The initialize response includes
"crypto"inenabled_payment_methodsand lists the offered assets incrypto_assets, each as{ assetCode, network, displayName, decimals }. - A successful payment fires the same
charge.successwebhook withchannel: "crypto"and acryptoobject carrying the asset, network, and asset amount. Theamountfield stays the NGN presentment value in kobo. - Verify works unchanged; the session reports
completedonce the deposit confirms. - Invoices record crypto payments like any other method, so
invoice.paidandinvoice.payment_receivedfire as usual.
Amounts you price stay in your presentment currency; we handle the conversion quote for the customer.
Fees
Crypto payments use the same pricing configured for your account as our other methods, including the fee cap. With crypto settlement the fee is taken in the asset itself, and the naira cap is converted at that payment's own exchange rate, so a large payment never pays more than the cap's worth regardless of settlement mode.
Withdrawal fee for crypto settlement
If you settle in crypto, each payout to your external wallet carries a flat withdrawal fee in the asset itself (for example a fixed amount of USDT), separate from the per-payment processing fee above. It covers the cost of the on-chain payout and is charged once per settlement payout, not per payment: all of a day's payments in the same asset and network batch into one payout, and the single fee comes off that batch total.
- The current fee per asset is shown in your dashboard on the key's crypto settings, next to each asset.
- Your payout breakdown (dashboard and email) itemises it: collected amount, withdrawal fee, net sent to your wallet.
- If a payout total is smaller than the fee, the payout is held and rolls into the next one until it clears the fee, so the fee can never consume a payout.
- Settling in Naira has no withdrawal fee; it follows your normal settlement rails.
Reliability
Payment confirmation is webhook-driven with an automatic reconciliation sweep behind it, so a confirmed on-chain deposit completes the checkout even if a webhook delivery is delayed. If a customer reports paying without the page confirming, the payment resolves automatically once the deposit confirms; the transaction also appears in your dashboard like any other.