Webhooks
Configure webhook endpoints, verify signatures, and design reliable asynchronous event processing.
Introduction
Webhooks allow Genuka Pay to notify your backend about transaction, payout, KYC, and company events without forcing your system to poll continuously.
Event Delivery
Receive asynchronous updates when transactions, payouts, or compliance states change.
Signature Verification
Validate every incoming delivery before applying state changes in your backend.
Secret Rotation
Regenerate webhook secrets when credentials change or exposure is suspected.
Required Headers
Webhook endpoint management calls should include:
X-Public-Key: YOUR_PUBLIC_KEY
X-Timestamp: UNIX_TIMESTAMP
X-Signature: HMAC_SHA256_SIGNATURERecommended Setup Flow
Start with the Webhooks page if you want to manage endpoints from the dashboard.
You can use that page to:
- create endpoints
- choose subscribed events
- enable or disable delivery
- inspect endpoint metadata
- rotate the webhook secret
Use the API when you want to automate setup or provision endpoints from your own tooling.
Endpoint Management API
GET /api/v1/webhook-endpointsPOST /api/v1/webhook-endpointsGET /api/v1/webhook-endpoints/{id}PUT /api/v1/webhook-endpoints/{id}DELETE /api/v1/webhook-endpoints/{id}POST /api/v1/webhook-endpoints/{id}/regenerate-secret
Create a Webhook Endpoint
curl -X POST "{{BASE_URL}}/api/v1/webhook-endpoints" \
-H "X-Public-Key: YOUR_PUBLIC_KEY" \
-H "X-Timestamp: UNIX_TIMESTAMP" \
-H "X-Signature: HMAC_SHA256_SIGNATURE" \
-H "Content-Type: application/json" \
-d '{
"name": "Production backend",
"target_url": "https://merchant.example.com/webhooks/genuka",
"events": [
"transaction.success",
"transaction.failed",
"payout.success",
"kyc.approved"
],
"is_active": true
}'Main Request Fields
nametarget_urleventsis_activemetadata
Available Events
transaction.successtransaction.failedtransaction.processingtransaction.refundedpayout.successpayout.failedpayout.processingpayout.cancelledkyc.submittedkyc.approvedkyc.rejectedcompany.createdcompany.suspendedcompany.reactivated
Delivery Payload Shape
{
"id": "01HW...",
"event": "transaction.success",
"timestamp": "2026-09-19T12:10:00.000000Z",
"data": {
"transaction_id": "01HR...",
"idempotency_key": "...",
"amount": 10000,
"net_amount": 9575,
"provider_fee_amount": 150,
"genuka_fee_amount": 275,
"total_fee_amount": 425,
"currency": "XOF",
"status": "SUCCESS",
"completed_at": "2026-09-19T12:10:00.000000Z",
"metadata": { "external_id": "order_10001" }
}
}Your own reference comes back in data.metadata.external_id, the one you sent at initiation.
Delivery headers:
Signature— HMAC-SHA256 of the request, see belowX-Webhook-IdX-Webhook-Event
Signature Verification
The signature arrives in the Signature header: an HMAC-SHA256 of the raw request body, keyed with the endpoint secret.
import crypto from "crypto";
// rawBody: the request body exactly as received, before any JSON parsing.
export function verifyWebhook(rawBody, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
const received = Buffer.from(signature, "utf8");
const computed = Buffer.from(expected, "utf8");
return (
received.length === computed.length &&
crypto.timingSafeEqual(received, computed)
);
}Sign the raw body, not the reparsed object
Re-serialising the JSON after parsing it changes whitespace and key order: the signature will no longer match. Keep the raw body (express.raw(), an unparsed request.body) for verification. Compare in constant time, and reject any unsigned delivery.
Secret Rotation
curl -X POST "{{BASE_URL}}/api/v1/webhook-endpoints/{id}/regenerate-secret" \
-H "X-Public-Key: YOUR_PUBLIC_KEY" \
-H "X-Timestamp: UNIX_TIMESTAMP" \
-H "X-Signature: HMAC_SHA256_SIGNATURE"Store the regenerated secret immediately. It may not be displayed again later.
Recommendations
- acknowledge webhook deliveries quickly with a
2xxresponse - push heavy work to a queue or worker
- verify the signature before mutating business state
- make your receiver idempotent
- correlate webhook IDs with internal reconciliation records
How is this guide?
Last updated on