What Is a Webhook?
An HTTP request one system sends to a URL you provide, when something happens. The term was coined in 2007.
A webhook is an HTTP request that one system sends to a URL you supply, automatically, when a particular event occurs. The original and still the clearest definition is a user-defined HTTP callback.
The term was coined by Jeff Lindsay in a blog post dated 3 May 2007 titled Web hooks to revolutionize the web. It combines the web with the programming concept of a hook, a point where custom code can be attached to intercept an event.
Webhooks compared with the alternatives
| Approach | Who initiates | Latency | Cost when idle | Main drawback |
|---|---|---|---|---|
| Polling | You, repeatedly | Up to the poll interval | High, most calls return nothing | Wasteful and always slightly stale |
| Webhook | The provider, on the event | Near immediate | None | You must run a public endpoint |
| WebSocket | Either, over a held connection | Immediate | A connection per client | Stateful, reconnection logic needed |
| Server-sent events | The provider, over a held connection | Immediate | A connection per client | One-directional, fewer integrations |
The practical appeal is the idle column. Polling an API every minute for an event that happens twice a day makes 1,440 requests to learn something twice. A webhook makes two.
What a webhook request contains
Almost always an HTTP POST to your URL, with a JSON body describing what happened and headers carrying metadata. The headers usually include an event type, a unique event ID, a timestamp, and a signature.
The event ID is the one people skip and later need. It is what lets you recognise a duplicate delivery, which you will receive.
Verifying that it came from who it claims
A webhook endpoint is a public URL that accepts POST requests from the internet. Anyone who learns the address can send it anything, so the payload must be authenticated before it is trusted.
The de facto pattern across major providers is an HMAC signature, usually SHA-256, computed over a timestamp and the raw request body using a shared secret. You recompute it and compare.
Two details matter. Compute the signature over the raw bytes, not the parsed and re-serialised JSON, because re-serialising changes the bytes. And check the timestamp, rejecting anything older than a few minutes, or a captured request can be replayed indefinitely.
Delivery is at-least-once, not exactly-once
Providers retry failed deliveries, typically with exponential backoff over hours or days before giving up. A network blip after your server processed the event but before the response arrived produces a retry of work already done.
Handlers therefore have to be idempotent, meaning processing the same event twice has the same effect as processing it once. Recording processed event IDs and discarding repeats is the usual implementation.
Ordering is not guaranteed either. A created and an updated event for the same object can arrive out of order, so handlers that assume sequence will eventually be wrong.
Respond fast, work later
The standard guidance is to acknowledge with a 2xx as quickly as possible and do the actual work asynchronously. Providers time out, and slow handlers trigger retries that queue behind each other.
This creates a well-known blind spot: your 200 means received, not processed. If the background worker fails afterwards, the provider's dashboard shows a successful delivery for an event that had no effect.
Related concepts
Verifying that events actually land is covered in webhook monitoring. Where events form an ordered chain, see business flow monitoring.