On-Ramp: Fiat → Crypto

Step-by-step guide to integrating fiat-to-crypto on-ramp transactions.

The on-ramp flow lets your users pay with local fiat currency and receive cryptocurrency in their wallet. IvoryPay handles the payment collection, conversion, and crypto payout automatically.

How it works

1. Your server calls POST /v1/onramp with user and transaction details
2. IvoryPay returns a virtual bank account (or checkout URL) for the user to pay into
3. The user transfers fiat to the provided account
4. IvoryPay detects the payment → webhook: onramp.fiatPaymentReceived
5. IvoryPay converts fiat to crypto and sends it to the wallet address
6. Transaction completes → webhook: onramp.success (or onramp.failed)

Mobile money support

For currencies other than NGN (e.g. UGX, KES, GHS), IvoryPay may return a mobile money checkout URL or USSD prompt instead of a virtual bank account. The user completes payment via their mobile money wallet. The flow and webhooks are identical — only the payment collection method differs.

Integration steps

1

Create the on-ramp transaction

Choose between two initiation methods:

Method
Use when

POST /v1/onramp

You're creating a new customer and transaction in one call

POST /v1/onramp/initiate

The customer already exists in your IvoryPay account

Example: Initiate with customer creation

curl -X POST https://ramp-api.ivorypay.io/api/v1/onramp \
  -H "x-api-key: your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Amina",
    "lastName": "Okafor",
    "email": "amina@example.com",
    "phoneNumber": "+2348012345678",
    "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD68",
    "blockchain": "BSC_MAINNET",
    "reference": "550e8400-e29b-41d4-a716-446655440000",
    "token": "USDT",
    "fiatCurrency": "NGN",
    "fiatAmount": 50000
  }'

Response

{
  "statusCode": 200,
  "success": true,
  "message": "On-ramp initiated successfully",
  "data": {
    "firstName": "Amina",
    "lastName": "Okafor",
    "email": "amina@example.com",
    "refCode": "abc123def4",
    "reference": "550e8400-e29b-41d4-a716-446655440000",
    "transferDetails": {
      "accountName": "IvoryPay - Amina Okafor",
      "accountNumber": "1234567890",
      "bank": "Providus Bank",
      "amountPayable": 50000,
      "expiresAt": "2026-03-26T13:00:00.000Z",
      "currency": "NGN",
      "businessFee": 0,
      "platformFee": 250,
      "gasFee": 0.5,
      "createdAt": "2026-03-26T12:00:00.000Z",
      "checkoutUrl": "https://checkout.ivorypay.io/pay/abc123",
      "cryptoAmount": 31.25
    }
  }
}
2

Collect payment from your user

You have two options:

  1. Redirect to checkout — Send the user to checkoutUrl where IvoryPay handles the payment UI (works for both bank transfers and mobile money)

  2. Display bank details — Show the accountNumber, bank, and amountPayable in your own UI for a bank transfer

circle-exclamation
3

Listen for webhooks

Set up a webhook endpoint to receive real-time updates:

Event
When it fires

onramp.fiatPaymentReceived

User's fiat payment has been detected and confirmed

onramp.cryptoPayoutProcessing

Crypto is being sent to the user's wallet

onramp.success

Crypto has been delivered — transaction complete

onramp.failed

Something went wrong — check failedReason

Example webhook payload: onramp.success

{
  "event": "onramp.success",
  "data": {
    "reference": "550e8400-e29b-41d4-a716-446655440000",
    "amount": 31.25,
    "platformFeeInCrypto": 0.15,
    "businessFeeInCrypto": 0,
    "gasFee": 0.5,
    "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD68",
    "network": "BSC_MAINNET",
    "token": "USDT",
    "transactionHash": "0xabc123...",
    "status": "SUCCESS",
    "customer": {
      "refCode": "abc123def4",
      "email": "amina@example.com",
      "firstName": "Amina",
      "lastName": "Okafor"
    }
  }
}
4

Verify the transaction (optional)

You can also poll for the transaction status:

curl -X GET https://ramp-api.ivorypay.io/api/v1/onramp/status/550e8400-e29b-41d4-a716-446655440000 \
  -H "x-api-key: your_api_key"
5

Specifying amounts and fees

You can specify the transaction amount in either fiat or crypto (not both):

Scenario
Fields to send

User wants to spend 50,000 NGN

"fiatAmount": 50000

User wants to receive exactly 30 USDT

"cryptoAmount": 30

Business fees follow the same rule — specify the fee in the same denomination as the amount:

Use businessFeeInFiat regardless of whether you specify fiatAmount or cryptoAmount.

triangle-exclamation

Minimum amounts

Before initiating, check the minimum on-ramp amount for a currency:

Transaction lifecycle

Frequently asked questions

chevron-rightWhat happens if the payment session expires before the user pays?hashtag

The transaction moves to the EXPIRED status. You will need to create a new on-ramp transaction by calling POST /v1/onramp again. The expiry time is returned in the expiresAt field of the response, so you can display a countdown timer in your UI to prompt the user to pay before the deadline.

chevron-rightWhat if the user sends the wrong fiat amount?hashtag

If the user sends an amount that differs from the expected amountPayable, IvoryPay will still detect and process the payment. The crypto amount delivered will be recalculated based on the actual fiat received. You should listen for the onramp.success webhook and check the final amount field to confirm how much crypto was delivered.

chevron-rightCan I set both fiatAmount and cryptoAmount in the same request?hashtag

No. The API requires you to specify exactly one of fiatAmount or cryptoAmount. If you include both, the request will fail with a validation error. Use fiatAmount when the user wants to spend a specific amount of local currency, and cryptoAmount when the user wants to receive an exact amount of crypto.

chevron-rightHow do I check the minimum on-ramp amount for a given currency?hashtag

Call GET /v1/onramp/minimum-amount/{currency} (e.g., /minimum-amount/NGN) with your API key. The response contains the minimum fiat amount required to initiate an on-ramp transaction in that currency.

chevron-rightWhat does the onramp.failed webhook mean, and how should I handle it?hashtag

The onramp.failed event indicates that the transaction could not be completed. The webhook payload includes a failedReason field explaining the cause. You should notify the user of the failure and, depending on the reason, either retry by creating a new transaction or contact IvoryPay support for assistance.

Last updated