Wallet & payouts
Read your wallet balance, manage the bank accounts you withdraw to, and initiate withdrawals. Withdrawals move real money, so they sit behind extra guardrails - read Withdrawals carefully before enabling them.
All endpoints share the prefix /v1/wallet and authenticate with an API key.
payouts:write and wallet:withdrawals:create are finance write scopes. On a
live key, both require an IP allowlist - key
creation is rejected without one.
Get balance
GET /v1/wallet/balance{
"message": "Wallet balance retrieved",
"data": {
"balance": 250000,
"availableBalance": 245000,
"pendingWithdrawals": 5000,
"minimumWithdrawalAmount": 1000,
"currency": "NGN"
}
}availableBalance is what you can withdraw right now - it excludes funds reserved by
pending withdrawals.
Deposit accounts
GET /v1/wallet/deposit-accountsVirtual bank accounts customers (or you) can transfer into to fund the wallet. Requires the business to have completed at least Level 1 (BVN) verification.
{
"message": "Deposit accounts retrieved",
"data": {
"verificationLevel": 1,
"isEligible": true,
"accounts": [
{
"id": "ba1a2b3c-...",
"bankName": "Example Bank",
"accountNumber": "9012345678",
"accountName": "Acme Foods Ltd",
"qrCodeUrl": "https://.../qr/ba1a2b3c.png",
"provider": "paystack"
}
],
"requiredLevel": 1,
"requiredAction": null
}
}If isEligible is false, accounts is empty and requiredAction explains what to do
(e.g. complete BVN verification).
Payout accounts
Payout accounts are the bank accounts you withdraw to.
List payout accounts
GET /v1/wallet/payout-accounts{
"message": "Payout accounts retrieved",
"data": [
{
"id": "pa1a2b3c-...",
"bankName": "Example Bank",
"accountNumber": "0123456789",
"accountName": "Acme Foods Ltd",
"isDefault": true
}
]
}List banks
GET /v1/wallet/banksReturns the banks you can resolve and pay out to.
Query parameters
Resolve an account
POST /v1/wallet/payout-accounts/resolveVerifies a bank account number and returns the registered account name. Resolve before adding an account so you store the correct name.
Body
{ "account_number": "0123456789", "bank_code": "044" }Add a payout account
POST /v1/wallet/payout-accountsBody
Response 201 Created - the new payout account. Send an Idempotency-Key header to
avoid duplicates.
Withdrawals
Withdrawals transfer funds from your wallet to a payout account. Because a leaked key could otherwise drain a wallet, API-initiated withdrawals require all of the following:
- The key holds the
wallet:withdrawals:createscope. - The (live) key has an IP allowlist.
- The key has a withdrawal policy configured (set when creating/updating the key):
maxPerTransaction- maximum amount per withdrawalmaxPerDay- maximum total per rolling dayallowedPayoutAccountIds- only these payout accounts may be paid out to
- The requested
payout_account_idis in the policy’s allowlist, and the amount is within both caps.
If any condition fails, the request is rejected before any money moves:
All of Cloove’s standard withdrawal safeguards (minimum amount, verification-level limits, atomic balance checks, and audit logging) still apply.
List withdrawals
GET /v1/wallet/withdrawalsReturns paginated withdrawal history (page, limit).
Initiate a withdrawal
POST /v1/wallet/withdrawalsBody
{ "amount": 25000, "payout_account_id": "pa1a2b3c-..." }Response 201 Created
{
"message": "Withdrawal submitted",
"data": {
"withdrawal": {
"id": "w1a2b3c4-...",
"type": "WALLET_WITHDRAWAL",
"amount": 25000,
"currency": "NGN",
"status": "PENDING",
"externalReference": "CLV-WD-...",
"createdAt": "2026-01-15T10:00:00.000Z"
},
"fee": { "amount": 50, "currency": "NGN" }
}
}Always send an Idempotency-Key header when initiating a withdrawal. The transfer is
processed asynchronously - track it with the wallet.withdrawal.completed and
wallet.withdrawal.failed webhooks.