Webhooks
Verify signatures
Prove that a delivery really comes from Whazzup.
Signature header
Every delivery includes X-Whazzup-Signature in the format t=<unix seconds>,v1=<hmac>. The value v1 is the hex HMAC-SHA256 of the string t + "." + raw request body, keyed with your endpoint secret.
Verify
- Read the raw request body and the
X-Whazzup-Signatureheader. - Check the timestamp
tis recent (for example within 5 minutes) to block replays. - Compute HMAC-SHA256 of
t + "." + bodywith your secret. - Compare with
v1using a timing-safe comparison. Reject mismatches with 401.
Examples
Node.js
import { createHmac, timingSafeEqual } from "crypto";
function isValid(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(",").map(p => p.split("=")));
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
const expected = createHmac("sha256", secret)
.update(`${parts.t}.${rawBody}`)
.digest("hex");
return timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
}Python
import hmac, hashlib, time
def is_valid(raw_body: bytes, header: str, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
if abs(time.time() - int(parts["t"])) > 300:
return False
expected = hmac.new(
secret.encode(),
parts["t"].encode() + b"." + raw_body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(parts["v1"], expected)