Wernzi Tools

Wernzi Tools Guide

What Is a Webhook and How to Test One

Webhooks let apps notify each other in real time when something happens. Learn how webhooks work, what a payload looks like, and how to test and debug them.

By Wernzi Tools team · Published November 7, 2026 · 6 min read · Updated November 2026

Most of the time, when one app wants information from another, it asks. It sends an API request and waits for a reply, and if it wants to know whether anything changed, it has to ask again — and again. That pattern is called polling, and it works, but it is wasteful: most of those requests come back with the same answer, "nothing new", and the one time something does change, you only find out at the next check.

A webhook flips this around. Instead of polling for updates, you give the other app a URL and say: when something happens, call me. The event comes to you the moment it happens — a payment that triggers an order confirmation, a code push that starts a deployment, a form submission that posts a message to your team chat. This guide explains how webhooks work, what the messages they send look like, and how to test and debug them safely.

How a webhook works

A webhook is simply an HTTP request that one application sends to another when a specific event occurs. You start by registering a URL — your webhook endpoint — in the dashboard of the service that produces the events, and you choose which events you care about. From then on, whenever one of those events happens, the service sends an HTTP POST request to your URL with the details of the event in the body.

Your endpoint is a normal web server route. It receives the request, reads the payload, does whatever the event requires — updating a database, sending an email, kicking off a build — and answers with an HTTP status code. A 2xx response means "received, thank you". Anything else, or a timeout, usually tells the sender the delivery failed, and most providers will retry the event a few times before giving up.

What a webhook payload looks like

The body of a webhook request is almost always JSON, and it follows a predictable shape: a field naming the event type, a timestamp, a unique event ID, and a data object with the details. A payment webhook, for example, might carry the event type "payment.succeeded", the amount, the currency, the customer ID and the payment reference. Your code reads the event type first and decides what to do with the rest.

Two details deserve attention. First, the event ID: providers can deliver the same event more than once, especially after a retry, so record the IDs you have already processed and ignore duplicates. Handling the same payment twice could charge a customer twice. Second, the payload is a snapshot, not a live query — if you need the freshest state, use the IDs in the payload to fetch the current record from the API.

{
  "id": "evt_9F2K7Q1X",
  "type": "payment.succeeded",
  "created": 1762406400,
  "data": {
    "amount": 4999,
    "currency": "usd",
    "customer": "cus_8D3M2P",
    "payment_id": "pay_4H7K9Q"
  }
}

Webhooks vs polling vs APIs

Polling and webhooks solve the same problem — "tell me when something changes" — in opposite ways. Polling is simple and robust: you control the timing, you need no public URL, and nothing can push unexpected data at you. Its costs are delay and waste: you learn about an event only at your next poll, and most polls return nothing. For a dashboard that refreshes every minute, that is fine. For a payment that should trigger an instant confirmation email, it is not.

Webhooks are the right choice when events are infrequent but time-sensitive, and when you can expose a public HTTPS endpoint to receive them. APIs are for on-demand questions — "what is the current status of order 123?" — while webhooks are for announcements: "order 123 was just paid". Many real systems combine all three: webhooks for instant notification, the API for fetching details, and polling as a safety net in case a delivery was missed.

How to test a webhook

Testing a webhook is harder than testing a normal API because your code does not make the request — the provider does. The practical way to test is to watch the requests arrive. Use a request-inspection service that gives you a temporary public URL, point the provider at it, trigger a test event from the provider dashboard, and read the exact request: headers, body and timing. That shows you precisely what your endpoint will receive in production.

Then test the failure cases, because they are where webhooks break. Send a payload with a bad signature and confirm your endpoint rejects it. Send malformed JSON and confirm it does not crash. Make your endpoint slow on purpose and check that the provider retries. And verify your responses: return a 200 status quickly, before doing any slow work, so the provider does not treat a slow handler as a failed delivery. To understand the response codes you see while testing, check what each HTTP status code means; to inspect a captured payload, paste it into a JSON formatter and read it in a readable form.

  • Start with the provider's test-event button — it sends a realistic sample payload.
  • Capture a real request first, then build your handler against what you actually received.
  • Return 2xx fast, and do slow work (emails, database writes) afterwards.
  • Test duplicate deliveries: your handler must be safe to run twice.

Security: verify the signature

Anyone on the internet can send an HTTP POST to your webhook URL, so you must prove each request really came from the provider. Providers solve this with a signature: they compute an HMAC of the request body using a shared secret and send the result in a header. Your endpoint recomputes the same HMAC with your copy of the secret and compares the two. If they match, the request is genuine; if not, reject it.

A few more rules keep webhooks safe. Always use HTTPS so the payload and signature cannot be read or altered in transit. Check the timestamp in the payload to reject old, replayed requests. Keep the shared secret out of your source code — load it from an environment variable — and rotate it if it ever leaks. Finally, treat the payload as untrusted input like any other: validate its shape before you act on it, because a forged event that slips through can trigger real actions in your system.

Try it yourself

Put what you just read into practice with these free tools — no sign-up needed.

Keep learning

Browse all guides →