That’s Me signs every webhook payload using HMAC-SHA256.
Always verify the signature before processing the payload.
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.