What is a Webhook? Definition, Examples & How to Set One Up

What is a webhook? A webhook is an automated HTTP request a service sends when an event happens. Learn how webhooks work, see examples, set one up in Node.js, and follow best practices.

A webhook is an automated HTTP request that one system sends to a URL you control whenever a specific event happens. Instead of your application constantly asking another service "has anything changed yet?", the service simply pushes the information to you the instant it does.

For technical folks, it's easiest to think of webhooks as "reverse APIs" or "push APIs": one server makes an API request to another server. (For a deeper comparison, see webhooks vs API.)

If you prefer a plain-language version: imagine a friend who bakes cakes. Rather than you checking the kitchen every five minutes, your friend texts you the moment a cake is ready. A webhook is that text message between web services.

What are examples of webhooks?

The most common real-world webhook examples:

  1. Payments — when a payment is made, a webhook is sent to the merchant's server so it can process the order. See receiving Stripe webhooks on localhost.
  2. Software testing / CI/CD — when code is pushed to GitHub, a webhook notifies a CI system to run tests and deploy. See the GitHub + Jenkins guide.
  3. Connecting services together — when you want to glue two third-party tools together, webhooks are the bridge. See Google Home + IFTTT + Node-RED.
  4. Notifications — posting a message to a Discord or Slack channel when something happens, like a TradingView alert.

Anatomy of a webhook request

Every webhook is an ordinary HTTP request, so it has three parts you'll work with:

  • The method and URL — almost always a POST to the endpoint URL you registered with the provider.
  • Headers — metadata about the delivery. The important ones are the Content-Type (usually application/json), an event-type header (e.g. GitHub's X-GitHub-Event), and a signature header the provider uses to prove the request is authentic (e.g. Stripe-Signature, X-Hub-Signature-256).
  • The body (payload) — the JSON describing what happened: the event type, an ID, a timestamp, and the data object.

Knowing the exact shape of these three parts is the whole job when you integrate a new provider — which is why it helps to capture a real request and inspect it before writing any handler code.

Webhooks vs APIs vs polling

ApproachDirectionWhen data movesBest for
REST APIYou → provider (pull)When you askOn-demand reads and writes
PollingYou → provider (pull, on a timer)Every N seconds, whether or not anything changedSimple, but wasteful and slow
WebhookProvider → you (push)The instant an event happensReal-time reactions to events

Webhooks replace polling: instead of asking "has anything changed?" on a loop, the provider tells you the moment it does. See the full breakdown in webhooks vs API.

How to receive a webhook in an application

A webhook is, at its core, just a POST request to a URL on your server. Instead of a person visiting your site or a CLI calling your API, it's another website POSTing data to you. So to receive one, you need a server listening for POST requests on a specific path.

Here it is in Node.js with Express:

npm init -y
npm install express

Create index.js:

const express = require('express')
const app = express()
app.use(express.json())

const port = 3000

app.post('/webhooks', (req, res) => {
  console.log('Received webhook:', req.body)
  res.sendStatus(200) // always acknowledge quickly
})

app.listen(port, () => {
  console.log(`Listening for webhooks on port ${port}`)
})

Start it:

node index.js

And send a test webhook with curl:

curl -X POST --data '{"important":"data"}' \
  -H 'Content-Type: application/json' \
  http://localhost:3000/webhooks

That's about as complicated as it gets — you can now receive webhooks from any service and process them.

How to set up a webhook (and receive it on localhost)

Setting up a webhook is two steps:

  1. Expose a public URL that listens for POST requests (the handler above).
  2. Register that URL in the sending service's webhook settings (e.g. Stripe → Developers → Webhooks, or GitHub → Settings → Webhooks).

The tricky part is step 1 during development: providers can only call public URLs, but your handler runs on localhost. That's what Webhook Relay solves — inspect the incoming payload in your browser, then forward it to your machine with the agent:

relay forward --bucket my-app http://localhost:3000/webhooks

No public IP, no firewall changes, and the URL stays the same so you configure the provider once. See how to test webhooks for the full workflow.

Webhook best practices

  • Always respond 2xx quickly. If you return an error or respond slowly, the sender will retry. Do heavy work asynchronously and acknowledge first. Only return 5xx when you genuinely can't process the event (e.g. the database is down) and want a retry.
  • Verify the signature. Most providers sign webhooks with an HMAC so you can confirm authenticity. See how to verify a webhook signature and the free HMAC verifier.
  • Don't rely on ordering. Webhooks can arrive out of order. If order matters, use a queue or sort by a timestamp in the payload.
  • Make handlers idempotent. The same event can be delivered more than once; de-duplicate on an event ID so reprocessing is safe.
  • Keep payloads thin. If you're sending webhooks, send identifiers and let the receiver fetch full data via your API. This avoids stale data and keeps payloads small.

For the full checklist, see webhook security best practices, webhook authentication methods and retries & idempotency.

How to test and debug webhooks

You can't see a webhook until something sends one, so the fastest way to learn a provider's payload is to capture a real request:

  1. Capture & inspect — point the provider at a free webhook tester URL and read the exact headers and body.
  2. Verify the signature — confirm authenticity with the HMAC verifier and the verify a webhook signature guide.
  3. Forward to localhost — drive your local handler with real events using the relay agent. See how to test webhooks and how to debug webhooks.

Webhooks by provider

Most integrations follow the same pattern with provider-specific signatures and event shapes. These guides cover the exact details for popular services — capture and inspect the payload, then receive it on localhost:

Looking for a no-code option? Every provider also has a dedicated tester — for example the Stripe webhook tester and GitHub webhook tester.

Routing and transforming webhooks

Once you receive a webhook you often want to send it somewhere else, or reshape it first. Webhook Relay can transform payloads and fan a single event out to multiple destinations:

Next steps