Friday, April 24, 2026

What is a webhook? Complete guide with examples

Hooksbase
Fundamentals
Webhook flow diagram showing a source service POSTing to a receiver URL

A webhook is an HTTP request that one service sends to another to notify it that something happened. The sending service POSTs a JSON body to a URL the receiving service has registered. The receiving service responds with 2xx to acknowledge it got the message.

That's the entire pattern. The interesting parts are everything that hangs off it: how the receiver knows the request is real, what happens when the receiver is down, what the payload looks like, and how the whole thing stays reliable in production.

How do webhooks work?

Step by step:

  1. The receiver registers a URL with the sending service. ("When a payment succeeds, POST to https://my-app.example.com/stripe-webhook.")
  2. An event happens on the sending service. (A customer pays.)
  3. The sender POSTs a JSON payload to the registered URL describing the event.
  4. The receiver responds with 2xx if it processed the event, or with a non-2xx if something went wrong.
  5. The sender retries non-2xx responses on a backoff schedule, usually for hours or days.

Both sides are HTTP servers. The "webhook" is the agreement: I will POST you when X happens, you will respond.

Webhook examples

Webhooks are everywhere in modern SaaS:

  • Stripe posts a webhook when a payment succeeds, fails, refunds, or a subscription renews.
  • GitHub posts a webhook when a PR is merged, an issue is opened, or a workflow completes.
  • Slack posts a webhook when a user installs your app, sends a message your bot can see, or interacts with a button you posted.
  • Shopify posts a webhook when an order is created, fulfilled, refunded, or cancelled.
  • Twilio posts a webhook when an SMS is delivered, a call ends, or a number receives a message.
  • Clerk posts a webhook when a user signs up, updates their profile, or deletes their account.

Each of these lets your application react to something happening in another service without polling for changes.

Webhook vs API: what's the difference?

A traditional API is pull-based — your application asks the other service "did anything happen?" on a loop.

A webhook is push-based — the other service tells your application when something happens.

Pull APIs are simpler to reason about but slow and wasteful: you poll constantly, most polls return nothing. Webhooks are real-time but harder to operate: you have to be online to receive them, and you have to handle the failure modes when you're not.

Most production systems use both — APIs for state, webhooks for events.

What does a webhook payload look like?

Webhooks send JSON. A simple Stripe payment_intent.succeeded payload looks like this:

{
  "id": "evt_1NxV5y2eZvKYlo2C8wT9pQ4Z",
  "type": "payment_intent.succeeded",
  "created": 1714000000,
  "data": {
    "object": {
      "id": "pi_3NxV5y2eZvKYlo2C0pZ4uX2A",
      "amount": 2999,
      "currency": "usd",
      "customer": "cus_O8N3K5p4lJ2mNw"
    }
  }
}

Most providers send their event metadata in HTTP headers as well — event ID, signature, delivery attempt number. Receivers use these for idempotency, signature verification, and retry handling.

Webhook security: what to verify

Anyone can POST to your webhook URL. The receiver has to verify the request actually came from the service it claims to be from. Three things to check on every inbound webhook:

  1. Signature. Reputable providers sign the payload with HMAC-SHA256 using a shared secret. Compute the signature on your side and compare it constant-time to the header value.
  2. Timestamp. Most signatures include a timestamp to prevent replay attacks. Reject requests older than five minutes.
  3. Source. If the provider publishes IP ranges (Stripe, GitHub, Twilio do), verify the request came from one of them.

Hooksbase verifies signatures for Stripe, GitHub, Clerk, Slack, and Resend on Starter+ after the request passes Hooksbase ingest auth and before the payload reaches your endpoint. Forged supported-provider events are rejected before delivery is persisted.

What can go wrong with webhooks?

Five failure modes show up in every production webhook system:

  • Duplicate delivery. The same event arrives twice because the sender retried after a slow response. Idempotency is the fix — store the event ID and refuse to process the same one twice.
  • Out-of-order delivery. Webhooks aren't ordered by default. If your handler depends on event order (subscription created → invoice paid → invoice settled), you need to either reorder them yourself or use a relay that gives you strict FIFO.
  • Receiver downtime. Your endpoint is down. The sender retries for a while, then gives up. You lose events. A relay that queues incoming events independent of your endpoint solves this.
  • Slow handling. Your endpoint takes 30 seconds to respond. The sender times out and retries. Now you're processing the same event twice in parallel. Acknowledge fast, process async.
  • Payload changes. The sender changes the payload shape in a minor version. Your handler crashes. A transform layer in front of your endpoint isolates you from this.

Most of these are solved problems. They're just not solved problems in your codebase unless you've built a relay layer in front of your endpoint.

What is a webhook relay?

A webhook relay sits between the sender and your endpoint. The sender or a verification forwarder POSTs to the relay with the required ingest auth; the relay verifies supported providers when configured, queues accepted events, transforms, retries, and delivers to your endpoint. If your endpoint is down, the relay holds accepted events. If a payload changes, the relay can transform it to the shape you expect. If a delivery fails terminally, the relay sends it to a DLQ where you can replay it while the payload is retained.

This is what Hooksbase is. HTTP, email, and form ingest on every tier; scheduled cron, provider packs, and transforms on Starter+; programmable routing; retries with backoff; Pro+ FIFO and event drains; deterministic replay while payloads are retained; DLQ; and tiered delivery history. Sources that can send the Hooksbase bearer secret can call the relay directly; sources that cannot may need a small verification forwarder.

If you're operating webhooks at scale today and any of the failure modes above sound familiar, start free and see your first delivery in about ten minutes.

For more depth: the Verify provider webhooks guide, Routing, transforms, and replay for AI agents, or Recover failed agent events with DLQ and replay.

Keep reading