A webhook is an HTTP request that a service sends automatically to a previously registered URL as soon as a specific event occurs, such as a new order or a newsletter sign-up. The receiver does not have to ask; it gets notified.
A webhook reports an event with an HTTP request to a registered URL, push instead of polling: how it works, how to secure it and what it is used for.
What a webhook means
In May 2007, Jeff Lindsay described web hooks as user-defined callbacks made with HTTP POST. The user specifies a URL, and the application posts a message there when something happens. The Standard Webhooks specification today calls webhooks a common name for HTTP callbacks and the way services notify each other of events.
The difference from an ordinary API is the direction. With an API, your own program asks whether there is anything new: that is pull. With a webhook, the other service gets in touch on its own as soon as there is something new: that is push. Polling every five minutes sends many requests that return nothing and, in the worst case, learns of an event five minutes late.
Webhooks complement APIs rather than replace them. Often the webhook only carries the notice that something has changed, and the receiver then fetches the details through the API.
How it works
The process has three steps. First, the receiver sets up an address that can accept requests, the endpoint, and registers it with the sending service, together with the events it cares about. When one of them occurs, the service sends an HTTP POST request to that address, usually with the data in JSON. The receiver confirms receipt with a status code in the 2xx range.
An example from email marketing: Mailchimp can send webhooks when someone subscribes or unsubscribes, changes their email address, or when a campaign has been sent. A CRM can then update a contact's status straight away, without syncing the list at intervals.
Each provider decides two things for itself. The first is the waiting time. GitHub expects a 2xx response within ten seconds; otherwise it terminates the connection and treats the delivery as failed. The second is retries. GitHub does not automatically redeliver failed deliveries. Stripe, by contrast, keeps trying for up to three days in live mode, with exponential back-off. A receiver therefore has to check each service's documentation to find out what is lost when its server does not respond.
ReceiverSending service
1The receiver sets up an address that can accept requests, the endpoint, and registers it with the sending service, together with the events it cares about.
Endpoint and events
2When one of them occurs, the service sends an HTTP POST request to that address, usually with the data in JSON.
HTTP POST with JSON
3The receiver confirms receipt with a status code in the 2xx range.
2xx status code
Each provider decides two things for itself: the waiting time and retries.
GitHubExpects a 2xx response within ten seconds; otherwise it terminates the connection and treats the delivery as failed.Does not automatically redeliver failed deliveries.
✕
StripeKeeps trying for up to three days in live mode, with exponential back-off.
up to three days
The flow is the same everywhere; the rules for failure are not.
Why it matters
Webhooks connect tools without anyone moving data by hand. A new order in the shop can trigger an invoice, a CRM entry and a follow-up email. Many marketing automation workflows run on events like these.
Because an endpoint is reachable from the internet, anyone can call it. That is why many providers sign their webhooks. GitHub sends an HMAC hash in the X-Hub-Signature-256 header, computed from the webhook's secret token and the payload. HMAC is a mechanism for message authentication using cryptographic hash functions, described in RFC 2104 from February 1997. The receiver computes the same hash and compares the two. GitHub and Stripe advise doing this with a constant-time comparison rather than a plain equality operator.
A receiver needs to know two more properties. Stripe states that an endpoint might occasionally receive the same event more than once, and that it does not guarantee delivery in the order events are generated. Stripe also puts a timestamp into the signature; by default its libraries reject messages older than five minutes, to fend off replayed messages.
Best practices
Verify the signature of every incoming message and discard messages without a valid signature.
Compare the hash in constant time, not with a plain equality operator.
Respond with 2xx straight away and do the actual processing afterwards, in a queue.
Store the ID of every event and process duplicates only once.
For events where order matters, fetch the current state through the API.
Check whether the service retries failed deliveries and, if it does not, recover missed events yourself.
Common mistakes
Running the endpoint without signature verification, so anyone can inject fake events.
Doing lengthy processing before responding and so exceeding the service's time limit.
Treating every event as unique and, for example, creating an order twice.
Assuming that every service retries failed deliveries automatically.
Keeping the secret in source code or in a public repository.
Manuel Riveiro RodriguezCEO & Digital Strategist
A technical audit covers this and everything else in one pass.
A webhook is an HTTP request that a service sends automatically to a registered URL as soon as a specific event occurs. A CRM, for example, learns of a new order or sign-up straight away, without having to ask at regular intervals. The data usually arrives in JSON, sent with HTTP POST.
What is the difference between a webhook and an API?
With an API, your own program actively asks whether there is new data; this is called pull. With a webhook, the other service gets in touch on its own as soon as something happens; this is called push. The two are often combined: the webhook reports the change, and the details are fetched through the API.
How do you secure a webhook?
Mainly with a signature. The sender computes an HMAC hash from a secret key and the content of the message and sends it in a header. The receiver computes the same hash, compares the two in constant time and discards messages without a valid signature. A timestamp also protects against replayed messages.
What happens if the receiver is unavailable?
That depends on the service. Stripe retries delivery in live mode for up to three days, with growing intervals. GitHub, on the other hand, does not automatically redeliver failed deliveries; they can be recovered manually or with code. That is why every webhook calls for a look at the provider's own documentation.
Can a webhook send the same event twice?
Yes. Stripe states explicitly that an endpoint might occasionally receive the same event more than once, and that the order of events is not guaranteed. The receiver therefore stores the ID of every processed event and skips repeats, so that, for example, an order is not created twice.