NOCK
API

Verify Webhook Signatures

Validate NOCK webhook requests with HMAC-SHA256 before triggering side effects.

Every NOCK webhook includes a signature so your endpoint can prove the request came from NOCK and was not modified in transit.

Signature format

NOCK sends:

x-nock-signature: t=<timestamp>,v1=<hex_hmac>
x-nock-timestamp: <timestamp>

The HMAC message is:

<timestamp>.<raw request body>

The algorithm is HMAC-SHA256 using the endpoint signing secret shown when the webhook is created.

Node.js verification

import { createHmac, timingSafeEqual } from 'node:crypto';

export function verifyNockWebhook({
  rawBody,
  secret,
  signatureHeader,
  timestampHeader,
}: {
  rawBody: string;
  secret: string;
  signatureHeader: string;
  timestampHeader: string;
}) {
  const timestamp = Number(timestampHeader);
  if (!Number.isFinite(timestamp)) return false;

  const ageSeconds = Math.abs(Date.now() / 1000 - timestamp);
  if (ageSeconds > 300) return false;

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

  const received = signatureHeader
    .split(',')
    .find((part) => part.startsWith('v1='))
    ?.slice(3);

  if (!received) return false;

  const receivedBuffer = Buffer.from(received, 'hex');
  const expectedBuffer = Buffer.from(expected, 'hex');
  if (receivedBuffer.length !== expectedBuffer.length) return false;

  return timingSafeEqual(receivedBuffer, expectedBuffer);
}

Implementation checklist

  • Read the raw request body before parsing JSON.
  • Reject requests older than 5 minutes.
  • Use constant-time comparison for the HMAC.
  • Use x-nock-delivery or payload id for idempotency.
  • Return a 2xx response only after your consumer has accepted the event.

Warning

Do not verify against a prettified or re-stringified JSON body. The signature is calculated over the exact raw body bytes sent by NOCK.

On this page