What is a Deposit?
A deposit represents a single NGN bank transfer into an onramp’s virtual account. It is the upstream event that triggers FX conversion and settlement.A deposit is not the on-chain transaction—it’s the NGN inflow. The on-chain withdrawal (if applicable) happens after FX conversion.
Deposit Properties
| Property | Description | Example |
|---|---|---|
deposit_id | Unique identifier | dep_9x2k5m8p |
onramp_id | Parent onramp | onramp_3j5k8n2q |
merchant_id | Owner (inferred) | merch_abc123 |
user_email | End-user email | [email protected] |
payment_reference | Daya-generated reference | DAYA-3J5K8N2Q |
amount_ngn | NGN amount received | 15000.00 |
bank_reference | Bank’s transaction reference | FLW-REF-123456 |
rate_id | FX rate used | rate_8x7k2mq9p |
amount_asset | Asset amount after conversion | 9.70 |
asset | Asset type | USDC, USDT |
chain | Blockchain network | BASE, ETH, etc. |
tx_hash | On-chain transaction hash | 0x8f3e2d... |
status | Current state | See Deposit Statuses |
failure_reason | Why deposit failed (if applicable) | "Rate expired" |
flag_reason | Why flagged (if applicable) | "Deposit after expiry" |
created_at | When deposit received | 2026-01-14T15:06:30Z |
settled_at | When fully settled | 2026-01-14T15:08:15Z |
updated_at | Last status change | 2026-01-14T15:08:15Z |
Bank sender details (
sender_name, sender_account, sender_bank) are captured internally but not exposed via API in v0.1.Deposit Statuses
| Status | Description | Terminal? | Merchant Action Required? |
|---|---|---|---|
PENDING_FX | NGN received, awaiting FX execution | ❌ No | ❌ No |
PENDING_WITHDRAWAL | FX done, waiting for on-chain confirmation | ❌ No | ❌ No |
SETTLED | Fully complete (on-chain or balance credit) | ✅ Yes | ❌ No |
FAILED | Permanent failure | ✅ Yes | ✅ Contact support |
FLAGGED | Held for manual review | ✅ Yes | ✅ Contact support |
REVERSED | Bank reversed the transfer | ✅ Yes | ❌ No |
Terminal vs Non-Terminal States
Non-terminal states (in-progress):PENDING_FX→ FX conversion in progressPENDING_WITHDRAWAL→ On-chain broadcast in progress
SETTLED→ SuccessFAILED→ Permanent failureFLAGGED→ Requires manual ops reviewREVERSED→ Bank reversed the original transfer
Deposit Lifecycle
Lifecycle Stages
- 1. PENDING_FX
- 2. PENDING_WITHDRAWAL
- 3. SETTLED
- 4. FAILED
- 5. FLAGGED
- 6. REVERSED
NGN deposit received, FX not yet executedTriggers:
- Bank transfer lands in virtual account
- Webhook from payment provider received
- Validate deposit is within onramp TTL and rate expiry
- Check limits (per-onramp, per-merchant, system-wide)
- Execute FX conversion
deposit.createdIdempotency
Duplicate bank transfers with the samebank_reference create only one deposit record.
Why?
- Banks may send duplicate webhooks
- User may accidentally transfer twice to same VA
- Payment provider may retry notifications
bank_reference maps to exactly one deposit_id.
Querying Deposits
List Deposits
Retrieve deposits with optional filters:| Parameter | Description | Example |
|---|---|---|
onramp_id | Filter by onramp | onramp_3j5k8n2q |
status | Filter by status | SETTLED, PENDING_FX |
from | Start date (ISO 8601) | 2026-01-01T00:00:00Z |
to | End date (ISO 8601) | 2026-01-31T23:59:59Z |
page | Page number | 1 |
per_page | Results per page | 20 (max 100) |
Get Single Deposit
Retrieve specific deposit by ID:Example Responses
Atomicity Guarantees
FX conversion and settlement are atomic:- Either: Both FX and settlement succeed →
SETTLED - Or: One or both fail →
FAILEDorFLAGGED
Common Deposit Flows
- Happy Path (Auto-Withdraw)
- Happy Path (Merchant Balance)
- Late Deposit (Flagged)
- Limit Exceeded (Flagged)
- User transfers 15,000 NGN to virtual account
- Deposit created:
PENDING_FX - FX executed: 15,000 NGN → 9.70 USDC
- Risk engine approves withdrawal
- Status →
PENDING_WITHDRAWAL - On-chain transaction broadcast to BASE
- Transaction confirms
- Status →
SETTLED - Webhook:
deposit.settled
Merchant-Visible Fields Only
The following fields are captured internally but not exposed via API:sender_name(bank sender’s name)sender_account(sender’s account number)sender_bank(sender’s bank code)- Internal risk scores
- Detailed risk engine decision logs
If you need sender details for support or compliance, contact Daya operations with the
deposit_id.Best Practices
1
Use webhooks, not polling
Set up webhooks for real-time updates instead of polling
GET /v1/deposits.2
Handle all terminal states
Your application should gracefully handle
SETTLED, FAILED, FLAGGED, and REVERSED.3
Store deposit_id with user records
Link
deposit_id to your user’s transaction history for easy lookup.4
Implement idempotency in webhooks
Use
event_id or deposit_id to deduplicate webhook deliveries.5
Show tx_hash to users
Display
tx_hash (if available) so users can verify on-chain settlement on block explorers.