Genesys webhook signature verification failing on replay attempts

Our Node.js consumer is rejecting valid Genesys Cloud events because the HMAC SHA256 verification fails when we try to block replay attacks. We’re checking the X-Genesys-Signature header against the payload, but the timing window seems too tight or the header format is off. Here’s the verification logic:

const crypto = require('crypto');
const signature = req.headers['x-genesys-signature'];
const timestamp = parseInt(req.headers['x-genesys-timestamp']);
const body = req.body;

if (Date.now() - timestamp > 30000) {
 return res.status(401).send('Replay attack suspected');
}

const hmac = crypto.createHmac('sha256', WEBHOOK_SECRET);
hmac.update(`${timestamp}.${body}`);
const expected = hmac.digest('hex');

if (signature !== expected) {
 return res.status(403).send('Invalid signature');
}

The signature matches if I remove the timestamp check, but that defeats the purpose. Am I formatting the payload string incorrectly for the HMAC?