Skip to main content
GET
/
v1
/
rates
Retrieve rates
curl --request GET \
  --url https://api.daya.co/v1/rates \
  --header 'X-Api-Key: <x-api-key>'
{
  "rate_id": "rate_8x7k2mq9p",
  "from": "NGN",
  "to": "USDC",
  "side": "BUY",
  "rate": 1545.50,
  "inverse_rate": 0.000647,
  "fee_bps": 50,
  "min_deposit_ngn": 1500.00,
  "created_at": "2026-01-14T15:05:00Z",
  "expires_at": "2026-01-14T15:35:00Z"
}

Overview

Request firm FX quotes with guaranteed exchange rates. Each rate has a ~30-minute validity window and is identified by a unique rate_id.

Authentication

X-Api-Key
string
required
Your merchant API key
X-Api-Key: YOUR_API_KEY

Query Parameters

from
string
required
Source currency. Currently only NGN is supported.Allowed values: NGN
to
string
required
Destination currency.Allowed values: USDC, USDT, USD
USD is treated as equivalent to USDC/USDT in v0.1. Depeg scenarios are not handled.
side
string
required
Rate side. Determines whether the quote is for buying or selling crypto.Allowed values: BUY, SELL
  • BUY — Merchant is buying crypto (NGN deposits → stablecoin). Use for NGN funding accounts that settle onchain.
  • SELL — Merchant is selling crypto (stablecoin → NGN). Use for crypto funding accounts that settle to an NGN bank account.

Request Examples

curl --request GET \
  --url 'https://api.daya.co/v1/rates?from=NGN&to=USDC&side=BUY' \
  --header 'X-Api-Key: YOUR_API_KEY'

Response

rate_id
string
required
Unique identifier for this rate snapshot. Use this when creating funding accounts that need a quoted conversion.Example: rate_8x7k2mq9p
from
string
required
Source currencyExample: NGN
to
string
required
Destination currencyExample: USDC
side
string
required
Rate side — BUY or SELLExample: BUY
rate
number
required
Conversion rate from source to destination (e.g., 1 USDC = X NGN)Example: 1545.50
This rate already includes Daya’s spread/fee. You don’t need to calculate fees separately.
inverse_rate
number
required
Inverse conversion rate (e.g., 1 NGN = X USDC)Example: 0.000647
fee_bps
integer
Fee in basis points (1 bps = 0.01%)Example: 50 (0.5%)
min_deposit_ngn
number
required
Minimum NGN deposit amount for this rateExample: 1500.00 (~$1.00)
Deposits below this amount will be rejected with status FAILED.
created_at
string
required
When this rate was generated (ISO 8601 timestamp)Example: 2026-01-14T15:05:00Z
expires_at
string
required
When this rate becomes invalid (ISO 8601 timestamp)Example: 2026-01-14T15:35:00Z
Always check this before using rate_id to create a funding account. Expired rates will be rejected.

Success Response

{
  "rate_id": "rate_8x7k2mq9p",
  "from": "NGN",
  "to": "USDC",
  "side": "BUY",
  "rate": 1545.50,
  "inverse_rate": 0.000647,
  "fee_bps": 50,
  "min_deposit_ngn": 1500.00,
  "created_at": "2026-01-14T15:05:00Z",
  "expires_at": "2026-01-14T15:35:00Z"
}

Error Responses

{
  "error": {
    "code": "missing_parameter",
    "message": "Required parameter 'from' is missing",
    "details": "Query parameter 'from' must be provided"
  }
}

Rate Lifecycle

New rates are generated approximately every 10 minutes and expire after ~30 minutes.
Time    Rate ID         Valid Until
─────────────────────────────────────
15:05   rate_abc123     15:35
15:15   rate_def456     15:45
15:25   rate_ghi789     15:55
15:35   rate_jkl012     16:05
Request a fresh rate immediately before creating each temporary funding account that uses a quoted conversion.

Usage Notes

Rate Guarantee

For temporary funding accounts with a quoted settlement destination, the rate is guaranteed for deposits within the validity window:
  • Funding account created with rate_id at 15:10
  • Rate expires at 15:35
  • Deposit at 15:20 → Uses guaranteed rate ✅
  • Deposit at 15:40 → Flagged (expired) ❌

Caching Rates

You can cache rates client-side but must respect expires_at:
class RateCache {
  constructor() {
    this.rate = null;
  }
  
  async getValidRate() {
    if (!this.rate || new Date() >= new Date(this.rate.expires_at)) {
      const response = await fetch('https://api.daya.co/v1/rates?from=NGN');
      this.rate = await response.json();
    }
    return this.rate;
  }
}

Checking Time Remaining

Calculate remaining validity time:
function getSecondsRemaining(expiresAt) {
  const now = new Date();
  const expiry = new Date(expiresAt);
  return Math.max(0, (expiry - now) / 1000);
}

const rate = await getRates();
const remaining = getSecondsRemaining(rate.expires_at);
console.log(`Rate valid for ${remaining} seconds`);

Rate Calculation

The displayed rate includes Daya’s fee:
Displayed Rate = Market Rate × (1 - fee_bps / 10000)
Example:
  • Market rate: 1550 NGN/USDC
  • Fee: 50 bps (0.5%)
  • Displayed rate: 1550 × (1 - 0.005) = 1545.50 NGN/USDC

Common Patterns

Recommended flow:
  1. Call GET /v1/rates
  2. Display rate to user
  3. User confirms
  4. Call POST /v1/funding-accounts with rate_id
async function createFundingAccountWithRate(customerId, destinationAddress) {
  // Step 1: Get current rate
  const rate = await getRates();
  
  // Step 2: Show to user (await confirmation)
  await showRateToUser(rate);
  
  // Step 3: Create funding account with rate_id
  const fundingAccount = await createFundingAccount({
    type: 'TEMPORARY',
    rail: 'NGN_VIRTUAL_ACCOUNT',
    customer: { customer_id: customerId },
    currency: 'NGN',
    amount: 50000,
    settlement_destination: {
      type: 'ONCHAIN',
      rate_id: rate.rate_id,
      destination_asset: 'USDC',
      destination_chain: 'BASE',
      destination_address: destinationAddress
    }
  });
  
  return fundingAccount;
}
If FX venue is down, gracefully handle rate_unavailable error:
async function getRatesWithRetry(maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch('https://api.daya.co/v1/rates?from=NGN');
      if (response.status === 503) {
        await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5s
        continue;
      }
      return await response.json();
    } catch (error) {
      if (i === maxRetries - 1) throw error;
    }
  }
  throw new Error('Rates unavailable after retries');
}

Rate Limits

  • 100 requests per minute per API key
  • No specific rate limit on this endpoint (non-mutating)

Next Steps

Create Funding Account

Use the rate_id to create a funding account

Rates Concept

Learn more about rate semantics