Verifying signatures
Check the X-WRMS-Signature header so your endpoint only accepts requests that really came from WRMS Pro, and rejects replays.
Audience:Developer
Anyone can send a request to your endpoint. The signature proves it came from WRMS Pro, using the secret only you and WRMS Pro know.
How the signature is made
The X-WRMS-Signature header looks like this:
t=1790000000000,v1=3b0f8f0a4cā¦tis the time the request was signed, in milliseconds since 1 January 1970 (UTC).v1is the HMAC-SHA256 of the string<t>.<raw request body>, keyed with your webhook's signing secret, written as lowercase hexadecimal.
Verify it
- Read the raw request body exactly as received, before any JSON parsing.
- Split the header on
,and=to gettandv1. - Reject the request if
tis more than 5 minutes from your current time. - Compute HMAC-SHA256 of
t + "." + rawBodywith your secret. - Compare it with
v1using a constant-time comparison. Reject if they differ. - Respond
2xxquickly, then process the event.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyWrmsSignature(rawBody, header, secret, toleranceMs = 5 * 60 * 1000) {
const parts = Object.fromEntries(header.split(',').map((kv) => kv.split('=')));
const t = Number(parts.t);
const v1 = (parts.v1 ?? '').toLowerCase();
if (!Number.isFinite(t) || !v1) return false;
if (Math.abs(Date.now() - t) > toleranceMs) return false;
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(v1);
return a.length === b.length && timingSafeEqual(a, b);
}Common mistakes
- Parsing the JSON first. Re-serialising changes whitespace and key order, so the signature no longer matches. Sign-check the raw bytes.
- Treating
tas seconds. It is milliseconds. - Using the wrong secret after rotating it. Rotation takes effect immediately.
- Clock drift. Keep your server's clock synchronised, or requests fall outside the 5-minute window.
Avoid processing twice
A retried delivery has the same X-WRMS-Delivery ID and the same event id. Store IDs you have processed and skip repeats.
Still need help?
Email support@wrmspro.com or use the contact form. Signed-in users can also send a request from Settings ā Support.