v2.4 CURRENT PROTOCOLHMAC-SHA256

Webhook Signature Verification

The HMAC-SHA256 signature verification steps that prove an Incapon webhook event is genuine and keep unauthorised calls out.

How Does It Work? (Summary)

Inspect the Request Header

Incapon adds the x-incapon-signature header to every webhook call.

Compute the HMAC-SHA256 Digest

Sign the raw body you received with the webhook secret you copied from the dashboard.

Check the Timestamp and the Match

The timestamp tolerance is 300 seconds (this protects against replay attacks).

Incoming HTTP Headers

x-incapon-signatureRequired
t=1710418800,v1=9a8f4c2e...4e1b882d

Signature digest produced with HMAC SHA-256, plus the timestamp.

x-incapon-timestampRequired
1710418800

The moment the request was created, in Unix epoch seconds.

x-incapon-event-idUnique
evt_live_89124a9c_f901

Event ID for idempotency checks and for dropping repeated requests.

Implementation Code

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  const digest = hmac.update(payload).digest('hex');

  // Timing-safe equality check
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(digest)
  );
}

Things to Watch Out For

Use the Raw Body!

Sign the raw string from before JSON parsing (JSON.parse); otherwise whitespace differences and key ordering break the signature.

Constant-Time Comparison

To block timing attacks, always prefer the timingSafeEqual function over a plain ===.

Next Steps & Guides

Was this guide helpful?

Your feedback helps us improve our documentation.