Overview
Webhooks allow your application to receive real-time HTTP POST notifications whenever an asynchronous transaction changes status (e.g., successful airtime or data top-up, bill payments, cable TV subscriptions, or refunds) on Inlomax.
Instead of polling our API repeatedly, we automatically deliver transaction events to your configured endpoint as soon as they are processed.
Configuring Your Webhook
- Log in to your Inlomax dashboard and navigate to Developer's API.
- Enter your publicly accessible destination URL in the Webhook URL field (e.g.
https://yourdomain.com/api/webhook). - (Recommended) Set or click Auto Generate Secret to create a secret key for cryptographic payload signing.
- Click Update Webhook & Secret and confirm with your 4-digit Transaction PIN.
Webhook Signature & Security
HMAC-SHA256To ensure that incoming webhooks are genuinely from Inlomax and have not been intercepted or modified, we support HMAC-SHA256 signature verification.
When you set a Webhook Secret in your dashboard, every webhook sent to your URL includes the following HTTP header:
X-Inlomax-Signature: sha256=4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945
Webhook Payload Structure
When a transaction status is finalized, Inlomax sends an HTTP POST request with a JSON body formatted as follows:
{
"status": "success",
message": "Dear Customer, You have successfully gifted 0903837261 with 1.0GB of Data. Thank you.",
"reference": "INL|NQJK56QVZVHHX34RJ5XTMDXLG",
"type": "MTN 1.0GB SME Data",
"serviceid": "1",
"amount": "250.00",
"date": "2026-10-20 00:15:30"
}
How to Verify the Signature
To verify the authenticity of an incoming webhook on your server:
- Capture the incoming raw request body bytes before parsing JSON.
- Retrieve the
X-Inlomax-SignatureHTTP header from the request. - Compute the HMAC-SHA256 hash of the raw body using your configured Webhook Secret.
- Compare
sha256={computed_hash}with the received header using a timing-attack safe string comparison. - If the signature matches, process the webhook and return an HTTP
200 OKresponse. If it does not match, reject with HTTP401 Unauthorized.
PHP Implementation
<?php
// 1. Your webhook secret configured in Inlomax Dashboard
$webhookSecret = "YOUR_WEBHOOK_SECRET";
// 2. Read the raw unparsed request body
$rawPayload = file_get_contents('php://input');
// 3. Extract the X-Inlomax-Signature header
$signatureHeader = $_SERVER['HTTP_X_INLOMAX_SIGNATURE'] ?? '';
// 4. Verify signature if a secret is configured
if (!empty($webhookSecret)) {
$expectedSignature = 'sha256=' . hash_hmac('sha256', $rawPayload, $webhookSecret);
if (!hash_equals($expectedSignature, $signatureHeader)) {
http_response_code(401);
echo json_encode(["status" => "error", "message" => "Invalid webhook signature"]);
exit;
}
}
// 5. Signature is valid! Parse the JSON payload
$data = json_decode($rawPayload, true);
$reference = $data['reference'] ?? '';
$status = $data['status'] ?? '';
$amount = $data['amount'] ?? '';
// 6. Update your database and deliver value to your user...
// (Make sure your processing logic is idempotent based on $reference)
// 7. Always acknowledge receipt with 200 OK
http_response_code(200);
echo json_encode(["status" => "success"]);
?>
Node.js (Express) Implementation
const express = require('express');
const crypto = require('crypto');
const app = express();
const WEBHOOK_SECRET = 'YOUR_WEBHOOK_SECRET';
// Notice: capture raw body buffer for HMAC verification
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const rawPayload = req.body.toString('utf8');
const signatureHeader = req.headers['x-inlomax-signature'] || '';
if (WEBHOOK_SECRET) {
const expectedSignature = 'sha256=' + crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(rawPayload)
.digest('hex');
// Timing-safe comparison to prevent timing attacks
const isValid = crypto.timingSafeEqual(
Buffer.from(signatureHeader),
Buffer.from(expectedSignature)
);
if (!isValid) {
return res.status(401).json({ status: 'error', message: 'Invalid signature' });
}
}
// Parse verified payload
const event = JSON.parse(rawPayload);
console.log(`Transaction ${event.reference} status: ${event.status}`);
// Return 200 OK acknowledgment
res.status(200).json({ status: 'success' });
});
app.listen(3000, () => console.log('Webhook server running on port 3000'));
Python (Flask) Implementation
import hmac
import hashlib
from flask import Flask, request, jsonify
app = Flask(__name__)
WEBHOOK_SECRET = b"YOUR_WEBHOOK_SECRET"
@app.route('/webhook', methods=['POST'])
def handle_webhook():
raw_payload = request.get_data() # Raw bytes
signature_header = request.headers.get('X-Inlomax-Signature', '')
if WEBHOOK_SECRET:
expected_signature = 'sha256=' + hmac.new(
WEBHOOK_SECRET,
raw_payload,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected_signature, signature_header):
return jsonify({"status": "error", "message": "Invalid signature"}), 401
# Verified payload
data = request.get_json()
reference = data.get('reference')
status = data.get('status')
# Process transaction update...
return jsonify({"status": "success"}), 200
if __name__ == '__main__':
app.run(port=5000)