What Are Webhooks and How Do They Work? A Plain-English Guide
Understand what webhooks are, how they work, and when to use them over polling. A practical introduction for developers and technical founders building integrations.
A webhook lets one service notify another about an event by sending an HTTP request to a registered endpoint. The receiver needs to verify the request, accept it durably, and handle duplicates or missed deliveries.
Webhooks in One Sentence
A webhook is an HTTP POST request that an external service sends to your server when a specific event occurs.
That is the whole concept. When Stripe processes a payment, it sends a POST to your server. When GitHub merges a pull request, it sends a POST to your CI system. When Shopify records a new order, it sends a POST to your fulfilment service. You register a URL with the provider, and they call it when relevant events happen.
The alternative — polling — is your server periodically asking the provider "anything new?" Webhooks invert the direction: the provider contacts you.
The Four Steps of a Webhook Delivery
1. You register a URL. In the provider's dashboard or API, you tell them where to send events. This is usually called a webhook endpoint, webhook URL, or callback URL. It must be a publicly reachable HTTPS URL — not localhost.
2. An event occurs. A customer pays. An order ships. A file is uploaded. The provider's system detects this event internally.
3. The provider sends an HTTP POST. The provider constructs a JSON payload describing the event and sends an HTTP POST request to your registered URL. The payload contains details about what happened: the event type, a unique event ID, a timestamp, and the relevant data.
4. Your server responds. Your endpoint processes the event and returns an HTTP 2xx status code to the provider. This tells them delivery was successful. If you return anything else, or if the request times out, the provider may retry according to its documented policy.
What a Webhook Payload Looks Like
Payloads vary by provider, but they follow a common pattern. A Stripe payment_intent.succeeded event looks roughly like this:
{
"id": "evt_1Pxabc123",
"type": "payment_intent.succeeded",
"created": 1714000000,
"data": {
"object": {
"id": "pi_1Pxdef456",
"amount": 4900,
"currency": "usd",
"status": "succeeded"
}
}
}Key fields to understand:
id: A unique, stable identifier for this event. It stays the same across retries. Store this for deduplication.type: The event name. Subscribe only to the event types you actually need.created: Unix timestamp of when the event occurred.data.object: The object that changed — the payment, the order, the subscription.
What You Need to Build on Your Side
Receiving webhooks requires three things from you:
A public HTTPS endpoint. Your URL must be reachable from the internet. In development, tools like ngrok or the Stripe CLI can tunnel your localhost to a public URL for testing.
Signature verification. The provider includes a cryptographic signature in the request headers. You verify it against a shared secret to confirm the request came from the provider, not from someone who guessed your URL. Never skip this step.
A 2xx response returned quickly. Return 200 or 202 before doing slow work. If your handler takes too long, the provider's request times out and they retry — which can cause duplicate processing. Verify the event, durably queue the work, return a success response, then process in the background. Do not acknowledge success if the durable write fails.
Common Misconceptions
"Webhooks guarantee exactly-once delivery." They do not. Providers retry on failures. You will receive duplicates. Design your handler to be idempotent — processing the same event twice should produce the same result as processing it once.
"If I return 200, the data is safely stored." Only if your code actually wrote it. Returning 200 just stops retries. If your downstream database write fails after you returned 200, the event is lost unless you have your own retry mechanism.
"Webhooks are only for payments." They are used everywhere: CI/CD pipelines, CRM updates, shipping notifications, authentication events, content publishing, IoT device state changes, and more.
Next Steps
Once you understand the basics, the important topics to learn are: HMAC signature verification, idempotency patterns, retry and dead-letter strategies, and how to structure your webhook endpoint for testability. Each of these has a substantial body of production knowledge behind it.