Webhook Tutorial: What It Is and How to Use It
Webhook tutorial explaining what webhooks are, how they work, and how to set one up safely. Learn testing, security, retries, and best practices.
Introduction
A webhook is a way for one app to notify another app when something happens. Instead of asking repeatedly for updates, the receiving app gets an HTTP request as soon as the event occurs. That makes webhooks a common part of event-driven architecture.
This webhook tutorial explains what webhooks are, how they work, how they compare with APIs and polling, and how to set one up safely. You’ll also learn how to test a webhook locally, verify signatures, handle retries and duplicate delivery, and avoid common mistakes.
Webhooks are used in many real systems, including GitHub, Stripe, Shopify, Slack, Twilio, GitLab, PayPal, and Zapier. They can trigger deployments, payment updates, order notifications, SMS messages, and cross-app automations.
What Is a Webhook in Simple Terms?
A webhook is an event-driven HTTP callback. In simple terms, it is a message sent from one system to another when an event happens. The sender is often called the webhook sender, and the receiving app is the webhook receiver, webhook listener, or endpoint that accepts the request.
A webhook request is usually a POST request sent over HTTPS. It includes a payload, headers, and often a signature or delivery ID. The payload is the data about the event, such as a payment, a new issue, or an order update.
How Do Webhooks Work?
Here is the basic flow:
- An event happens in a service such as GitHub, Stripe, or Shopify.
- The service sends an HTTP POST request to your endpoint.
- Your webhook listener checks the request, verifies the signature, and reads the payload.
- Your app processes the event.
- Your endpoint returns a fast 2xx response to confirm receipt.
That 2xx response tells the sender the event was received successfully. If the sender does not get a successful response, it may retry the delivery.
Webhook vs API: What Is the Difference?
An API is a general way for one system to request data or perform actions in another system. A REST API usually works in a request-response pattern: your app asks for something, and the server replies.
A webhook is different because it is push-based. The provider sends data to you when an event happens, instead of waiting for your app to ask for it.
In short:
- API: your app asks for data
- Webhook: the other app sends data to you
APIs are better when you need to fetch data on demand. Webhooks are better when you want event-driven updates with less repeated traffic.
Webhooks vs Polling
Polling means your app keeps checking an API on a schedule to see whether anything changed. For example, you might ask every minute whether a payment succeeded or an order shipped.
Webhooks are usually better when you want faster updates and less wasted traffic. Polling can still be useful when a provider does not support webhooks, when you need a periodic snapshot, or when you want a fallback mechanism.
Why use a webhook instead of polling?
- Lower latency for event updates
- Fewer unnecessary API calls
- Less server load
- Better fit for event-driven architecture
How Do I Create a Webhook Endpoint?
A webhook endpoint is a public URL that can receive incoming requests. To create one:
- Choose the event you want to receive.
- Create an HTTPS route in your app.
- Accept POST requests.
- Parse the payload.
- Verify the signature.
- Return a 2xx response quickly.
If you are using Node.js and Express, a simple route such as app.post("/webhook", ...) can serve as the webhook receiver. In ASP.NET WebHooks, you can create a similar endpoint in a .NET app. Microsoft Learn also has documentation for webhook-related patterns in the Microsoft ecosystem.
How Do I Set Up a Webhook Step by Step?
- Pick the event you want to subscribe to, such as
payment_intent.succeededin Stripe orpushin GitHub. - Create your webhook listener endpoint.
- Deploy it so it is reachable over HTTPS.
- Copy the endpoint URL into the provider dashboard.
- Select the events you want to receive.
- Save the shared secret for signature verification.
- Send a test event.
- Confirm that your app receives the payload and returns a 2xx response.
- Add idempotency so duplicate delivery does not create duplicate side effects.
For documentation, use the documentation template and the Markdown style guide so your endpoint details stay consistent.
How Do I Test a Webhook Locally?
To test a webhook locally, run your app on your machine and expose it with ngrok so the provider can reach it over a public HTTPS URL. Then send a test event from Stripe, GitHub, Shopify, or another provider.
When testing, check:
- The request headers
- The JSON payload
- The status code your endpoint returns
- Whether signature verification succeeds
Tools like ngrok, request inspectors, and provider replay features help you debug the full delivery flow before you go live.
How Do I Verify a Webhook Signature?
Signature verification proves that the request came from the expected sender and was not altered in transit. Most providers use HMAC with a shared secret.
A common pattern is:
- Read the raw request body.
- Compute the HMAC using the shared secret.
- Compare the computed value with the signature header.
- Reject the request if the values do not match.
Do not parse and reserialize the body before verification unless the provider explicitly says that is safe. Use the exact signing method described in the provider’s API documentation.
What Should a Webhook Return After Receiving a Request?
After receiving a valid webhook request, your endpoint should return a fast 2xx response, usually 200 OK or 204 No Content.
Return a 2xx response only after you have accepted the event. If you need to do slow work, queue it and finish processing after the response is sent.
Why Are Webhook Requests Retried?
Webhook requests are retried when the sender does not receive a successful response, times out, or gets a network error. Retries help make delivery more reliable.
This is why webhook systems often use duplicate delivery. The same event may arrive more than once, so your handler should be idempotent.
How Do I Handle Duplicate Webhook Events?
Use idempotency keys or event IDs to detect repeats. Store the event ID in your database, cache, or job queue, and skip processing if you have already handled it.
This matters for payments, order updates, and other actions where duplicate processing could create duplicate charges, duplicate emails, or duplicate records.
What Are Common Webhook Use Cases?
Common webhook use cases include:
- GitHub: trigger CI/CD builds when code is pushed
- Stripe: update orders when payments succeed or fail
- Shopify: react to order, inventory, or fulfillment events
- Slack: send alerts into channels
These are all examples of event-driven architecture in practice.
Are Webhooks Secure?
Webhooks can be secure if you design them correctly. Use HTTPS, verify signatures, validate the payload, and reject requests that do not match the expected event.
Other good practices include:
- Keep the shared secret private
- Check timestamps when the provider supports them
- Log delivery IDs for auditing
Security depends on implementation, not on the webhook concept itself.
What Are the Most Common Webhook Mistakes?
The most common webhook mistakes are:
- Not verifying the signature
- Returning a slow response
- Doing heavy work before sending the 2xx response
- Ignoring retries and duplicate delivery
- Using HTTP instead of HTTPS
How Do GitHub Webhooks Work?
GitHub webhooks send event notifications when things happen in a repository, such as pushes, pull requests, issues, or releases. You configure a repository webhook, choose the events you want, and point GitHub to your endpoint.
GitHub includes headers such as an event type header and a delivery ID, and it signs requests so you can verify them with a shared secret.
How Do Stripe Webhooks Work?
Stripe webhooks notify your app about payment and billing events such as payment_intent.succeeded, checkout.session.completed, or subscription changes. You register an endpoint in the Stripe dashboard, select the events you want, and verify each request with Stripe’s signature header.
Stripe also provides test mode and replay tools, which are useful when you are learning how to build and debug a webhook receiver.
What Is a Webhook Payload?
A webhook payload is the data sent in the request body. It is often JSON and usually contains the event type, object data, timestamps, and identifiers.
For example, a payment webhook payload might include the payment ID, amount, currency, and status. A GitHub payload might include the repository, action, and sender.
What Headers Are Included in Webhook Requests?
Common webhook headers include:
Content-Type- An event type header
- A delivery ID header
- A signature header
The exact header names depend on the provider. Always check the API documentation for the service you are integrating.
What Is the Difference Between a Webhook and a Callback?
A callback is a broad term for any function or URL that is called after an event or operation completes. A webhook is a specific kind of callback delivered over HTTP to a URL you control.
So, all webhooks are callbacks in a general sense, but not all callbacks are webhooks.
Conclusion
Webhooks let one system notify another system when an event happens, which makes them a practical alternative to polling for many real-time workflows. They are simple in concept, but reliable implementations need HTTPS, signature verification, idempotency, and careful handling of retries.
If you are building your first webhook, start with one event in GitHub or Stripe, test it locally with ngrok, verify the payload and headers, and make sure your endpoint returns a fast 2xx response. From there, you can expand into automations with tools like Shopify, Slack, Twilio, GitLab, PayPal, and Zapier.