logo

Webhook Configuration & Security

Portal Configuration (Mandatory)

  • Required: Configure your Webhook URL and Webhook Secret in the Merchant Portal (Integration → Webhooks)
  • These settings serve as the default for all transactions
  • The webhook secret is used to generate HMAC SHA256 signatures for webhook verification
  • You must configure a webhook URL to receive payment notifications

Request-Level Override

  • You can optionally provide a callback_url in individual API requests
  • If callback_url is provided, it overrides the portal-configured webhook URL for that specific transaction
  • If callback_url is not provided, the portal-configured webhook URL is used
  • The webhook secret from the portal is always used for signature generation (if configured)

Security

  • Validate incoming webhook requests by checking the source IP and/or using a shared secret
  • Verify HMAC SHA256 signatures using the X-Webhook-Signature header (if webhook secret is configured)
  • Handle duplicate webhook deliveries idempotently using reference or trace_number

Webhook Signature Verification

Important: Always verify webhook signatures to ensure the request is authentic and prevent replay attacks.

Steps to verify

  1. Extract the X-Webhook-Signature and X-Webhook-Timestamp headers from the incoming request
  2. Get the raw request body (JSON string) and sort the keys alphabetically
  3. Create a message string: {timestamp}.{sorted_payload_json}
  4. Compute HMAC SHA256: HMAC_SHA256(message, webhook_secret)
  5. Compare the computed signature with the X-Webhook-Signature header using constant-time comparison
  6. Validate the timestamp to prevent replay attacks (recommended: 5-minute tolerance)

Code Examples

Request
curl -X POST "https://your-server.com/webhook" \
  -H "Content-Type: application/json" \
  -H "X-Webhook-Signature: your_signature" \
  -H "X-Webhook-Timestamp: 1234567890" \
  -d '{
  "event": "payment.completed",
  "reference": "ABC123",
  "amount": 1000,
  "status": "SUCCESS"
}'

Security Best Practices

  • Always use constant-time comparison functions (hmac.compare_digest in Python, crypto.timingSafeEqual in Node.js) to prevent timing attacks
  • Validate the timestamp to prevent replay attacks (recommended: reject requests older than 5 minutes)
  • Store your webhook secret securely (environment variables, secret management service)
  • Never log or expose the webhook secret
  • Return 401 Unauthorized if signature verification fails