Overview
Payins fund your Zuba balance. These deposit methods are live today:- NGN bank transfers: transfers into your fixed virtual account are credited automatically; dynamic per-deposit virtual accounts are also available via the API.
- EUR & GBP bank transfers: transfers into your dedicated named accounts (EUR IBAN via SEPA, GBP sort code + account number via Faster Payments) are credited automatically.
- USD bank deposits: transfers into your managed USD deposit account are credited automatically.
- XOF & XAF bank transfers: receiving accounts fund your trade-desk orders. Upload evidence only when the returned settlement has
requirements.proofOfPayment: true; other orders reconcile without a proof upload. - Crypto deposits: provision an on-chain address and receive USDC or USDT, credited on confirmation. Live accounts apply a per-transfer minimum, below which a transfer is not credited.
NGN Deposits
Fixed virtual account
Your workspace has a dedicated NGN virtual account in your business name (Zuba {Merchant Name}). Transfers sent to it are credited to your NGN balance automatically. No create call is required. Fetch the details with GET /v1/virtual-accounts/me:
Get My Virtual Account Response
Dynamic virtual accounts (per deposit)
Alternatively, create a deposit withPOST /v1/deposits to receive one-off virtual account details for a specific sender. NGN deposits created this way require the sender’s firstName, lastName, email, and phoneNumber to generate the virtual account:
Create Deposit Response (NGN)
The
iban and bic field names are shared across deposit methods. For NGN
deposits, iban carries the virtual account number and bic carries the
bank name. Display the metadata block to the sender: accountNumber,
accountName, bankName, and expiresAt are the details they need to
complete the transfer before the virtual account expires.EUR & GBP Bank Deposits
Your workspace can be provisioned with dedicated named accounts in your business name: an EUR IBAN reachable over SEPA and a GBP account number + sort code reachable over Faster Payments. Transfers sent to them are credited to the matching balance automatically (no create call is required) and appear as deposits with methodvirtual_account in GET /v1/deposits.
The account details are shown in the dashboard. Contact your account manager to provision named accounts.
USD Bank Deposits
USD deposits settle into a managed deposit account provisioned for your business. Transfers sent to your account details are credited to your USD balance automatically and appear as deposits with methodbank_deposit in GET /v1/deposits. No create call is required. Contact your account manager to provision a USD deposit account.
Requesting an account
Accounts can also be requested over the API withPOST /v1/virtual-accounts, for your own workspace or for a customer account you manage (pass its id in Zuba-Account-Id).
An account can only be opened once the owner has an approved application carrying everything the receiving bank asks for. Those attributes vary by currency and are not all collected during onboarding, so rather than discovering a gap from a failed request, ask first:
Check what is outstanding
Requirements Response
ready. When it is false, each entry names what is outstanding and, in resolution, the exact call that supplies it — already resolved down to the specific person where the value belongs to one. Send those, then request the account.
Read code rather than description: the codes are stable, the prose is not. A requirement whose resolution is null is one no API call sets, either because it is a detail recorded when the application was reviewed or because it is a state of the account or workspace rather than a value. Its description says what clears it.
status distinguishes the cases where nothing is outstanding: ready (the request would succeed), already_exists (the owner already holds an account in this currency, and requesting one returns it), and unavailable (the currency is not offered to this owner, and no value they supply changes that).
The check is read-only and safe to call as often as you like — collecting these from your customer at signup avoids a failed request later.
Crypto Deposits
Provision an on-chain deposit address withPOST /v1/deposits/crypto-address, then send USDC or USDT to it. The deposit is recorded and credited once the transfer confirms on-chain, and appears with method crypto_deposit.
network is a CAIP-2 chain identifier:
Address behaviour:
- Addresses are reused. Omitting
clientRefreturns your single default address for the network; the same call always returns the same address. Pass distinctclientRefvalues (for example, your end-customer IDs) to provision distinct addresses. - The address is asset-agnostic: it receives any supported stablecoin on its network.
- EVM addresses are valid across all EVM chains.
- A
409 Conflictmeans the address for that client/network/reference is frozen or archived and cannot be re-created. Contact support.
Deposit Lifecycle
Deposit Statuses
Checking Deposit Status
Deposit IDs are UUIDs. Fetch a deposit by ID to get its current status:Deposit status changes are not currently delivered as webhook events. The
webhook event catalog covers payout, order, and account events (see the
Webhooks guide). Poll
GET /v1/deposits/{id} to track a
deposit: fetching a pending or processing deposit also triggers an
asynchronous status refresh, so polling keeps the record fresh.Listing Deposits
Retrieve deposits for your account as a paginated list, newest first. Filter withstatus, and page with limit (1–100, default 20) plus cursor:
nextCursor as an opaque token: pass it back verbatim in the cursor query parameter to fetch the next page, and stop when hasMore is false. An invalid cursor, limit, or status value returns a 400 with field-level details.
Error Handling
Payin endpoints return standard error bodies:400 Bad Request
See the Error Handling guide for retry and recovery strategies.
Best Practices
Deposit Creation
Deposit Creation
- Always include a unique
clientReffor idempotency and reconciliation (duplicates are rejected with a400) - Display the full
metadatablock to the sender: account number, account name, bank name, and expiry - Communicate the virtual account expiry (
metadata.expiresAt) so the sender transfers in time - Store deposit IDs (UUIDs) for status tracking and customer support
Status Monitoring
Status Monitoring
- Poll
GET /v1/deposits/{id}with exponential backoff - Handle all eight statuses, including
in_review,refunding, andrefunded - Treat
in_reviewas not-yet-credited: funds are held for compliance review - Log deposit events for audit and debugging
Security
Security
- Use HTTPS for all API communications
- Never log sensitive customer payment data
- Implement proper access controls for deposit endpoints
- If you consume webhooks for other events, verify signatures (see Verifying Signatures)
Next Steps
Payouts
Send money globally to beneficiaries
Webhook Setup
Real-time notifications for payout, order, and account events
Ledger System
Track transactions with double-entry accounting
API Reference
Complete API documentation