What you are integrating
Coins lets your business offer digital-asset discovery, trades, balances, deposits, and withdrawals through the Daya API. Your Daya API key acts on your business’s Coins account. Daya records the aggregate Coins balance and orders. Your application records which customer owns each part of that balance.Start here
The current Coins authentication guide says Coins is live-only. Do not use a sandbox key or send test payments to a live deposit account.
Verified public contract
The Coins service mounts these actions underhttps://api.daya.co/coins/v1. Scopes are independent, so grant every scope a server process actually needs.
Webhook destinations are managed in the Daya Dashboard; the Coins API-key surface does not expose webhook-configuration routes.
Account verification and capability checks
The API key acts as one Daya Coins account. Verification belongs to the account behind that key. KYC completed on another account does not change this account’s capabilities. The current Coins service applies these checks:
Complete KYC through the Coins account onboarding flow. Do not send identity documents to the public trading endpoints. A permitted action can still be unavailable because of account status, a withdrawal pause, insufficient balance, unsupported asset or chain, or another runtime control.
The public Coins order does not carry an end-customer ID. This account-level KYC check is not a KYC check for each customer in your product. Keep your own customer identity and compliance process for the users whose funds you allocate in your ledger.
Funding and balance ownership
UseGET /coins/v1/fiat-deposits/options for available bank-transfer instructions. Display bank details only when the returned account.status is active. Do not accept a transfer to an account with status: disabled.
Use GET /coins/v1/crypto-deposits/options for supported crypto assets, chains, addresses, and minimums. Show the returned caid and contract_address when present; for a native asset, show its returned native-asset identifier. A symbol and chain alone do not identify a token when multiple contracts share a symbol. Do not infer a deposit address or token contract from another Daya product.
After a completed deposit, verify both the transaction and the balance that corresponds to the funding rail. GET /coins/v1/balance is the USD cash position. A crypto deposit is held under its credited asset and must be checked with GET /coins/v1/wallet/{caid} or GET /coins/v1/wallet/portfolio. Do not treat an unrelated USD balance as proof that a crypto deposit arrived.
The public Coins trade request has no customer identifier. Your business must authorize the customer in its own product, keep a customer-level ledger, and link its internal operation ID to the returned Daya IDs. The deposit options belong to the Coins account; an account-level address alone does not tell you which of your customers sent funds. Use a customer-attribution method that you can reconcile before you credit that customer. Do not create one Daya API key per end user to simulate customer ownership.
Trade safely
Read the asset catalog before you show an asset. Coins identifies an onchain asset by its chain and contract or native asset ID. Chain availability and token eligibility can change; a token visible on one chain is not interchangeable with the same symbol on another. UseGET /coins/v1/by-contract when a customer brings a contract address. The asset and trade concepts explain the identifiers.
Before offering a trade, require the current asset response to have tradable: true. For a buy, also require buy_enabled: true; for a sell, require sell_enabled: true. Recheck these fields before requesting a quote because migration, pause, or asset controls can change them after the customer first views the asset.
Create and save one Idempotency-Key for each logical order. Reuse that key if the request times out. Do not create a second order because the first response was delayed. A quote is short-lived; if it expires or was consumed, request a new quote and make a new logical order. Do not credit the bought asset from a pending response.
Withdrawals and cash-out
Coins has separate crypto and fiat withdrawal flows. A crypto withdrawal needs a supported asset, saved destination address, and fee estimate. A fiat withdrawal needs Tier 2, a USD-to-NGN FX quote, and a saved bank account. Read the Coins concepts and endpoint reference before implementing either flow. Both create routes needcoins:withdraw; managing saved destinations needs coins:write.
Create and retain one Idempotency-Key for each logical withdrawal. If POST /crypto-withdrawals or POST /fiat-withdrawals times out before returning an ID, replay the exact request with the same key. Do not generate a new key for that retry; a new key can create a second money movement.
Withdrawal creation can be disabled even when read endpoints work. If the API returns 503 WITHDRAWALS_DISABLED, do not retry in a loop or present the withdrawal as submitted. Ask Daya to confirm when the capability is enabled for your account.
Webhooks, recovery, and launch checks
Configure a signed HTTPS webhook in the Daya Dashboard. Verify the signature, deduplicate by event ID, and process the event asynchronously. Keep polling and a reconciliation job as fallbacks. Webhook verification has the signing rules. Before launch, check that you can:- Authenticate with only the scopes each server process needs.
- Complete Tier 1 before NGN funding and Tier 2 before fiat withdrawal.
- Receive a deposit into the Coins account and match it to the correct customer.
- Place one order, handle a timeout without a duplicate, and wait for its final state.
- Handle an expired quote, insufficient balance, a failed order, and a delayed webhook.
- Reconcile the sum of customer allocations with the Coins account.
- Confirm asset, chain, and withdrawal availability with Daya instead of assuming every documented option is live.