Skip to main content
POST
https://api.daya.xyz
/
v1
/
onramp
POST /v1/onramp
curl --request POST \
  --url https://api.daya.xyz/v1/onramp \
  --header 'Authorization: <authorization>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "type": "<string>",
  "user": {
    "user.email": "<string>"
  },
  "rate_id": "<string>",
  "settlement": {
    "settlement.mode": "<string>",
    "settlement.asset": "<string>",
    "settlement.chain": "<string>",
    "settlement.destination_address": "<string>"
  }
}
'
{
  "onramp_id": "onramp_3j5k8n2q",
  "type": "THROWAWAY",
  "status": "ACTIVE",
  "rate_id": "rate_8x7k2mq9p",
  "payment_reference": "DAYA-3J5K8N2Q",
  "virtual_account": {
    "account_number": "9876543210",
    "account_name": "Daya - [email protected]",
    "bank_name": "Wema Bank",
    "bank_code": "035"
  },
  "expires_at": "2026-01-14T15:30:00Z",
  "settlement": {
    "mode": "AUTO_WITHDRAW",
    "asset": "USDC",
    "chain": "BASE",
    "destination_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
  },
  "created_at": "2026-01-14T15:05:12Z"
}

Overview

Create an onramp (deposit configuration) that generates a virtual NGN bank account for receiving deposits. Onramps can be permanent (long-lived) or throwaway (ephemeral with 25-minute TTL).

Authentication

Authorization
string
required
Bearer token with your API key
Authorization: Bearer YOUR_API_KEY

Request Body

type
string
required
Onramp typeAllowed values: THROWAWAY, PERMANENT
  • THROWAWAY: Short-lived VA (25 minutes), locked to rate_id
  • PERMANENT: Long-lived VA, uses current rate at settlement
user
object
required
End-user information
rate_id
string
required
Rate identifier from GET /v1/ratesExample: rate_8x7k2mq9p
For throwaway onramps, this rate is locked. For permanent onramps, it’s informational only.
settlement
object
required
Settlement configuration

Request Examples

{
  "type": "THROWAWAY",
  "user": {
    "email": "[email protected]"
  },
  "rate_id": "rate_8x7k2mq9p",
  "settlement": {
    "mode": "AUTO_WITHDRAW",
    "asset": "USDC",
    "chain": "BASE",
    "destination_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
  }
}

Response

onramp_id
string
required
Unique identifier for this onrampExample: onramp_3j5k8n2q
type
string
required
Onramp type: THROWAWAY or PERMANENT
status
string
required
Current onramp statusValues: ACTIVE, EXPIRED, DISABLED, FLAGGEDNew onramps start as ACTIVE
rate_id
string
required
Associated rate identifier
payment_reference
string
required
Unique payment reference for user to include when transferringExample: DAYA-3J5K8N2Q
This reference is globally unique and helps route deposits to the correct onramp.
virtual_account
object
required
NGN bank account details for receiving deposits
expires_at
string
When onramp expires (ISO 8601 timestamp)Example: 2026-01-14T15:30:00Z
  • For throwaway onramps: ~25 minutes from creation
  • For permanent onramps: null (no expiry)
settlement
object
required
Settlement configuration (same as request)
created_at
string
required
When onramp was created (ISO 8601 timestamp)

Success Response

{
  "onramp_id": "onramp_3j5k8n2q",
  "type": "THROWAWAY",
  "status": "ACTIVE",
  "rate_id": "rate_8x7k2mq9p",
  "payment_reference": "DAYA-3J5K8N2Q",
  "virtual_account": {
    "account_number": "9876543210",
    "account_name": "Daya - [email protected]",
    "bank_name": "Wema Bank",
    "bank_code": "035"
  },
  "expires_at": "2026-01-14T15:30:00Z",
  "settlement": {
    "mode": "AUTO_WITHDRAW",
    "asset": "USDC",
    "chain": "BASE",
    "destination_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
  },
  "created_at": "2026-01-14T15:05:12Z"
}

Error Responses

{
  "error": {
    "code": "rate_expired",
    "message": "The specified rate_id has expired",
    "details": "Request a new rate via GET /v1/rates"
  }
}

Validation Rules

  • rate_id must exist
  • rate_id must not be expired
  • For throwaway onramps, rate_id.expires_at must be ≥ now + 25 minutes
AUTO_WITHDRAW mode:
  • asset, chain, and destination_address are required
  • destination_address must be valid for specified chain
MERCHANT_BALANCE mode:
  • Only mode is required
  • asset, chain, destination_address are not allowed
user.email must be a valid email format
  • Max 1,000 onramps per day per merchant
  • Exceeding this auto-freezes merchant account

Best Practices

1

Get fresh rate before creation

Always call GET /v1/rates immediately before POST /v1/onramp to ensure maximum validity window.
2

Validate destination address

Use a blockchain library to validate addresses before submitting:
import { isAddress } from 'ethers';

if (!isAddress(destinationAddress)) {
  throw new Error('Invalid Ethereum address');
}
3

Store onramp_id

Link onramp_id to your user records for easy lookup and support.
4

Display virtual account details

Show VA details clearly to users with countdown timer (for throwaway onramps).
5

Handle rate expiry errors gracefully

If rate_expired error occurs, automatically request a fresh rate and retry.

Rate Limits

  • 1,000 onramp creations per day per merchant
  • Exceeding triggers automatic merchant freeze and email to operations
  • 100 API requests per minute per key

Immutability

Once created, onramp settlement configuration is immutable. You cannot change:
  • Settlement mode
  • Destination address
  • Asset or chain
To change these, create a new onramp.

Next Steps