Webhooks

What is a Webhook? (Explained Simply)

Webhooks sound technical, but the idea is actually pretty simple. Let's break it down.

April 20256 min read

The Simple Idea

Picture this: you're waiting for a package. You have two options — keep checking the front door every 10 minutes, or just let the delivery driver ring the doorbell when they arrive.

Webhooks are the doorbell.

Instead of your application constantly asking "did anything happen yet?", webhooks let other services notify you the moment something actually does happen. It's a push notification, but for your server.

The one-sentence version:

A webhook is an HTTP POST request that a service sends to your server automatically when a specific event occurs.

Where You've Already Seen Webhooks

You've almost certainly been on the receiving end of a webhook without knowing it. Here are three places they show up constantly:

💳 Stripe

When a customer pays, Stripe sends a webhook to your server with the payment details. Your server then updates the order status, sends a confirmation email, etc.

🐙 GitHub

When someone opens a pull request, GitHub can ping your CI/CD server. That's how automated test runs get triggered on every PR — webhooks.

💬 Slack

You can give Slack a URL and it'll POST a message payload to it whenever someone uses a slash command. Your bot receives that POST and responds.

Same pattern every time — something happens on their end, and they reach out to tell you about it immediately.

How Webhooks Actually Work

There's no magic here. A webhook is just a regular HTTP request. Here's what happens step by step:

1

You register a URL

You give Stripe (or GitHub, or whoever) a URL on your server — something like https://yoursite.com/webhooks/stripe. This is where they'll send requests.

2

Something happens on their end

A payment goes through, a PR gets merged, a new user signs up — whatever event you subscribed to.

3

They POST to your URL

The service makes an HTTP POST request to your URL with a JSON body describing what happened. Headers often include a signature so you can verify it's legit.

4

Your server responds with 200

You process the event and return a 200 OK. If you return anything else (or time out), most services will retry the webhook a few times.

What a Webhook Payload Looks Like

The body of a webhook request is almost always JSON. Here's a simplified example of what Stripe sends when a payment succeeds:

POST /webhooks/stripe HTTP/1.1
Content-Type: application/json
Stripe-Signature: t=1681234567,v1=abc123...

{
  "type": "payment_intent.succeeded",
  "data": {
    "object": {
      "id": "pi_3N1234",
      "amount": 2000,
      "currency": "usd",
      "customer": "cus_abc123",
      "status": "succeeded"
    }
  }
}

Notice: The type field tells you what happened. The data.object contains the details. And that Stripe-Signature header? That's how you verify the request actually came from Stripe and wasn't faked by someone else — it uses HMAC-SHA256 under the hood.

A Few Things That Catch People Off Guard

Most of these will bite you at least once. Better to know about them upfront.

Respond fast, process later

Most services expect a response within a few seconds. If your processing takes longer, acknowledge the webhook immediately and handle the work in a background job. Otherwise you'll get retry floods.

You might get duplicates

Services retry failed webhooks, which means you can receive the same event more than once. Always write your handlers to be idempotent — processing the same event twice shouldn't cause problems.

Localhost doesn't work out of the box

The service sending the webhook needs to reach your server over the internet. During development you need a tunnel tool like ngrok to expose your local server. More on that in the testing guide.

Always verify the signature

Your webhook URL is public. Anyone can POST to it. Most services include a signature header (using HMAC-SHA256) so you can verify the request is genuine. Don't skip this in production.

When Should You Use a Webhook?

Webhooks are the right choice whenever something happens on a third-party platform and you need to know about it quickly. A payment clears, a PR gets merged, a customer cancels their subscription — you want to react the moment it happens, not 30 seconds later when your next poll fires.

They're also the backbone of most CI/CD pipelines. When you push to GitHub, GitHub fires a webhook at your build server. That's what triggers the test run — no polling involved.

Where webhooks don't fit: when you need to fetch data on demand rather than react to events, or when the service simply doesn't offer them. In those cases a regular API call (or polling) is the right tool. Webhooks are push-only — you receive data when they decide to send it, not when you ask for it.

Common Events You'll Actually Subscribe To

Every service has its own event list, but the same handful come up again and again in real projects. Getting familiar with these will help you recognize where webhooks naturally fit.

Payment events

payment_intent.succeeded, invoice.payment_failed, customer.subscription.deleted — these drive most e-commerce logic. Payment clears? Fulfill the order. Subscription lapses? Lock the account.

Code repository events

push, pull_request, release — these power CI/CD pipelines. Push to main triggers a deployment. New PR triggers a test run. GitHub, GitLab, and Bitbucket all fire these via webhook.

Messaging events

When a user sends your Slack bot a message, Slack fires a webhook at your server with the message content. Your code reads it, does something, and responds. Same idea with Twilio when an SMS arrives, or SendGrid when an email bounces or is opened.

Form & CRM events

Typeform, HubSpot, Airtable — many SaaS tools fire a webhook when a form is submitted or a record changes. It's a common way to sync data between platforms without polling.

One thing they all have in common: the payload is JSON. If you ever need to quickly inspect or format a webhook payload you've captured during testing, JsonFormatter.ai is a handy way to pretty-print and explore the structure before writing your handler code.

Try It Yourself

The fastest way to understand webhooks is to see one arrive in real time. Our Webhook Tester gives you a unique URL — point any service at it and watch the requests come in with full headers and body.

What to Read Next