Webhooks
API ReferenceWebhooksSignature Verification
Signature Verification
Verify webhook authenticity using HMAC signatures.
How It Works
Signed webhook requests include an X-Webhook-Signature-512 header containing an HMAC-SHA512 signature of the raw request body. Verify this signature to ensure the webhook was sent by ReliancePays.
Do not verify against parsed or reserialized JSON, because even harmless formatting changes alter the signature input.
Verification Steps
- Extract the
X-Webhook-Signature-512header from the request - Compute an HMAC-SHA512 of the raw request body using your webhook secret
- Compare the computed signature with the one in the header
- Reject the request if signatures don't match
- Process each
event_idonce - Parse the JSON payload only after signature verification succeeds
Code Examples
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha512', secret)
.update(payload)
.digest('hex');
return signature.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
// In your webhook handler:
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-webhook-signature-512'];
if (!signature || !verifyWebhookSignature(req.body, signature, WEBHOOK_SECRET)) {
return res.status(400).send('Invalid signature');
}
// Process the event...
res.status(200).send('OK');
});import hmac
import hashlib
def verify_webhook_signature(payload, signature, secret):
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha512
).hexdigest()
return hmac.compare_digest(signature, expected)
# In your webhook handler:
@app.route('/webhooks', methods=['POST'])
def handle_webhook():
signature = request.headers.get('X-Webhook-Signature-512')
if not verify_webhook_signature(request.data, signature, WEBHOOK_SECRET):
return 'Invalid signature', 400
# Process the event...
return 'OK', 200<?php
function verifyWebhookSignature($payload, $signature, $secret) {
$expected = hash_hmac('sha512', $payload, $secret);
return hash_equals($expected, $signature);
}
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE_512'] ?? '';
if (!verifyWebhookSignature($payload, $signature, WEBHOOK_SECRET)) {
http_response_code(400);
echo 'Invalid signature';
exit;
}
// Process the event...
http_response_code(200);
echo 'OK';Always verify webhook signatures in production. Never skip verification, as it protects against forged webhook requests.