Webhooks
Instead of constantly asking "anything new?" — just get a tap on the shoulder when something happens.
The Simple Version
You order a package online. You could check the front door every 5 minutes to see if it arrived. That's annoying and wasteful — most of the time there's nothing there.
Or you could give the delivery driver your phone number and say: "Text me when you drop it off." Now you go about your day, and the moment the package arrives, you get a notification. No checking, no wasting time.
That's a webhook. It's one app saying to another: "When this thing happens, send me a message at this address." The address is a URL — a specific page on your server that's listening for incoming data.
The "checking every 5 minutes" approach is called polling. Webhooks replace that. Instead of you asking over and over, the other app tells you when something changes.
How It Actually Works
The Setup
You register a webhook URL with the service you want to listen to. This is just an endpoint on your server — a route that accepts incoming HTTP POST requests.
# In Stripe's dashboard, you'd set:
# Webhook URL: https://your-app.com/webhooks/stripe
# Events: payment_intent.succeeded, charge.failed
When the event happens (someone pays, a form is submitted, a repo gets a push), the service sends a POST request to your URL with a JSON payload describing what happened.
What the Data Looks Like
A Real Handler
Here's what a basic webhook endpoint looks like in Express (Node.js):
app.post('/webhooks/stripe', (req, res) => {
const event = req.body;
switch (event.type) {
case 'payment_intent.succeeded':
// Unlock the user's access
grantAccess(event.data.object.customer);
break;
case 'charge.failed':
// Notify the user
sendFailureEmail(event.data.object.customer);
break;
}
// Always respond 200 — otherwise the sender retries
res.status(200).json({ received: true });
});
Real World Examples
Security: Don't Trust Blindly
Anyone can send a POST request to your webhook URL. If you don't verify it, an attacker could fake events — like telling your app a payment succeeded when it didn't.
Check the HMAC header against your secret key
Never expose a webhook over plain HTTP
Do heavy work async — just acknowledge receipt
Make your handler idempotent — same event twice = same result
Key Takeaways
- Webhooks are reverse APIs — instead of you asking for data, the data comes to you
- They replace polling — no more "anything new?" every 5 seconds
- Always verify the signature — anyone can POST to your URL
- Respond 200 immediately — do the real work in the background, or the sender retries
- Make handlers idempotent — you might receive the same event more than once