Webhooks fail differently from normal code. A broken API call fails in front of you — red text, stack trace, right now. A broken webhook fails somewhere else, later, silently: Stripe sent the payment event, your endpoint 302'd it into the void, and you find out three weeks later when the numbers don't reconcile. A webhook tester exists to move that discovery from "three weeks later, in accounting" to "right now, on your screen." Here's how to use one properly, and the five failure modes that account for most webhook pain in production.
A normal API call: you send the request, you control the timing, you see the response. A webhook flips it — the other system calls you when something happens. Payment settled, repo pushed, form submitted, message received. That reversal is why webhooks power everything event-driven, and why they're miserable to debug: you don't control when the request comes, you can't set a breakpoint in Stripe's servers, and if your endpoint misbehaves, the evidence lives in someone else's dashboard.
Testing therefore has two directions. Inbound: catch what a provider actually sends you — inspect the headers, body, and signature of a real delivery. Outbound: simulate the provider — craft a payload and fire it at your endpoint to see how your code behaves. Our free webhook tester does the outbound half in the browser: build the request, describe the event in plain English and let it draft the JSON, send, inspect what came back.
Your site redirects http to https, or apex to www. Fine for browsers — fatal for webhooks. Most providers treat any 3xx as a failure and do not follow it; Stripe, notably, marks redirected deliveries as failed. The webhook "works" when you test the URL in a browser (which follows the redirect) and fails from the provider. The test: send a request to the exact configured URL and confirm you get a direct 200, not a 301 hop. Our status code guide covers why the difference matters; the fix is registering the final URL, exactly.
Providers give you seconds — often 5 to 10 — to respond before marking the delivery failed and scheduling a retry. The classic sin is doing real work in the handler: generate the invoice PDF, send the email, update three tables, then return 200. Load rises, the handler takes 12 seconds, the provider times out, retries pile onto an already-slow system, and now you're processing every event twice while falling further behind. The pattern that survives production: acknowledge fast, process async. Receive, validate the signature, queue the payload, return 200 in milliseconds. Everything else happens off the request path.
Every serious provider delivers at least once — meaning duplicates are guaranteed by design. Network blips, timeout retries, provider-side redelivery: the same event will arrive twice, eventually. If your handler isn't idempotent, that's double-shipped orders and double-sent emails. The fix is small: store each event ID, skip ones you've seen. Test it by firing the identical payload twice with your tester and confirming the second is a no-op. Teams that skip this test find out via a customer email that starts with "why was I charged twice."
An unverified webhook endpoint is an open door that accepts JSON — anyone who finds the URL can forge events. Providers sign deliveries (usually HMAC over the raw body plus a timestamp) so you can verify authenticity. Two implementation traps: verifying against the parsed-then-reserialized body instead of the raw bytes (your JSON library reorders keys, the HMAC no longer matches — this is the number one "signatures randomly fail" cause), and skipping the timestamp check, which leaves you open to replayed captures. Verify raw bytes, reject stale timestamps, and test with a deliberately wrong signature to confirm you actually reject it.
When a provider says "delivered, 200" and your database says otherwise, you need your own record to settle the argument. Log every inbound delivery — headers, body, timestamp, your response — before any processing. Storage is cheap; a reconciliation argument with a payment provider without receipts is not.
Webhook payloads are business events: payments, signups, messages. Piping them through third-party inspection services means a stranger holds a copy of your event stream. Fine for a hello-world test; questionable for production traffic. This is the design bias behind QADIR OS — agents that receive, inspect, and route events on your machine, with gateways for the channels you use and memory that persists locally. Your event stream is your business telling you what's happening; it should report to you, not to a middleman.
Test the five failure modes today. Fire real payloads at your endpoint with the free webhook tester, and grab the matching cURL command for your CI checks. Want the whole event loop running locally? Join early access — no card required.