Skip to content
SkanPay Docs

Cash-out: payouts and withdrawals

Send money from your SkanPay balance to a mobile money wallet: to anyone (a payout) or to your own business wallet (a withdrawal).

Payout or withdrawal?

PayoutWithdrawal
PaysAny MTN or Airtel wallet: customers, suppliers, agents, staffOnly your own approved payout wallets
Recipient named byA phone number (msisdn)A payout wallet id (destination)
Typical useMarketplace sellers, cash-back, salaries, customer refundsTaking your earnings out of SkanPay
Second approverNot requiredAbove a threshold, a second team member must approve
EndpointPOST /v1/payoutsPOST /v1/withdrawals
Webhookspayout.successful / payout.failedwithdrawal.successful / withdrawal.failed

Funding: the available balance

Both are paid from your available balance in the same currency. Money from charges becomes available one day after the charge succeeds; a deposit is available immediately. Check with GET /v1/balances.

The fee is charged on top: the recipient gets amount in full, and your balance is debited total_debited = amount + fee. If the available balance is less than that, the request fails with insufficient_balance and nothing is sent.

The moment a payout or withdrawal is accepted, amount + fee is held from your available balance, so two requests can never spend the same money. If it fails, the whole hold is returned, fee included. If it succeeds, the hold is paid out.

Payouts

Send money to any wallet, by phone number.

curl -X POST https://api.skanpay.website/v1/payouts \
  -H "Authorization: Bearer $SKANPAY_SECRET_KEY" \
  -H "Idempotency-Key: payout-seller-77-2026-09" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "150000",
    "currency": "UGX",
    "msisdn": "+256701234567",
    "reference": "payout-seller-77-2026-09",
    "narration": "September earnings",
    "metadata": { "seller_id": "77" }
  }'

The response is a payout object. As with charges, 201 means it exists; its status tells you where it is. The outcome arrives as payout.successful or payout.failed. On failure, the full total_debited is back in your available balance.

Withdrawals

A withdrawal moves your own earnings to one of your business's payout wallets. Unlike a payout, it cannot name an arbitrary phone number, so even a leaked API key cannot send your balance to a stranger.

Set up a payout wallet (dashboard only)

  1. An owner or admin opens Balances → Payout wallets in the dashboard and adds the MTN or Airtel number with a label.
  2. An owner approves it. If your account has more than one owner, it must be a different owner from the person who added it.
  3. It then cools off for 24 hours before it can receive money. If a wallet appears that nobody on your team added, revoke it in that window.

API keys can list wallets (GET /v1/payout_destinations) but never add or approve one.

Withdraw

curl -X POST https://api.skanpay.website/v1/withdrawals \
  -H "Authorization: Bearer $SKANPAY_SECRET_KEY" \
  -H "Idempotency-Key: sweep-2026-09-28" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "2500000",
    "currency": "UGX",
    "destination": "wal_01J9Z3K8Q4W6XK2M7N5P0R3T8V",
    "reference": "sweep-2026-09-28",
    "narration": "Daily sweep"
  }'

The wallet decides the country and network; the currency must be that country's currency.

Second approval above a threshold

A withdrawal above your account's approval threshold is created but not sent:

Waiting for approval
{ "id": "wdl_…", "status": "INITIATED", "approval_status": "PENDING", ... }

The funds are held immediately. A second team member approves or rejects it in the dashboard; the person who requested it cannot approve it themselves. A withdrawal made with an API key always needs a person to approve it when it is over the threshold.

  • Approved: approval_status becomes APPROVED and it is sent; you then get withdrawal.successful or withdrawal.failed.
  • Rejected: it fails with failure_code: "approval_rejected", the hold is released in full, and you get withdrawal.failed.
CurrencyDefault threshold
UGXUSh 5,000,000
KESKSh 170,000.00
GHSGH₵ 20,000.00

SkanPay can set a different threshold for your account.

Outcomes and failures

Cash-out follows the same statuses and failure codes as cash-in. wallet_not_found, wallet_inactive and wallet_limit_exceeded are the common recipient-side failures. Whatever the reason, a failed payout or withdrawal returns the full hold, fee included, to your available balance.

Errors specific to cash-out

HTTPcodeMeaning
403payouts_not_enabled_livePayouts are not switched on yet.
403withdrawals_not_enabled_liveWithdrawals are not switched on yet.
400insufficient_balanceAvailable balance < amount + fee.
400destination_not_activeWallet pending approval, cooling off, or revoked.
404destination_not_foundNo such payout wallet on your account.
429rate_limit_exceededMore than 60 cash-out requests a minute.

The phone-number, currency and limit errors from cash-in apply too. The minimum amount is the country minimum, USh 500 in Uganda.