Skip to main content
This guide shows you how to use Bitnob’s Offramp APIs to receive USDT from a user on-chain (e.g., via TRC20) and automatically convert and settle it into Nigerian Naira (NGN) into a local bank account. We’ll walk through the entire value flow, what each step means, and how to present each step clearly in your application.

Key concepts

The quote

Before you receive any crypto, you must lock in an exchange rate using a quote. The quote:
  • Tells you the exchange rate that will be used (e.g., 1 USDT = ₦1702)
  • Defines how many NGN the user will receive
  • Is valid for 16 minutes to avoid market volatility

Source of funds

You’re specifying:
  • source: “onchain”, meaning the user will send USDT from an external wallet
  • chain: “TRON”, the network the user will use to send the USDT (Tron is fastest and cheapest)

The address

After the quote is accepted via the initialize step, Bitnob gives you a USDT address. This is what you show the user to send funds to.

Settlement

When funds arrive at the address:
  • Bitnob automatically detects the incoming USDT
  • Converts it using the locked-in quote rate
  • Settles the equivalent NGN into the bank account you provided

Full flow overview

Bitnob account setup process

Request a quote

Step: Lock in the exchange rate. Full schema: Create Payouts Quote.
Example request:
Example response:
What this means:
  • The rate is guaranteed for 16 minutes, until the expires_at timestamp
  • You must initialize and receive funds within this window

Initialize the payout

This step binds the quote to the destination bank account: see Initialize Payout. Confirm the account resolves first with Account Lookup.
Example request:
Example response:
What you should do next:
  • Display the returned USDT address to the user
  • Prompt them to send the full deposit_amount (1000 USDT here) on TRC20 to the address. It is the quoted amount plus fees
  • Start tracking the reference and quote_id for this session

Funding finalizes the payout

Don’t call finalize on an onchain payout. It returns 400 before funding, and the payout finalizes automatically once the user’s deposit confirms. The USDT address stays valid until expires_at.

Testing in sandbox

Sandbox has no endpoint that simulates a stablecoin deposit to a payout address, so a payout you don’t fund stays PENDING_ADDRESS_DEPOSIT until it expires. Test the quote and initialize steps, and the webhook handling with your own signed test payloads.

Settlement lifecycle (what happens after deposit)

Once the user funds the address, Bitnob handles the rest of the flow: track it with Get Payout by ID or the payout webhooks:
  1. It confirms receipt (at least 19 confirmations on Tron, more for larger amounts)
  2. Converts the USDT to NGN at the locked quote rate
  3. Sends the NGN to the provided bank account
  4. Sends a payouts.processing webhook as it starts sending to the settlement rail, then a payouts.withdrawal.success webhook to your callback_url when completed

Handling quote expiry, underpayment, or failure

If the user sends less than deposit_amount, the deposit is refused, except for a shortfall of up to 0.0001 on stablecoins. Bitcoin has no tolerance. The payout doesn’t process and later expires, and the funds stay in your Bitnob balance. Show the exact amount, and tell the user their network fee is on top of it. If no deposit is received before expiry (16 min), Bitnob cancels the payout and sends a payouts.withdrawal.expired webhook. If a withdrawal fails (e.g., due to an invalid account), the payout record moves to FAILED and a payouts.withdrawal.failed webhook is sent. You can also poll Get Payout by ID to detect it.
Always listen for webhooks to track transaction outcomes.

Best practices

Always display deposit_amount and the chain to the user. Poll Get Payout by ID if you don’t implement webhooks yet. Use a unique reference per payout. This is your trace ID. Store the quote_id, reference, beneficiary, and address in your database for future reconciliation.

What this flow enables

You now have a programmable way to:
  • Receive USDT from anywhere in the world
  • Convert it automatically
  • Deliver it in local fiat to a verified bank account
  • Handle all messaging via webhooks

This is ideal for:

  • Remittance apps
  • Pay suppliers or gig workers in Nigeria
  • Crypto liquidation from global wallets

Next

Failure scenarios

Where this flow breaks, and what to do.

Reconciliation and ledger integrity

Keep both ledgers in agreement.