Webhook Not Receiving Data: A Step-by-Step Debugging Guide
When a webhook fails to deliver data, the issue typically lies in one of three areas: the sending provider, the network path, or the receiving server's configuration. Follow this systematic debugging guide to isolate and resolve the issue.
Step 1: Check the Provider's Delivery Logs
Most webhook senders (e.g., Stripe, GitHub, Shopify) provide a delivery log dashboard. Check this first to determine if the sender is attempting to dispatch the payload.
- No attempts recorded: The event trigger configuration is incorrect on the provider side. Verify that the specific events you want to monitor are selected.
- Failed attempts (Red/Error status): Note the HTTP status code returned by your server (e.g., 400, 403, 404, 500, or 502).
- Connection timeouts: Your server is not responding within the provider's timeout limit (usually 3 to 15 seconds).
Step 2: Isolate the Endpoint Using a Request Inspector
Rule out your server code by routing the webhook to a public request inspector like Webhook.site or RequestBin.
- Generate a temporary URL from Webhook.site.
- Update your webhook provider's destination URL to this temporary URL.
- Trigger the event.
If the inspector receives the data, your provider is working correctly; the issue lies in your network routing, firewall, or application code.
Step 3: Verify Network, DNS, and SSL/TLS Settings
Webhook providers require secure, publicly accessible endpoints. Verify the following network requirements:
- HTTPS Requirement: Most providers reject non-SSL (HTTP) endpoints or invalid/expired SSL certificates. Self-signed certificates are rarely accepted.
- Port Restrictions: Ensure your server listens on standard ports (
80or443). Many providers block custom ports like8080or5000. - Localhost Debugging: If debugging locally, use a tunneling tool like
ngrokorLocaltunnelto expose your local port to a public HTTPS URL:
ngrok http 3000
Step 4: Inspect Firewall and Reverse Proxy Logs
If the provider logs show a timeout or a 502/504 Bad Gateway, your server or reverse proxy (Nginx, Apache, Cloudflare) may be blocking the incoming traffic.
- Check your Nginx/Apache access and error logs (usually located in
/var/log/nginx/or/var/log/apache2/). - Verify that your firewall (UFW, AWS Security Groups) allows incoming traffic on port 443 from the provider's IP ranges.
- Disable Web Application Firewall (WAF) rules temporarily to see if they are flagging the webhook payload as suspicious.
Step 5: Debug Application Code and Payload Parsing
If your server receives the connection but returns a 400 (Bad Request) or 500 (Internal Server Error), the issue is in your application logic. A common culprit is failing to parse the incoming request body correctly.
Here is a robust Node.js/Express template designed to log incoming headers and raw body data for debugging:
const express = require('express');
const app = express();
// Use express.json() but preserve raw body for signature verification if needed
app.use(express.json({
verify: (req, res, buf) => {
req.rawBody = buf.toString();
}
}));
app.post('/webhook', (req, res) => {
console.log('--- Incoming Webhook ---');
console.log('Headers:', req.headers);
console.log('Body:', req.body);
// Always return a 200 OK immediately to acknowledge receipt
res.status(200).send('Webhook received');
});
app.listen(3000, () => console.log('Webhook receiver listening on port 3000'));
Ensure your endpoint returns a 200 OK or 202 Accepted status code immediately before running heavy background processes, as delayed responses trigger timeout errors and retries from the provider.
Need this done fast? order a fix on Kwork.
I take on freelance fixes and builds in this area.