Webhook 401 Unauthorized Error — Causes and Fixes
A step-by-step guide to diagnosing and resolving webhook authentication failures across bearer tokens, API keys, HMAC signatures, and custom auth schemes.
Quick Answer
A 401 means the webhook request was rejected because authentication failed — the token, API key, or signature was missing, expired, or incorrect. The sender needs to fix their credentials and retry.
What a Webhook 401 Error Means
HTTP 401 Unauthorized is an authentication challenge. It tells the requester: "I don't know who you are, or the credentials you sent are not valid." The server couldn't verify the identity of the sender.
It is important to distinguish 401 from 403. A 401 means authentication failed entirely — no valid identity was established. A 403 Forbidden means authentication succeeded but the authenticated identity doesn't have permission to access that resource. If you get 401, the problem is always in the credentials themselves.
In webhook contexts, a 401 typically means the endpoint requires some form of verification — a secret token, a signed payload, or an API key — and the incoming request either omitted it or sent the wrong value.
Why Webhooks Return 401
The most common causes of a webhook 401 are:
- The
Authorizationheader is missing entirely from the request. - The token format is wrong — for example, sending
Bearerwhen the server expects a raw key, or vice versa. - The token has expired and the sender hasn't refreshed it.
- The signing secret used to generate an HMAC signature doesn't match the secret configured on the receiving end.
- The header name is wrong — some providers use
X-Token,X-Api-Key, orX-Webhook-Secretinstead ofAuthorization. - The token was rotated or regenerated after the webhook was registered, but the new value wasn't saved.
- The webhook endpoint is receiving the payload after it passes through a proxy that strips auth headers.
How to Debug a Webhook 401 with Requex
The fastest way to debug a 401 is to capture the actual request before it reaches your protected endpoint. Requex gives you a public URL that accepts any HTTP request and displays the full headers, body, and query parameters in real time.
- Open Requex and copy the generated webhook URL.
- Point your webhook provider to the Requex URL instead of your real endpoint.
- Trigger a test event from the provider dashboard.
- In Requex, open the captured request and expand the Headers section.
- Look for the
Authorizationheader (or whatever header the provider uses). Check the exact value that arrived. - Compare that value with what your endpoint expects. The mismatch will usually be obvious.
This approach works because it captures what the provider actually sent — not what you assumed it sent. Proxy stripping, URL encoding differences, and whitespace issues all become visible at this step.
Fix Checklist
- ✓Confirm the Authorization header (or custom auth header) is present in the captured request.
- ✓Check whether the bearer token has expired and needs to be refreshed.
- ✓Verify the webhook signing secret on the receiving end matches what the provider has configured.
- ✓For HMAC: confirm you are computing the signature over the raw request body, not the parsed JSON.
- ✓Check the exact header name the provider sends — it may be
X-Signature-256notAuthorization. - ✓If credentials were recently rotated, update both the provider configuration and your endpoint secret at the same time.
- ✓Check for any reverse proxy or load balancer that may be stripping the auth header before it reaches your app.
Common Auth Methods and What to Check
Different platforms use different authentication approaches. Here is what to inspect for each:
| Method | Header | What to Check |
|---|---|---|
| Bearer Token | Authorization: Bearer TOKEN | Token value matches exactly, token hasn't expired |
| API Key | X-Api-Key: KEY | Key hasn't been rotated, header name matches provider docs |
| HMAC Signature | X-Hub-Signature-256 | Secret matches, algorithm is correct, raw body used (not parsed) |
| Basic Auth | Authorization: Basic BASE64 | Username and password both correct, base64 encoding is right |
| Custom Header | X-Webhook-Secret: VALUE | Header name and value both match provider configuration |
Example: HMAC Verification
HMAC-based auth is the most common source of 401 errors because the signature is computed from the raw request body. Parsing the JSON first and then re-serializing it will produce a different byte sequence and a different signature.
// Node.js — correct HMAC verification
const crypto = require('crypto');
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-hub-signature-256'];
const expected = 'sha256=' + crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(req.body) // req.body is raw Buffer here — not parsed JSON
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).json({ error: 'Invalid signature' });
}
const payload = JSON.parse(req.body);
// process payload...
res.status(200).json({ received: true });
});The key detail: use express.raw() (not express.json()) for the webhook route so that req.body is the unmodified raw buffer.
Related Errors
403 Forbidden
Authentication passed (the identity was verified) but the authenticated identity doesn't have permission to access the resource. See the webhook 403 error guide.
429 Too Many Requests
Auth succeeded but you've exceeded the rate limit. The endpoint is rejecting requests temporarily due to volume, not credentials. See the webhook 429 rate limit guide.
Related Resources
Webhook 403 Forbidden
Authenticated but still blocked — IP restrictions, scopes, permissions
Webhook Authentication Guide
Complete guide to securing webhooks with tokens and signatures
Webhook Security Best Practices
Broader security checklist for production webhook endpoints
Debug Webhook Errors
General troubleshooting guide for all webhook error types
Inspect the Exact Auth Headers Your Provider Sends
Capture the real request with Requex to see every header your provider sends — including the exact auth value — before it reaches your protected endpoint.
Open Requex →