Webhook Integration

Overview

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.

When to Use Webhooks

Webhooks are useful for actions that happen outside your application, such as:

  • Transaction completion notifications.
  • Wallet funding updates.
  • Failed transactions or refunds.
  • Other asynchronous events affecting user balances.

Using webhooks ensures your system is updated in real-time without requiring constant polling of the API.

Setting Up Webhooks

  1. Log in to your dashboard and navigate to your generate api key page.
  2. Add your webhook endpoint URL where notifications will be sent.
  3. Ensure your server can handle POST requests and responds with HTTP 200.

Tip: During development, you can use services like webhook.site to inspect payloads before implementing.

Webhook Payload Structure

All webhooks contain a transaction object with transaction data:

  • transactionId: Unique transaction identifier.
  • email: User email.
  • activity: The main action performed (e.g., "MTN airtime").
  • status: Transaction status (e.g., "Successful" or "Failed").
  • recipient: Target phone number, account, or recipient ID.
  • amount and amountUsed: Transaction amount and amount deducted.
  • initialBalance and finalBalance: User balances before and after the transaction.

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"
  }
}

Verifying Webhook Signatures

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.

Responding to Webhook Requests

  • Respond with HTTP 200 immediately after receiving a webhook.
  • Do not perform long-running operations before responding.
  • Queue further processing (e.g., notifications, logs, or balance updates) to a background worker.

Example Implementation (Node.js)

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);
});

Best Practices

  • Always verify the signature to ensure authenticity.
  • Respond quickly to avoid timeouts (our webhook expects a 200 response within 60s).
  • Make processing idempotent—record processed transactions to prevent duplicate actions.
  • Use background jobs for heavy processing like sending emails, updating balances, or applying referral bonuses.
  • Log all incoming events for auditing and debugging.
IABCONCEPT