What is a webhook? How webhooks work, with examples and security tips
A webhook is an HTTP callback that notifies your app when an event happens. How webhooks differ from polling, how to verify signatures and handle retries.
A webhook is a way for one service to notify another the moment something happens. Instead of your application asking a provider “is there anything new?” every few seconds, the provider sends an HTTP request to an address you choose as soon as an event occurs: a payment succeeds, a form is submitted, a message arrives, a build finishes.
Webhooks power a large part of the modern web: payment confirmations, chat bots, automation tools such as n8n or Zapier, deployment pipelines and monitoring alerts. This guide explains how they work, how they differ from a normal API call, and how to receive them safely.
Polling vs webhooks
With polling, your code repeatedly calls an API to check for changes. It is simple, but most of those requests return nothing new, they consume your rate limit, and updates arrive late by up to one polling interval.
With a webhook, the direction is reversed. You give the provider a URL once, and it calls you only when there is something to report. Updates arrive in seconds and no requests are wasted. A common way to remember it: an API is you calling the service; a webhook is the service calling you back.
How a webhook works, step by step
- You create an endpoint — a URL on your server, for example
https://example.com/hooks/payments, that accepts POST requests. - You register it with the provider and choose which events you want:
payment.succeeded,order.createdand so on. The provider usually gives you a secret for verifying signatures. - An event happens on the provider’s side.
- The provider sends a POST request to your URL with a JSON body describing the event.
- Your server verifies and acknowledges it by answering quickly with a 2xx status code, then processes the event.
- If you do not answer with 2xx, most providers retry later, often for hours or days, with growing delays.
A typical delivery looks like this:
POST /hooks/payments HTTP/1.1
Content-Type: application/json
X-Signature: t=1760880000,v1=5f2b9c...
{
"id": "evt_8421",
"type": "payment.succeeded",
"created": 1760880000,
"data": { "payment_id": "pay_193", "amount": 2500, "currency": "EUR" }
}
Where you meet webhooks
- Payments – the payment provider confirms that money actually arrived, refunds and disputes.
- Messaging and bots – Telegram, Slack and other platforms can deliver new messages to your bot through a webhook instead of long polling.
- Code hosting – GitHub and GitLab send push, merge request and pipeline events to CI systems and chat channels.
- Automation – tools like n8n start a workflow when a webhook URL is called.
- Monitoring – uptime checkers and alerting systems post incidents to chat or paging services.
Securing a webhook endpoint
A webhook URL is publicly reachable, so anyone who learns it can send fake events. Treat every incoming request as untrusted until verified.
Verify the signature
Most providers sign each request with a shared secret using HMAC-SHA256 and put the result in a header. Recompute the signature from the raw request body and compare it in constant time:
import crypto from 'node:crypto';
function isValid(rawBody, header, secret) {
const [tPart, sigPart] = header.split(',');
const timestamp = tPart.split('=')[1];
const expected = crypto.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`).digest('hex');
const given = sigPart.split('=')[1];
const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) < 300;
return fresh && given.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(given), Buffer.from(expected));
}
The exact format differs between providers, so follow their documentation. Two details matter everywhere: use the body exactly as received, before any JSON parsing changes it, and reject old timestamps to stop replay attacks.
Other protections
- HTTPS only, so the payload and signature cannot be read or changed in transit. See HTTP vs HTTPS.
- A hard-to-guess path helps, but it is not a replacement for signatures.
- Do not trust the payload blindly. For important events, such as a payment, fetch the object from the provider’s API by its ID before you ship goods or grant access.
- Keep the secret out of code; store it in environment variables or a secrets manager and rotate it if it leaks.
Reliability: duplicates, order and timeouts
- Answer fast. Providers wait only a few seconds. Save the event, reply 200, and do the heavy work in a background job.
- Expect duplicates. Retries mean the same event can arrive twice. Store processed event IDs and skip repeats, so your handler is idempotent.
- Do not rely on order. An “updated” event can arrive before “created”. Use timestamps or re-read the current state from the API.
- Plan for downtime. If your server is down longer than the provider’s retry window, events are lost. Many providers let you list or replay past events; use that to reconcile.
- Log deliveries with event ID, type and result. When something goes wrong, the log is the first place you will look.
Testing webhooks locally
Your laptop is not reachable from the internet, so providers cannot call it directly. Common options are the provider’s own CLI that forwards events to localhost, a tunnelling tool that gives you a temporary public URL, or a request-inspection service that shows incoming requests so you can see the real payload. Many dashboards also have a “send test event” button. Remove temporary tunnels when you finish testing.
Webhooks vs WebSockets
Both deliver updates without polling, but they solve different problems. A webhook is a single HTTP request from server to server for each event, ideal for backend integrations. A WebSocket is a long-lived connection that streams many messages, ideal for live dashboards, chat and prices in a browser or app.
Key takeaways
- A webhook is an HTTP callback: the service calls your URL when an event happens.
- It saves requests and delivers updates faster than polling.
- Always verify signatures, use HTTPS and check important events against the API.
- Reply quickly, handle duplicates and log everything.
Related reading: what an API is, what a REST API is and API keys vs OAuth.