Main resources
Withdrawals
Send funds from your wallet to a Mobile Money account, in USSD mode or via the hosted gateway.
The 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
idstringUnique withdrawal identifier.
referencestringInternal KPAY reference.
providerReferencestring | nullOperation identifier on the operator side (payoutId, UUID).
statusstringCurrent status.
PENDINGPROCESSINGCOMPLETEDFAILEDCANCELLEDamountnumberGross amount requested, in the operator country currency.
netAmountnumberNet amount sent to the beneficiary after commission.
feeAmountnumberWithdrawal commission charged.
currencystringCurrency derived from the operator country.
externalIdstringYour identifier (idempotency, retry-safe).
providerstring | nullProvider (operator) inferred from the number (e.g. MTN_MOMO_CMR).
countrystring | nullOperator 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)
Request body
amountnumberrequisAmount in the provider currency, minimum 100 XAF in Cameroon zone. A commission is charged.
providerstringrequisBeneficiary's Mobile Money operator code (e.g. MTN_MOMO_CMR). Determines the country and currency. See the provider catalogue.
phoneNumberstringrequisBeneficiary's Mobile Money number (USSD mode), in international format. In sandbox, a test number; in production, a real number.
externalIdstringUnique identifier — enables idempotency (safe retry).
descriptionstringDescription for reconciliation.
metadataobjectFree JSON metadata.
Request example
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)
{
"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
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();{
"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
Status tracking
GET/api/v1/payments/withdraw/:id
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
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) | Result | failureCode |
|---|---|---|
| 237653456019 | FAILED | PAYER_LIMIT_REACHED |
| 237653456029 | FAILED | PAYER_NOT_FOUND |
| 237653456039 | FAILED | PAYMENT_NOT_APPROVED |
| 237653456069 | FAILED | UNSPECIFIED_FAILURE |
| 237653456129 | SUBMITTED | — |
| 237653456789 | COMPLETED | — |
Withdrawals (payouts)
| Number (MSISDN) | Result | failureCode |
|---|---|---|
| 237653456089 | FAILED | RECIPIENT_NOT_FOUND |
| 237653456119 | FAILED | UNSPECIFIED_FAILURE |
| 237653456129 | SUBMITTED | — |
| 237653456789 | COMPLETED | — |