Additional resources
Webhooks
Receive real-time status change notifications without polling the API.
How it works
- Expose an endpoint on your server, capable of receiving HTTP POST requests.
- Configure your URLs callback URLs in your application settings from the dashboard (creation or modification).
- Receive the event — on each status change (deposit, withdrawal or refund), KPay sends a POST to the corresponding URL.
- Verify the signature then process the event (idempotency required).
- Respond 200 OK quickly to acknowledge receipt and avoid retries.
Callback URL configuration
When creating or modifying your application, you can define up to 4 callback URLs:
Available URLs
Generic URL (fallback)stringURL used by default if no specific URL is defined for a given transaction type.
Deposits callbackstringURL dedicated to incoming payment notifications (payment.* events).
Withdrawals callbackstringURL dedicated to withdrawal notifications (payout.* events).
Refunds callbackstringURL dedicated to refund notifications (refund.* events).
URL resolution
Event object
{
"event": "payment.completed",
"paymentId": "pay_abc123",
"reference": "KPAY-DEP-12345",
"status": "COMPLETED",
"amount": 5000,
"phoneNumber": "237670000001",
"externalId": "ORDER-12345",
"metadata": { "orderId": "12345" },
"completedAt": "2026-05-14T10:02:30.000Z",
"failedAt": null,
"failureReason": null,
"timestamp": "2026-05-14T10:02:31.000Z"
}Properties
eventstringEvent type (see next section).
paymentIdstringUnique KPay transaction identifier.
referencestringInternal KPay transaction reference.
statusstringFinal status.
COMPLETEDFAILEDCANCELLEDamountnumberTransaction amount.
phoneNumberstringCustomer phone number.
externalIdstringYour transaction identifier (if provided at initialization).
metadataobjectMetadata passed at initialization.
completedAtstring | nullCompletion timestamp (if COMPLETED).
failedAtstring | nullFailure timestamp (if FAILED/CANCELLED).
failureReasonstring | nullFailure reason if applicable.
timestampstringWebhook send timestamp (ISO 8601).
Event types
Events are grouped by transaction type. Each category is sent to the corresponding callback URL (or the generic URL as fallback).
Deposits (incoming payments)
Withdrawals (payouts)
Refunds
Request headers
X-KPAY-SignaturestringHMAC-SHA256 (hex) calculated on the raw JSON body received.
X-KPAY-EventstringEvent name (e.g. payment.completed, payout.failed).
User-AgentstringKPAY-Webhook/1.0
Security — signature verification
Always verify before processing
const crypto = require("crypto");
app.post("/webhooks/kpay",
express.raw({ type: "application/json" }),
(req, res) => {
const signature = req.headers["x-kpay-signature"];
const raw = req.body; // Buffer brut
const expected = crypto
.createHmac("sha256", process.env.KPAY_WEBHOOK_SECRET)
.update(raw)
.digest("hex");
const valid = signature &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!valid) return res.status(400).send("Invalid signature");
const event = JSON.parse(raw.toString());
// traiter de façon idempotente...
res.status(200).send("OK");
});Retries & best practices
- Retry policy: 3 attempts with backoff (1 s, 2 s, 4 s), 3 s timeout per attempt. No retry on 4xx response; retry on 5xx/network.
- Respond quickly: return 200 before any long processing; process asynchronously if needed.
- Idempotency: the same event may arrive multiple times; deduplicate via paymentId / externalId.
- HTTPS required, valid certificate.
- Optional URLs: if you define no callback URL, KPay will not attempt to send webhooks. You can always check the status via the API GET /api/v1/payments/:id.
Source of authority