Skip to main content

Overview

Convert cryptocurrency to fiat currency with real-time quotes and seamless bank transfers. This guide covers getting exchange rates and initiating offramp transactions. What you’ll learn:
  • Get exchange quotes
  • Initiate crypto-to-fiat swaps
  • Understand deposit addresses
  • Monitor swap progress
  • Handle different scenarios

Exchange Process

1

Get Quote

Check current exchange rate for your crypto amount
2

Verify Bank Account

Confirm recipient bank details
3

Initiate Swap

Create offramp order with bank details
4

Deposit Crypto

Send crypto to the provided deposit address
5

Receive Fiat

Fiat sent to your bank account

Get Exchange Quote

Get real-time exchange rate before initiating a swap.
import MoneiSDK from 'monei-sdk';

const monei = new MoneiSDK({
  apiKey: process.env.MONEI_API_KEY,
});

// Get quote for 100 USDT to NGN
const quote = await monei.offrampExchange.getQuote({
  token: 'USDT',
  network: 'base',
  amount: 100,
  fiat: 'NGN'
});

console.log('Exchange Quote:');
console.log('================');
console.log('Token:', quote.token);
console.log('Amount:', quote.amount, quote.token);
console.log('Network:', quote.network);
console.log('Fiat Currency:', quote.fiat);
console.log('Exchange Rate:', quote.rate, 'NGN per', quote.token);
console.log('You will receive:', quote.amount * quote.rate, 'NGN');
Query Parameters:
ParameterTypeRequiredDescription
tokenstringYesToken symbol (USDT, USDC, CNGN)
networkstringYesNetwork (base, polygon, arbitrum, etc.)
amountnumberYesAmount of crypto to convert
fiatstringNoFiat currency (NGN, GHS, KES, USD) - defaults to NGN
Response:
{
  "token": "USDT",
  "amount": 100,
  "network": "base",
  "fiat": "NGN",
  "rate": 1550.25
}

Supported Tokens & Networks

Tether USD
NetworkStatus
Polygon✓ Supported
Arbitrum One✓ Supported
BNB Smart Chain✓ Supported
Ethereum✓ Supported
Tron✓ Supported
Lisk✓ Supported
Celo✓ Supported
Most Popular: BNB Smart Chain, Polygon (lowest fees)

Initiate Swap

Create an offramp order to convert crypto to fiat.
// Initiate swap: 100 USDT → NGN
const order = await monei.offrampExchange.initiateSwap({
  amount: 100,
  token: 'USDT',
  network: 'base',
  fiatCurrency: 'NGN',
  bankCode: 'GTBINGLA', // GTBank
  accountNumber: '0123456789',
  accountName: 'JOHN DOE'
});

console.log('Offramp Order Created:');
console.log('======================');
console.log('Reference:', order.reference);
console.log('Status:', order.status);
console.log('Amount:', order.amount, order.token);
console.log('Fiat Amount:', order.fiatAmount, order.fiatCurrency);
console.log('\nDeposit Details:');
console.log('Network:', order.onChain.network);
console.log('Address:', order.onChain.depositAddress);
console.log('Expected Amount:', order.onChain.expectedAmount);
console.log('\nBank Details:');
console.log('Bank:', order.bankDetails.bankName);
console.log('Account:', order.bankDetails.accountNumber);
console.log('Account Name:', order.bankDetails.accountName);
console.log('\nNext Step:');
console.log(`Send exactly ${order.onChain.expectedAmount} ${order.token} to:`);
console.log(order.onChain.depositAddress);
Request Body:
FieldTypeRequiredDescription
amountnumberYesAmount of crypto to swap
tokenstringYesToken symbol (USDT, USDC, CNGN)
networkstringYesBlockchain network
fiatCurrencystringYesFiat currency (NGN, GHS, KES, USD)
bankCodestringYesRecipient bank code
accountNumberstringYesRecipient account number
accountNamestringYesRecipient account name
Response:
{
  "statusCode": 200,
  "message": "Swap initiated successfully",
  "data": {
    "reference": "OFFRAMP-ABC123XYZ",
    "status": "awaiting_deposit",
    "amount": 100,
    "token": "USDT",
    "network": "base",
    "fiatCurrency": "NGN",
    "fiatAmount": 155025,
    "exchangeRate": 1550.25,
    "onChain": {
      "network": "base",
      "depositAddress": "0x1234567890abcdef1234567890abcdef12345678",
      "expectedAmount": 100,
      "tokenContract": "0x...",
      "expiresAt": "2024-02-15T12:00:00Z"
    },
    "bankDetails": {
      "bankCode": "GTBINGLA",
      "bankName": "Guaranty Trust Bank",
      "accountNumber": "0123456789",
      "accountName": "JOHN DOE"
    },
    "createdAt": "2024-02-15T11:30:00Z",
    "expiresAt": "2024-02-15T12:00:00Z"
  }
}

Complete Offramp Flow

async function completeOfframp() {
  // 1. Get quote
  console.log('Step 1: Getting quote...');
  const quote = await monei.offrampExchange.getQuote({
    token: 'USDT',
    network: 'base',
    amount: 100,
    fiat: 'NGN'
  });
  
  console.log(`Rate: ${quote.rate} NGN per USDT`);
  console.log(`You will receive: ₦${(quote.amount * quote.rate).toLocaleString()}`);
  
  // 2. Verify bank account
  console.log('\nStep 2: Verifying bank account...');
  const verification = await monei.offrampPayouts.verifyBankAccount({
    bankCode: 'GTBINGLA',
    accountNumber: '0123456789'
  });
  
  console.log(`Account Name: ${verification.accountName}`);
  
  // 3. Initiate swap
  console.log('\nStep 3: Initiating swap...');
  const order = await monei.offrampExchange.initiateSwap({
    amount: 100,
    token: 'USDT',
    network: 'base',
    fiatCurrency: 'NGN',
    bankCode: verification.bankCode,
    accountNumber: verification.accountNumber,
    accountName: verification.accountName
  });
  
  console.log(`\n✓ Order created: ${order.reference}`);
  console.log(`Status: ${order.status}`);
  console.log(`\nDeposit Address: ${order.onChain.depositAddress}`);
  console.log(`Amount to send: ${order.onChain.expectedAmount} USDT`);
  console.log(`Network: ${order.onChain.network}`);
  console.log(`Expires: ${new Date(order.expiresAt).toLocaleString()}`);
  
  // 4. Send crypto (user does this manually or via SDK)
  console.log('\n⚠️ IMPORTANT: Send crypto to deposit address');
  console.log('After sending, track status using order.reference');
  
  return order;
}

// Execute
const order = await completeOfframp();

Deposit Address

Each offramp order generates a unique deposit address. Important Notes:
Each order has a unique deposit address. Do not reuse addresses from previous transactions.
Deposit addresses expire (typically 30 minutes). Send crypto before expiration.
Send the exact expected amount. Partial or excess amounts may delay processing.
Ensure you send on the correct network (Base, Polygon, etc.). Wrong network = lost funds.
Each address is for one transaction only. Multiple deposits to same address won’t be processed.

Exchange Rates

Rates update in real-time based on market conditions.
// Compare rates across networks
async function compareNetworks(amount) {
  const networks = ['base', 'polygon', 'arbitrum', 'bsc'];
  const quotes = [];
  
  for (const network of networks) {
    const quote = await monei.offrampExchange.getQuote({
      token: 'USDT',
      network: network,
      amount: amount,
      fiat: 'NGN'
    });
    
    quotes.push({
      network: network,
      rate: quote.rate,
      fiatAmount: amount * quote.rate
    });
  }
  
  // Sort by best rate
  quotes.sort((a, b) => b.rate - a.rate);
  
  console.log(`Best Rates for ${amount} USDT → NGN:\n`);
  quotes.forEach((q, i) => {
    console.log(`${i + 1}. ${q.network}:`);
    console.log(`   Rate: ${q.rate} NGN/USDT`);
    console.log(`   You get: ₦${q.fiatAmount.toLocaleString()}\n`);
  });
  
  return quotes[0]; // Best rate
}

// Find best network
const best = await compareNetworks(100);
console.log(`Best network: ${best.network}`);

Best Practices

Get Fresh Quotes

Rates change. Get new quote before each transaction

Verify Before Swap

Always verify bank account before initiating

Send Exact Amount

Send exactly the expected amount to avoid delays

Correct Network

Double-check network before sending crypto

Track Order

Save reference number and monitor progress

Act Quickly

Send crypto before deposit address expires

Troubleshooting

Error: Failed to create offramp orderCommon causes:
  • Invalid bank details
  • Unsupported token/network
  • Amount below minimum ($10)
  • Amount above limit
  • KYC not completed
Solution:
  • Verify all parameters
  • Check supported tokens/networks
  • Ensure amount is within limits
  • Complete KYC verification
Problem: Deposit address expired before sending cryptoSolution:
  • Create new offramp order
  • Get new deposit address
  • Send crypto promptly (within 30 min)
  • Set reminder to send quickly
Problem: Sent more or less than expected amountIf less:
  • Order may be cancelled
  • Crypto refunded (minus gas)
If more:
  • Excess may be refunded
  • Contact support
Prevention:
  • Copy exact amount from order
  • Double-check before sending
Error: Sent crypto on wrong networkExample: Sent USDT on Ethereum instead of BaseSolution:
  • Contact support immediately
  • Provide transaction hash
  • May require manual recovery (fees apply)
Prevention:
  • Verify network in wallet before sending
  • Check deposit address network

Next Steps

Overview

Learn offramp basics

Bank Verification

Verify bank accounts

Tracking

Monitor transaction progress

Networks

Learn about blockchain networks