Webhooks
Configurez vos endpoints webhook et vérifiez les livraisons de manière sécurisée.
Webhooks
Genuka Pay peut notifier votre backend sur les événements transaction, payout, KYC et company.
Headers requis
Les requêtes de gestion d’endpoints webhook doivent inclure :
X-Public-Key: YOUR_PUBLIC_KEY
X-Timestamp: UNIX_TIMESTAMP
X-Signature: HMAC_SHA256_SIGNATUREFlux recommandé
Les webhooks doivent être gérés depuis le dashboard Genuka Pay, via la page Webhooks.
Ce flux permet à votre équipe :
- de créer des endpoints
- de choisir les événements
- d’activer ou désactiver les endpoints
- d’inspecter quelques métadonnées de livraison
- de régénérer le secret
Utilisez l’API ci-dessous seulement pour l’automatisation ou l’outillage interne.
API de gestion
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
Créer un 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": "Backend de production",
"target_url": "https://merchant.example.com/webhooks/genuka",
"events": [
"transaction.success",
"transaction.failed",
"payout.success",
"kyc.approved"
],
"is_active": true
}'Événements disponibles
transaction.successtransaction.failedtransaction.processingtransaction.refundedpayout.successpayout.failedpayout.processingpayout.cancelledkyc.submittedkyc.approvedkyc.rejectedcompany.createdcompany.suspendedcompany.reactivated
Forme du payload
{
"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" }
}
}Retrouvez votre propre référence dans data.metadata.external_id, celle que vous avez envoyée à l'initiation.
Headers envoyés :
Signature— HMAC-SHA256 de la requête, voir ci-dessousX-Webhook-IdX-Webhook-Event
Vérification de signature
La signature arrive dans le header Signature : un HMAC-SHA256 du corps brut de la requête, avec le secret de l’endpoint.
import crypto from "crypto";
// rawBody : le corps de la requête tel que reçu, avant tout parsing JSON.
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)
);
}Signez le corps brut, pas l’objet reparsé
Re-sérialiser le JSON après l’avoir parsé change les espaces et l’ordre des clés : la signature ne correspondra plus. Gardez le corps brut (express.raw(), request.body non parsé) pour la vérification. Comparez aussi en temps constant, et rejetez toute livraison non signée.
Rotation du secret
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"Le nouveau secret doit être stocké immédiatement.
Recommandations
- retournez un
2xxrapidement - poussez le traitement lourd dans une queue
- vérifiez la signature avant traitement
- implémentez l’idempotence côté récepteur
How is this guide?
Last updated on