Webhooks allow your system to receive real-time notifications about events such as completed transactions, wallet funding, or failed requests. When an event occurs, a POST request is sent to your configured webhook URL with a JSON payload.
Webhooks are useful for actions that happen outside your application, such as:
Using webhooks ensures your system is updated in real-time without requiring constant polling of the API.
Tip: During development, you can use services like webhook.site to inspect payloads before implementing.
All webhooks contain a transaction object with transaction data:
Example payload:
{
"transaction": {
"transactionId": "1234567890",
"email": "user@example.com",
"activity": "MTN airtime",
"status": "Successful",
"recipient": "08032566178",
"amount": 100,
"amountUsed": 99,
"initialBalance": 500,
"finalBalance": 401,
"Method": "API"
}
}Each webhook is signed using the user's secret key. The signature is sent in the X-Signature header. To verify the webhook:
import crypto from "crypto";
function isValidWebhook(rawBody, signature, secretKey) {
const hash = crypto
.createHmac("sha256", secretKey)
.update(rawBody)
.digest("hex");
return hash === signature;
}Always validate this signature before processing the webhook payload.
import express from "express";
import bodyParser from "body-parser";
const app = express();
// Capture raw body for signature verification
app.use(bodyParser.json({
verify: (req, res, buf) => { req.rawBody = buf.toString(); }
}));
app.post("/webhook", async (req, res) => {
const signature = req.headers["x-signature"];
const secretKey = process.env.USER_SECRET_KEY;
if (!signature || !isValidWebhook(req.rawBody, signature, secretKey)) {
return res.status(401).send("Invalid signature");
}
const payload = req.body;
console.log("Received webhook:", payload);
res.sendStatus(200);
});