Glossary
2xx Response (Acknowledgement)
The HTTP status your endpoint returns to tell the provider a webhook was received. Anything outside 2xx — or a slow response — counts as failure and triggers retries.
The webhook contract is brutally simple: return 2xx quickly and the provider marks the event delivered; return anything else — 4xx, 5xx, a redirect, or nothing before the timeout — and it schedules a retry. Providers don't read your response body; the status code is the entire conversation.
Timeouts are tighter than most handlers assume: Stripe allows ~20 seconds, Shopify 5, Slack 3. Doing real work inline (DB writes, API calls, PDF generation) is the classic way to blow the window and get retried for events you actually processed. The fix is ack-then-process: persist the raw event to a queue or table, return 200, and do the work asynchronously.
The one caveat: return 2xx only after the event is *durably* stored. A handler that returns 200 and then crashes before persisting has told the provider 'delivered' about an event that no longer exists anywhere.
Ack-then-process: acknowledge fast, work async
app.post("/webhooks", express.raw({ type: "*/*" }), async (req, res) => {
verifySignature(req.body, req.header("Stripe-Signature"));
await queue.enqueue(req.body); // durable first
res.sendStatus(200); // then acknowledge
});How HookSense helps
Every HookSense endpoint answers 2xx in milliseconds and lets you configure the exact status, body, and headers per endpoint — so an agent can simulate a 500 or a slow handler with `replay_callback` and watch how the provider's retry schedule actually behaves.
Get a free webhook URL