Updated on 14 Jul, 202636 mins read 19 views

If you have worked with APIs, you have probably heard statements like:

  • “Configure a webhook endpoint”
  • “Stripe will send a webhook.”
  • “GitHub triggers a webhook on every push.”

Many developers treat webhooks as something special or magical.

They are not.

In fact, understanding webhooks becomes much easier once you realizes one simple fact:

A webhook is not a new technology. It is simply an HTTP endpoint whose purpose is to receive event notification from another system.

Everything else – security, retries, signatures, idempotency, queues – is built around making that communication reliable.

Understanding the Problem

Imagine you own an e-commerce website.

Customers pay using Stripe.

When the payment succeeds, your website should:

  • Mark the order as paid.
  • Generate an invoice.
  • Send an email.
  • Start shipping.

The problem is:

How does your application know that the payment succeeded?

There are two possible approaches.

Approach 1: Keep Asking (Polling)

Your server repeatedly asks Stripe:

Has payment succeeded?

No.

...

Has payment succeeded?

No.

...

Has payment succeeded?

Yes.

This is called polling.

Your application continuously requests information whether or not anything has changed.

This works.

But it has several drawbacks:

  • Wastes API requests
  • Higher server load
  • Delayed updates
  • More network traffic
  • Poor scalability

Approach 2: Let Stripe Notify You

Instead of asking repeatedly:

Your Server

(waiting...)

Stripe

Payment Successful
	↓
Immediately sends notification

Now your server doesn't need to ask.

Stripe tells your server exactly when something happens.

This is the core idea behind webhooks.

In other words, webhooks enable one system to push information to another in real time, eliminating the need for the receiving application to continuously pull for updates.

Polling vs Webhooks

Imagine ordering pizza.

Polling:

You call every minute.

Is my pizza ready?
No.

One minute later...
Is it ready?
No.

One minute later...
Ready?
No.

Webhook

The restaurant calls you.

Pizza Ready
	↓
Restaurant calls you immediately

The restaurant initiates the communication.

That's exactly how webhooks work.

What Exactly is a Webhook?

Here's the definition that many developers eventually arrive at after building production systems:

A webhook is an HTTP endpoint exposed by an application whose purpose is to receive event notifications from another system.

Notice something important.

The definition does not say:

  • a special protocol
  • a new networking technology
  • a new API type

Because it isn't. It is simple an endpoint.

Webhooks Are Just HTTP Endpoints

This is probably the biggest misconception.

People imagine webhooks as something fundamentally different.

They are not.

Consider Express.js:

app.post("/api/orders", createOrder);

app.post("/webhooks/stripe", stripeWebhook);

Express doesn't know which one is a webhook.

Both are simply routes.

The framework treats them identically.

The only difference is who calls them.

Normal API Endpoint

Usually called by:

  • frontend
  • mobile app
  • another internal service

Example:

POST /api/login

The client decides when to call.

Webhook Endpoint

Usually called by:

  • Stripe
  • GitHub
  • Shopify
  • Slack
  • PayPal
  • Twilio

Example:

POST /webhooks/stripe

The third-party service decides when to call.

That is the difference.

The intention is different – not the technology.

Anatomy of a Webhook

Every webhook consists of four parts.

Let's understand each one.

Event

Something happens.

Examples:

payment.success

payment.failed

order.created

repository.push

user.created

The event occurs inside another application.

Sender

The application that detected the event.

Examples:

  • Stripe
  • GitHub
  • Shopify

It prepares an HTTP request.

Payload

The event data.

Example:

payment.success

payment.failed

order.created

repository.push

user.created

Receiver

Your webhook endpoint.

Example:

POST /webhooks/payment

This endpoint receives the request and processes it.

How Do Webhooks Work?

The webhooks are surprisingly simple to understand once you see the flow.

1 Register a webhook endpoint

The receiving application starts by creating an HTTP endpoint (commonly called a webhook endpoint) and sharing its URL with the provider.

For example, you might tell Stripe:

“Whenever a payment succeeds, send the event details to https://myapp.com/webhooks/payment

This is essentially your application saying, “Notify me whenever this event happens”.

2 An event occurs

Whenever the subscribed event takes place – for example, a successful payment in Stripe or a new pull request on GitHub – the provider detects the event and prepares an HTTP POST request.

The request contains a payload, typically in JSON format, with all the relevant details about what happened.

3 The webhook is delivered

The provider immediately sends the HTTP POST request to your webhook endpoint. At this point it's essentially saying:

“An event just occurred. Here's everything you need to know.”

Because the provider initiates the request, your application doesn't have to keep checking whether anything has changed.

4 Your application processes the event

Your webhook endpoint receives the request, reads the payload, and performs whatever actions are required.

Depdending on your application's needs, it might:

  • Update the database
  • Change an order's status
  • Send a confirmation email
  • Trigger a CI/CD pipeline
  • Notify a Slack channel
  • Start another business workflow

Once the processing is complete, your application usually responds with a HTTP 200 OK status code to let the provider know the event was received successfully.

The entire process typically completes within seconds — or even milliseconds.

A real-world example

Suppose you are monitoring a GitHub repository.

When someone opens a pull request, GitHub instantly sends a webhook request containing details about the new pull request to your application.

Your service can then automatically trigger a CI/CD pipeline, assign reviewers, or send a notification to Slack – all without anyone manually checking GitHub for updates.

Complete Lifecycle of a Webhook

Let's follow a payment.

Step 1

Customer clicks:

Pay

Step 2

Stripe processes payment.

SUCCESS

Step 3

Stripe creates an event.

payment.success

Step 4

Stripe sends HTTP request.

POST /webhooks/stripe

Body:

{
  "event": "payment.success",
  "payment_id": "pay_123"
}

Step 5

Your server receives it.

Receive Request
  ↓
Validate
  ↓
Process
  ↓
Return 200

Done.

That's literally the webhook lifecycle.

Inside the Webhook Endpoint

A production webhook endpoint usually performs these steps.

Receive Request
	↓
Authenticate Sender
	↓
Validate Payload
	↓
Check Idempotency
	↓
Execute Business Logic
	↓
Respond

Let's understand each one.

Step 1 – Receive Request

The HTTP server receives a POST request.

Exactly like every other API endpoint.

Nothing special happens here.

Step 2 – Authenticate the Sender

Anyone on the internet could send:

POST /webhooks/stripe

Without authentication, attackers could fake events.

Therefore we verify the sender.

Common techniques:

  • HMAC signature
  • Shared secret
  • Timestamp verification
  • IP allow-list (optional)

Step 3 – Validate Payload

Never assume incoming data is correct.

Verify:

  • required fields
  • event type
  • data types
  • schema

Example:

Missing payment_id
	↓
Reject request

Step 4 – Check Idempotency

One event may arrive multiple times.

This surprises many beginners.

Webhooks are at least once delivered.

That means duplicates are normal.

Suppose Stripe retries.

payment.success
	↓
payment.success
	↓
payment.success

Should you process all three?

No.

Instead:

event_id
	↓
Already processed?
	↓
Yes
	↓
Ignore

This property is called idempotency.

An idempotent operation produces the same result whether executed once or many times.

Step 5 – Execute Business Logic

Only after validation should business logic execute.

Example:

Update Order
	↓
Generate Invoice
	↓
Send Email
	↓
Notify Warehouse

Step 6 – Respond

Return success.

HTTP 2000 OK

This tells the sender:

Delivery Successful

Webhook Security

Security is where production systems differ from tutorials.

Signature Verification

Most providers compute:

signature = HMAC(secret, request_body)

They include it in headers.

X-Signature
 abc123...

Your server calculates the same value.

If they match:

Valid

Otherwise:

Reject

This prevents forged requests.

Timestamp Validation

Suppose someone records a legitimate webhook.

Six months later they replay it.

Without timestamp validation:

Old Payment
	↓
Processed Again

Timestamp verification prevents replay attacks.

HTTPS

Always use HTTPS.

Never expose webhook endpoints over HTTPS.

Validate Everything

Never trust incoming payloads.

Validate:

  • types
  • schema
  • required fields
  • supported event names

Why Webhooks Are Retried

Network fail.

Server crash.

Databases become unavailable.

Suppose your server responds:

500 Internal Server Error

Should Stripe give up?

No.

Instead:

Attempt 1
  ↓
Fail
  ↓
Wait
  ↓
Attempt 2
  ↓
Fail
  ↓
Attempt 3

Most providers implement exponential backoff.

Example:

1 minute
	↓
5 minutes
	↓
30 minutes
	↓
2 hours

Why Idempotency Is Critical

Imagine:

Payment
	↓
Webhook arrives
	↓
Order marked paid

Now suppose the response times out.

Stripe never receives:

200 OK

Stripe assumes delivery failed.

It retries.

Same Event Again

Without idempotency:

Charge Customer Again

Generate Invoice Again

Ship Again

A disaster.

Therefore:

event_id
	↓
Already Exists?
	↓
Ignore

Idempotency is mandatory.

Why Queues Matter

Beginners often write:

Receive Webhook
↓
Update Database
↓
Generate PDF
↓
Resize Images
↓
Send Email
↓
Call Another API
↓
Return 200

This is bad.

The sender waits.

Instead.

Receive Webhook

↓

Validate

↓

Store Event

↓

Push to Queue

↓

Return 200 Immediately

Worker processes later.

Queue

↓

Worker

↓

Email

↓

Database

↓

Reports

Benefits:

  • Fast responses
  • Better scalability
  • Higher reliability
  • Retry support
  • Fault isolation

Full Mental Model

An event occurs in a third-party system
                │
                ▼
The third party creates an event payload
                │
                ▼
It sends an HTTP POST request to your webhook endpoint
                │
                ▼
Your endpoint:
  • Verifies the sender
  • Validates the payload
  • Checks idempotency
  • Records or queues the event
                │
                ▼
Background workers execute the business logic
                │
                ▼
Your application updates its state
Buy Me A Coffee

Leave a comment

Your email address will not be published. Required fields are marked *