Main resources

Withdrawals

Send funds from your wallet to a Mobile Money account, in USSD mode or via the hosted gateway.

Sandbox mode. Use your kpay_test_... keys and the test numbers below. KPay routes your requests to its test environment — no real money is moved.

The Withdrawal Object

Withdrawal Object
{
  "id": "wdr_xyz456",
  "reference": "KPAY-WD-20260514-XYZ456",
  "providerReference": "f4401bd2-1568-4140-bf2d-eb77d2b2b639",
  "status": "COMPLETED",
  "amount": 5000,
  "netAmount": 4750,
  "feeAmount": 250,
  "currency": "XAF",
  "externalId": "WD-ORDER-98765",
  "provider": "MTN_MOMO_CMR",
  "country": "CMR",
  "phoneNumber": "237653456789",
  "isTest": true,
  "description": "Retrait commission — mai 2026",
  "metadata": { "payoutCycle": "2026-05" },
  "createdAt": "2026-05-14T10:00:00.000Z",
  "completedAt": "2026-05-14T10:01:45.000Z",
  "failedAt": null,
  "failureReason": null
}

Properties

idstring

Unique withdrawal identifier.

referencestring

Internal KPAY reference.

providerReferencestring | null

Operation identifier on the operator side (payoutId, UUID).

statusstring

Current status.

PENDINGPROCESSINGCOMPLETEDFAILEDCANCELLED
amountnumber

Gross amount requested, in the operator country currency.

netAmountnumber

Net amount sent to the beneficiary after commission.

feeAmountnumber

Withdrawal commission charged.

currencystring

Currency derived from the operator country.

externalIdstring

Your identifier (idempotency, retry-safe).

providerstring | null

Provider (operator) inferred from the number (e.g. MTN_MOMO_CMR).

countrystring | null

Operator country, ISO 3166-1 alpha-3 (e.g. CMR).

USSD Mode — Initiate a withdrawal

POST/api/v1/payments/withdraw

Authentication & environment

kpay_test_xxxxxxxxxxxxxxxx. In sandbox, use a test number for the beneficiary (see the "Test mode" section).

Mandatory provider (USSD mode)

provider catalogue. The provider whitelist of your Application also applies to withdrawals.

Request body

amountnumberrequis

Amount in the provider currency, minimum 100 XAF in Cameroon zone. A commission is charged.

providerstringrequis

Beneficiary's Mobile Money operator code (e.g. MTN_MOMO_CMR). Determines the country and currency. See the provider catalogue.

phoneNumberstringrequis

Beneficiary's Mobile Money number (USSD mode), in international format. In sandbox, a test number; in production, a real number.

externalIdstring

Unique identifier — enables idempotency (safe retry).

descriptionstring

Description for reconciliation.

metadataobject

Free JSON metadata.

Request example

Node.js
const res = await fetch("https://admin.kpay.site/api/v1/payments/withdraw", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.KPAY_API_KEY,
    "X-Secret-Key": process.env.KPAY_SECRET_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "amount": 5000,
  "provider": "MTN_MOMO_CMR",
  "phoneNumber": "237653456789",
  "externalId": "WD-ORDER-98765"
}),
});
const data = await res.json();

Response (201)

201 Created
{
  "id": "wdr_xyz456",
  "reference": "KPAY-WD-20260514-XYZ456",
  "providerReference": "f4401bd2-1568-4140-bf2d-eb77d2b2b639",
  "status": "PENDING",
  "amount": 5000,
  "netAmount": 4750,
  "feeAmount": 250,
  "currency": "XAF",
  "externalId": "WD-ORDER-98765",
  "provider": "MTN_MOMO_CMR",
  "country": "CMR",
  "phoneNumber": "237653456789",
  "isTest": true,
  "message": "Retrait initié, transfert en cours auprès de l'opérateur."
}

Hosted gateway mode (GATEWAY)

Call /api/v1/payments/withdraw without phoneNumber / paymentMethod, with returnUrl (required) and cancelUrl (optional). The beneficiary enters their information on the KPay hosted page.

Request example

Node.js
const res = await fetch("https://admin.kpay.site/api/v1/payments/withdraw", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.KPAY_API_KEY,
    "X-Secret-Key": process.env.KPAY_SECRET_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "amount": 5000,
  "externalId": "WD-ORD-001",
  "returnUrl": "https://monsite.com/return"
}),
});
const data = await res.json();
Withdraw response in GATEWAY mode
{
  "id": "wdr_abc123",
  "reference": "KPAY-WD-20260514-ABC123",
  "externalId": "WD-ORD-001",
  "status": "PENDING",
  "mode": "GATEWAY",
  "amount": 5000,
  "netAmount": 4750,
  "feeAmount": 250,
  "currency": "XAF",
  "gatewayUrl": "https://admin.kpay.site/gateway/gw_9aB3...",
  "expiresAt": "2026-05-16T10:45:00.000Z",
  "isTest": true,
  "message": "Redirect the beneficiary to gatewayUrl to enter withdrawal details."
}

Return signature

The gateway return for a withdrawal uses the same signature scheme as payments (status|reference|externalId|ts). See Signature verification.

Status tracking

GET/api/v1/payments/withdraw/:id

Node.js
const res = await fetch("https://admin.kpay.site/api/v1/payments/withdraw/wdr_xyz456", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.KPAY_API_KEY,
    "X-Secret-Key": process.env.KPAY_SECRET_KEY,
  },
});
const data = await res.json();

Insufficient balance

If the wallet balance does not cover the amount (including commission), the initialization returns 422 Unprocessable Entity.

Test mode (KPay sandbox)

With a kpay_test_… key, withdrawals are routed to the KPay sandbox. As with payments, the beneficiary's test number determines the outcome (COMPLETED, FAILED with failureCode, or SUBMITTED). Check the Withdrawals (payouts) column below.

Providers : MTN_MOMO_CMR, ORANGE_CMR

Payments (deposits)

Number (MSISDN)ResultfailureCode
237653456019FAILEDPAYER_LIMIT_REACHED
237653456029FAILEDPAYER_NOT_FOUND
237653456039FAILEDPAYMENT_NOT_APPROVED
237653456069FAILEDUNSPECIFIED_FAILURE
237653456129SUBMITTED
237653456789COMPLETED

Withdrawals (payouts)

Number (MSISDN)ResultfailureCode
237653456089FAILEDRECIPIENT_NOT_FOUND
237653456119FAILEDUNSPECIFIED_FAILURE
237653456129SUBMITTED
237653456789COMPLETED

Related resources

Was this page helpful?