Skip to main content
Here are common webhook issues and how to resolve them.

Signature Verification Failing

Not Using Raw Payload Body

Problem: When generating the signature, we use the raw string body of the message payload. If you parse the JSON and then stringify it, the signature won’t match. Solution: Always use the raw request body exactly as received:
// WRONG - parsing and re-stringifying changes the format
const payload = JSON.parse(body);
verify(JSON.stringify(payload), headers); // Will fail!

// CORRECT - use the raw body
verify(rawBody, headers);

Wrong Secret Key

Problem: Using the wrong webhook secret or not properly decoding it. Solution:
  • Ensure you’re using the correct secret for each endpoint (secrets are unique per endpoint)
  • Remove the whsec_ prefix before base64 decoding

Timestamp Expired

Problem: Your server’s clock is out of sync, causing valid webhooks to be rejected. Solution: Ensure your server’s time is synchronized using NTP.

Webhooks Not Being Received

Endpoint Not Accessible

Problem: Your endpoint isn’t publicly accessible. Solution:
  • Ensure your server is running and the endpoint URL is correct
  • Check firewall rules allow incoming HTTPS requests
  • Verify the endpoint works with a simple curl test

SSL/TLS Issues

Problem: Invalid or expired SSL certificate. Solution: Ensure your endpoint has a valid SSL certificate from a trusted CA.

Wrong Response Codes

Returning Errors for Successful Processing

Problem: Returning non-2xx status codes even when the webhook was processed successfully. Solution: Always return a 2xx status code when you’ve successfully received and queued the webhook for processing:
// CORRECT
app.post('/webhooks', (req, res) => {
  queue.add(req.body); // Add to queue for async processing
  res.status(200).send('OK'); // Acknowledge immediately
});

Timeouts

Processing Takes Too Long

Problem: Your endpoint takes more than 15 seconds to respond. Solution: Process webhooks asynchronously:
app.post('/webhooks', async (req, res) => {
  // Don't do this - blocks the response
  // await processOrder(req.body);
  
  // Do this instead - queue for background processing
  await queue.add('process-webhook', req.body);
  res.status(200).send('OK');
});

Failure Recovery

Re-enable Disabled Endpoint

If your endpoint was disabled after consecutive failures:
  1. Fix the underlying issue
  2. Go to Settings > Webhooks in the dashboard
  3. Click Enable Endpoint on the disabled endpoint

Replay Failed Messages

To recover missed webhooks after an outage:
  1. Go to your endpoint details
  2. Click Options > Recover Failed Messages
  3. Select the time range to replay
Check the webhook logs in your dashboard for detailed error messages and response codes from your endpoint.