Skip to main content
That’s Me signs every webhook payload using HMAC-SHA256. Always verify the signature before processing the payload.

Signature format

The X-TM-Signature header contains:
t=1711234567,v1=abc123def456...
  • t — Unix timestamp of the delivery
  • v1 — HMAC-SHA256 of timestamp.payload_body using your endpoint secret

Verification examples

import { createHmac, timingSafeEqual } from 'crypto';

function verifyWebhookSignature(
  payload: string,
  signature: string,
  secret: string,
): boolean {
  const parts = Object.fromEntries(
    signature.split(',').map(p => p.split('='))
  );
  const timestamp = parts['t'];
  const expected = createHmac('sha256', secret)
    .update(`${timestamp}.${payload}`)
    .digest('hex');

  return timingSafeEqual(
    Buffer.from(`v1=${expected}`),
    Buffer.from(`v1=${parts['v1']}`)
  );
}
Always use a timing-safe comparison (timingSafeEqual / hmac.compare_digest) to prevent timing attacks.