Skip to main content

Testing Webhook Receivers

Webhooks are hard to test for one structural reason: the requests come from someone else's system, on their schedule. You cannot click a button in your own test suite and have Stripe send you a real payment event. Testing webhook receivers is therefore mostly about recreating the sender's behavior, including its failure modes, in environments you control.

This guide covers the practical setup: receiving webhooks during local development, simulating events and failures, automating the tests in CI, and checking the security properties that webhook endpoints need.

Building webhooks?
Svix is the enterprise ready webhooks sending service. With Svix, you can build a secure, reliable, and scalable webhook platform in minutes. Looking to send webhooks? Give it a try!

What arrives at your endpoint

A webhook delivery is an HTTP request, almost always a POST, sent to the webhook URL you registered. The body carries the event data as JSON, and the headers carry metadata: a Content-Type, usually a signature header for verification, and often a unique message ID and timestamp. Everything in this guide comes down to making sure your webhook endpoint handles that request correctly, including when the request is malformed, delayed, duplicated, or forged.

Receiving webhooks locally

The awkward part of local development is that webhook senders need a publicly reachable URL, and your laptop doesn't have one. There are two standard ways around this.

Tunneling tools like ngrok or the Svix CLI expose your local server through a temporary public URL, so real deliveries reach the code running in your editor. This is the fastest path to debugging actual payloads; our guide to testing webhooks locally walks through the setup.

Alternatively, capture tools like Svix Play give you a hosted URL that records every delivery it receives, letting you inspect headers and payloads without running anything. This is the right tool when you want to see what a sender actually sends before writing any code.

For staging environments, the same principles apply with one addition: keep the staging receiver isolated from production data and configuration, because webhook handlers by design trigger side effects.

Simulating events and failures

Once you can receive deliveries, the question becomes coverage. Replaying a happy-path event is easy with curl or Postman: capture a real payload once, then send it to your endpoint whenever you need it. The tests that actually catch bugs are the unhappy paths, because that is where webhook systems differ from ordinary HTTP APIs.

Test your endpoint against malformed payloads and unexpected event types; a receiver should reject or ignore them without crashing. Test duplicate deliveries by sending the same event twice, since retries make duplicates a normal occurrence that your handler must absorb idempotently. Test slow responses by adding artificial delay to your handler and confirming the sender's timeout and retry behavior does what you expect. And test the retry schedule itself by returning a 500 from your endpoint and watching when redeliveries arrive, so you know your real-world recovery window.

Automating webhook tests in CI

Manual testing catches integration problems; automated tests keep them from coming back. The most useful automated tests treat your webhook handler as a function: construct a request with a known payload and a valid signature, run it through the handler, and assert on the side effects. This requires generating signatures in your test code with a test secret, which is worth the small setup cost because it means signature verification stays enabled in tests instead of being mocked out, and broken verification fails your build instead of production.

Beyond handler-level tests, a small end-to-end suite that boots the service and posts realistic deliveries to the actual HTTP endpoint catches routing, middleware, and body-parsing regressions that unit tests miss. Raw-body handling is a classic one: signature verification needs the exact bytes that arrived, and a framework middleware that re-serializes JSON will break it in ways only an end-to-end test notices.

Security testing

A webhook endpoint is a public URL that accepts POSTs, so test it like an attacker would. Send unsigned requests and confirm they are rejected. Send correctly signed requests with stale timestamps and confirm they are rejected too, since that is your replay-attack protection. Confirm the endpoint is HTTPS-only, that payloads are handled as untrusted input, and that oversized bodies are rejected rather than buffered indefinitely. If you use scanning tools like OWASP ZAP in your pipeline, include the webhook routes; they are easy to forget because no browser ever visits them.

Monitoring: testing that never stops

Production traffic will eventually produce a case your tests didn't. Log every delivery with its headers, verification result, and processing outcome, and track failure rate and processing latency over time. Alerting on a spike in verification failures or a growing backlog catches sender-side changes and receiver-side regressions long before customers notice missing data. Our webhook monitoring guide covers what to measure and when to alert.

Troubleshooting quick reference

When a webhook integration misbehaves, isolate which side is failing. If the sender's dashboard shows no delivery attempt, the problem is upstream: check the event actually fired and the endpoint is registered. If deliveries show as failed, read the response code the sender recorded: 4xx points at verification or parsing in your handler, 5xx at your infrastructure, and timeouts at slow processing. If deliveries succeed but data is wrong or missing, capture the raw payload with a tool like Svix Play and compare it against what your handler expects. The failure almost always becomes obvious once you are looking at the actual request instead of your assumptions about it.