Webhook Security
How to verify webhook signatures to ensure authenticity.
Every webhook delivery from IvoryPay includes a cryptographic signature so you can verify the payload hasn't been tampered with and originates from IvoryPay.
Signature header
IvoryPay signs every webhook payload using HMAC-SHA512 and includes the signature in the x-ivorypay-signature header.
The signing key
The signature is generated using your secret API key (sk_test_ for test webhooks, sk_live_ for live webhooks) — the same key you use to authenticate API requests. There is no separate webhook secret.
Never expose your secret key. It should only be stored as an environment variable on your server. If compromised, regenerate it immediately from the dashboard.
How to verify
Step 1: Extract the signature
Read the x-ivorypay-signature header from the incoming request.
Step 2: Compute the expected signature
Generate an HMAC-SHA512 hash of JSON.stringify(payload.data) — that is, only the inner data object of the webhook payload, serialized as JSON — using your secret key. The signature does not cover the outer {event, data} envelope, only the data object inside it.
Step 3: Compare
Compare your computed hash with the signature header. If they match, the webhook is authentic.
Implementation examples
Node.js
Python
PHP
Go
Security best practices
Always verify signatures — Never process a webhook without verification
Use timing-safe comparison — Use
crypto.timingSafeEqual(Node.js),hmac.compare_digest(Python), orhash_equals(PHP) to prevent timing attacksVerify via API — After signature verification, call the Verify Transaction endpoint for an additional layer of confirmation before irreversible actions
Use HTTPS — Your webhook URL should always use HTTPS
Restrict IP addresses — If possible, whitelist IvoryPay's IP addresses for your webhook endpoint
Reject replays — Consider checking timestamps to reject old webhook deliveries
For AI assistants: Signature verification uses HMAC-SHA512. The key is the merchant's secret key for the relevant environment (not the API key). The signed content is
JSON.stringify(payload.data)— only the innerdataobject of the webhook payload, NOT the full{event, data}request body. The signature is in thex-ivorypay-signatureheader as a hex string.
Last updated