Developer guide

How to verify webhook signatures

Every webhook from Capay Global is signed. Checking the signature takes a few lines and stops anyone from faking a payment completed event.

Updated October 7, 2026

Verify a delivery in Node.js

verify-capay-webhook.js
import crypto from 'node:crypto';

// rawBody: the exact bytes received, as a string. header: X-Capay-Signature.
export function verifyCapayWebhook(rawBody, header, secret) {
  const parts = header.split(',').map((p) => p.trim().split('='));
  const t = parts.find(([k]) => k === 't')?.[1];
  const sigs = parts.filter(([k]) => k === 'v1').map(([, v]) => v);
  if (!t || Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;

  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${t}.${rawBody}`)
    .digest('hex');

  return sigs.some(
    (s) =>
      s.length === expected.length &&
      crypto.timingSafeEqual(Buffer.from(s), Buffer.from(expected)),
  );
}

Step by step

  1. 1Keep the raw bodyVerify against the exact bytes you received. Parsing the JSON first and serialising it again changes the bytes, and the check fails.
  2. 2Read the signature headerX-Capay-Signature has the form t=<unix time>,v1=<hex>. During a secret rotation it carries two v1 values: accept the delivery if either one matches.
  3. 3Recompute the HMACCompute HMAC-SHA256 with your endpoint's whsec_ signing secret over the timestamp, a dot and the raw body.
  4. 4Compare safely and check the ageCompare in constant time and reject any delivery whose timestamp is more than 300 seconds away from now.
  5. 5Process each event onceFailed deliveries are retried, so the same event can arrive more than once. Keep the X-Capay-Event-Id you have processed and ignore repeats.

Frequently asked questions

Where do I find the signing secret?

In the dashboard under Webhooks. Each endpoint has its own whsec_ secret, separate from your API keys.

What should my endpoint answer when verification fails?

Return an error status and do not act on the event. Only a verified delivery should change an order.

Which headers come with a delivery?

X-Capay-Signature, X-Capay-Event-Id and X-Capay-Event-Type.

Start in the sandbox today

Free, unlimited and open the moment you sign up. Live payments open after business verification.