Skip to Content
Wallet & payouts

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.

EndpointScope
GET /v1/wallet/balancewallet:read
GET /v1/wallet/payout-accountspayouts:read
GET /v1/wallet/bankspayouts:read
POST /v1/wallet/payout-accounts/resolvepayouts:read
POST /v1/wallet/payout-accountspayouts:write
GET /v1/wallet/withdrawalswallet:withdrawals:read
POST /v1/wallet/withdrawalswallet:withdrawals:create

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.

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/banks

Returns the banks you can resolve and pay out to.

Query parameters

ParameterTypeDescription
currencystringCurrency to list banks for (defaults to your business currency)
providerstringRestrict to a specific payment provider

Resolve an account

POST /v1/wallet/payout-accounts/resolve

Verifies a bank account number and returns the registered account name. Resolve before adding an account so you store the correct name.

Body

FieldTypeRequiredDescription
account_numberstringYesAccount number to resolve
bank_codestringYesBank code from List banks
providerstringNoPayment provider to resolve through
{ "account_number": "0123456789", "bank_code": "044" }

Add a payout account

POST /v1/wallet/payout-accounts

Body

FieldTypeRequiredDescription
bank_namestringYesBank name
account_numberstringYesAccount number
account_namestringYesResolved account name
bank_codestringNoBank code
providerstringNoPayment provider

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:

  1. The key holds the wallet:withdrawals:create scope.
  2. The (live) key has an IP allowlist.
  3. The key has a withdrawal policy configured (set when creating/updating the key):
    • maxPerTransaction - maximum amount per withdrawal
    • maxPerDay - maximum total per rolling day
    • allowedPayoutAccountIds - only these payout accounts may be paid out to
  4. The requested payout_account_id is in the policy’s allowlist, and the amount is within both caps.

If any condition fails, the request is rejected before any money moves:

errorMeaning
ip_allowlist_requiredThe key has no IP allowlist
withdrawal_policy_requiredThe key has no withdrawal policy
payout_account_not_allowedThe payout account isn’t in the policy allowlist
amount_exceeds_per_transaction_limitAmount is over maxPerTransaction
amount_exceeds_daily_limitAmount would exceed maxPerDay for today

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/withdrawals

Returns paginated withdrawal history (page, limit).

Initiate a withdrawal

POST /v1/wallet/withdrawals

Body

FieldTypeRequiredDescription
amountnumberYesAmount to withdraw
payout_account_iduuidYesA payout account in the key’s policy allowlist
{ "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.

Last updated on