Refunds

Return a captured payment to the payer. The recipient and amount are derived from the original payment.

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 Refund object

Initiation returns the refund transaction that was created, along with the state of the original payment.

Initiation response
{
  "id": "b7c1e2f3-4a5d-6e7f-8901-2b3c4d5e6f70",
  "status": "PENDING",
  "amount": 5000,
  "currency": "XAF",
  "originalPaymentId": "a1b2c3d4-5e6f-7890-1a2b-3c4d5e6f7081",
  "originalPaymentStatus": "COMPLETED",
  "message": "Remboursement initié — transfert en cours vers le payeur"
}

Properties

idstring

KPay identifier for the refund. Keep it to reconcile with webhooks.

statusstring

State at initiation. PENDING: accepted, transfer under way. FAILED: initiation refused, no funds moved.

PENDINGFAILED
amountnumber

Refunded amount, equal to the gross amount paid by the customer (fees included).

currencystring

Refund currency, identical to the original payment.

originalPaymentIdstring

Identifier of the refunded payment.

originalPaymentStatusstring

State of the original payment at initiation. It becomes REFUNDED once the refund is confirmed.

messagestring

Human-readable message describing the outcome of the initiation.

Refund rules

  • Full refunds only: there is no amount field. The gross amount paid by the customer is returned, fees included. The refund itself incurs no fee.
  • A 7-day window after the payment completes. Beyond that, the request is refused.
  • One active refund per payment. A previously failed attempt does not prevent a new one.
  • The payment must be an incoming payment with status COMPLETED.
  • The amount is reserved on your wallet as soon as the refund is initiated: your available balance drops immediately. If the balance does not cover the amount, the request is refused.
  • Once the refund is confirmed, the original payment moves to status REFUNDED.

No phone number required

The recipient is derived from the original payment by the provider. Unlike a manual payout, there is no risk of sending the money to the wrong person.

Initiate a refund

POST/api/v1/payments/:id/refund

Authentication

kpay_test_xxxxxxxxxxxxxxxx. Use your test keys: no real money moves.

Path parameter

idstringrequis

KPay identifier of the payment to refund, as returned when the payment was initiated.

Request body

reasonstring

Reason stored in the transaction history and echoed in webhooks. 255 characters maximum.

externalIdstring

Your own refund identifier. Acts as an idempotency key: replaying the request with the same value will not trigger a second refund. Generated by KPay if omitted. 100 characters maximum.

Node.js
const res = await fetch("https://test.admin.kpay.site/api/v1/payments/a1b2c3d4-5e6f-7890-1a2b-3c4d5e6f7081/refund", {
  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({
  "reason": "Produit en rupture de stock",
  "externalId": "REFUND-CMD-2026-00042"
}),
});
const data = await res.json();
201 Created
{
  "id": "b7c1e2f3-4a5d-6e7f-8901-2b3c4d5e6f70",
  "status": "PENDING",
  "amount": 5000,
  "currency": "XAF",
  "originalPaymentId": "a1b2c3d4-5e6f-7890-1a2b-3c4d5e6f7081",
  "originalPaymentStatus": "COMPLETED",
  "message": "Remboursement initié — transfert en cours vers le payeur"
}

Asynchronous processing

A 201 response means the refund was accepted, not that it completed. The final status arrives by webhook.

Tracking a refund

The final status is delivered to the refund callback URL configured on your application.

Events

refund.completedwebhook

The refund succeeded. Funds left your wallet and the original payment becomes REFUNDED.

refund.failedwebhook

The refund failed. Reserved funds are released and the original payment stays COMPLETED.

Without a webhook, poll GET /api/v1/payments/:id.

Errors

In sandbox

Refunds behave identically in sandbox and production. First capture a payment using a test number that completes, then refund it: no real money moves.

Related resources

Was this page helpful?

K-PAY — Mobile Money and card payments across Central Africa.