Skip to main content

Overview

Throwaway Merchant Balance onramps create short-lived NGN virtual accounts (25-minute TTL) that convert deposits to USD and credit your merchant’s internal Daya balance instead of sending funds on-chain immediately.
This type is ideal for aggregating deposits before making batch withdrawals to reduce on-chain fees.

Use Cases

Batch Withdrawals

Aggregate multiple small deposits before withdrawing

Reduced Gas Fees

Make fewer, larger on-chain transactions

Flexible Timing

Withdraw later when gas fees are lower

Internal Accounting

Track balances before external settlement

Characteristics

PropertyValueDescription
TTL25 minutesVirtual account expires after 25 minutes
FX RateLocked to rate_idGuaranteed rate within validity window
VA ReuseNoVA number not reused for 365 days
Rate GuaranteeYesFirm quote honored
SettlementMERCHANT_BALANCECredited to internal USD balance
DestinationN/ANo on-chain address needed

FX Behavior

Similar to Type B1 (Auto-Withdraw), the onramp locks to a specific rate_id:
Unlike auto-withdraw, settlement is instant (no on-chain wait time). Funds are immediately available in your Daya balance.

Settlement Configuration

No destination address required:
{
  "settlement": {
    "mode": "MERCHANT_BALANCE"
  }
}
The deposit converts to USD equivalent and credits your internal balance. You initiate withdrawals separately via the balance management API.

Creating a Throwaway Merchant Balance Onramp

Step 1: Get Rate

curl --request GET \
  --url 'https://api.daya.xyz/v1/rates?from=NGN&to=USDC' \
  --header 'Authorization: Bearer YOUR_API_KEY'

Step 2: Create Onramp

curl --request POST \
  --url https://api.daya.xyz/v1/onramp \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "type": "THROWAWAY",
    "user": {
      "email": "[email protected]"
    },
    "rate_id": "rate_8x7k2mq9p",
    "settlement": {
      "mode": "MERCHANT_BALANCE"
    }
  }'
Response:
{
  "onramp_id": "onramp_7k3m5n8q",
  "type": "THROWAWAY",
  "status": "ACTIVE",
  "rate_id": "rate_8x7k2mq9p",
  "payment_reference": "DAYA-7K3M5N8Q",
  "virtual_account": {
    "account_number": "1122334455",
    "account_name": "Daya - [email protected]",
    "bank_name": "Wema Bank",
    "bank_code": "035"
  },
  "expires_at": "2026-01-14T15:30:00Z",
  "settlement": {
    "mode": "MERCHANT_BALANCE"
  },
  "created_at": "2026-01-14T15:05:12Z"
}

User Experience

Display to users:

Complete Your Payment

Guaranteed rate: 1 USDC = 1545.50 NGN

Transfer NGN to:

Bank:Wema Bank
Account Number:1122334455
Account Name:Daya - [email protected]
Reference:DAYA-7K3M5N8Q

⏰ Complete within 25 minutes

Funds will be credited to your account balance instantly

Deposit Flow

Happy path:
1

User transfers NGN

User sends NGN to virtual account within 25 minutes
2

Deposit detected

Status: PENDING_FXWebhook: deposit.created
3

FX executed

NGN converted to USD at locked rateUSD credited to merchant’s internal balanceStatus: SETTLED (immediately—no on-chain wait)Webhook: deposit.settled
Duration: Typically 1-2 minutes (faster than auto-withdraw because no on-chain settlement).
The deposit is SETTLED as soon as FX executes and balance is credited. No pending withdrawal state.

Lifecycle

Same as Type B1, but deposits settle faster because no on-chain confirmation is needed.

Merchant Balance Management

Checking Balance

Query your merchant balance:
GET /v1/merchant/balance
Response:
{
  "merchant_id": "merch_abc123",
  "balances": {
    "usd_available": "1250.00",
    "usd_pending_withdrawal": "0.00"
  },
  "updated_at": "2026-01-14T15:35:00Z"
}

Withdrawing from Balance

Initiate a withdrawal from your balance:
POST /v1/merchant/withdraw
Request:
{
  "amount": "1000.00",
  "asset": "USDC",
  "chain": "BASE",
  "destination_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
}
Withdrawal APIs are covered in the merchant balance management documentation (future release).

When to Use

  • Processing many small deposits (< $10 each)
  • Want to minimize on-chain fees
  • Need flexibility in withdrawal timing
  • Want to aggregate before withdrawing
  • Building internal accounting before external settlement
  • Withdrawing during low gas fee periods

Comparison with Auto-Withdraw

FeatureMerchant BalanceAuto-Withdraw
Settlement speed1-2 mins2-5 mins
On-chain txNone (until withdrawal)Immediate
Gas feesBatch-optimizedPer-deposit
DestinationLater (flexible)Fixed at creation
Status flowPENDING_FX → SETTLEDPENDING_FX → PENDING_WITHDRAWAL → SETTLED
Use caseAggregationDirect payment

Gas Fee Savings Example

Scenario: 100 users each deposit $5
ApproachOn-chain TxsGas Cost (Est.)
Auto-Withdraw100 txs50(100×50 (100 × 0.50)
Merchant Balance1 tx (batch withdrawal)$0.50
Savings: $49.50 (99% reduction)
Use Merchant Balance mode for high-volume, low-value transactions to dramatically reduce on-chain fees.

Late Deposit Handling

Same as Type B1:
  • Deposits after 25-minute expiry are FLAGGED
  • Deposits after rate_id expiry are FLAGGED
  • Manual operations review required for flagged deposits

Limits

Subject to standard limits:
  • Per-onramp: Max $1,000 per deposit
  • Per-merchant daily: Max $10,000
  • System-wide daily: Max $100,000
See Limits & Risk for details.

Best Practices

Withdraw from balance when it reaches a certain threshold (e.g., $1,000) to optimize gas fees.
async function checkAndWithdraw() {
  const balance = await getBalance();
  if (balance.usd_available >= 1000) {
    await initiateWithdrawal(balance.usd_available);
  }
}
Set up alerts when balance exceeds thresholds or is low.
Schedule withdrawals during off-peak hours when gas fees are lower.
Maintain records of which deposits contribute to your balance for reconciliation.
Apps processing 100+ deposits/day benefit most from this mode.

Accounting & Reconciliation

Merchant balance uses double-entry ledger accounting: When deposit settles:
Debit:  clearing:ngn:unallocated
Credit: merchant:{merchant_id}:usd:available
When withdrawal initiated:
Debit:  merchant:{merchant_id}:usd:available
Credit: merchant:{merchant_id}:usd:pending_withdrawal
When withdrawal completes:
Debit:  merchant:{merchant_id}:usd:pending_withdrawal
Credit: treasury:usd:onchain
Ledger details are internal but ensure atomic operations and prevent double-spending.

Error Scenarios

Scenario: Attempting to withdraw more than availableError:
{
  "error": {
    "code": "insufficient_balance",
    "message": "Available balance ($500) is less than requested amount ($1000)"
  }
}

Next Steps