Webhooks: APIs That Call You
📨 Webhooks: APIs That Call You
The Reverse Direction: Why Webhooks Exist
Imagine wanting to know the moment a payment succeeds. Without webhooks, the only option is polling — repeatedly asking "has it succeeded yet?" (GET /payments/123/status) every few seconds, wasting requests and adding delay between the real event and when you find out about it. A webhook lets the payment provider push a notification to you the instant it happens, instead.
Polling vs. Webhooks
Polling
Your code repeatedly asks "did anything change?" — wasteful when nothing has, and laggy since you only find out on your next poll, not the instant it happens.
Webhooks
The other system tells YOU, immediately, the moment something happens — no wasted requests, no polling delay.
How a Webhook Actually Works
- You register a URL ("endpoint") with the provider — e.g. "call this URL when a payment succeeds."
- Something happens on their end (a payment succeeds).
- Their server sends an HTTP
POSTrequest to your registered URL, with a body describing the event. - Your server processes it and responds quickly with a
2xxstatus to acknowledge receipt.
A Realistic Payment-Succeeded Webhook Payload
Signature Verification: Proving the Request Is Genuine
Your webhook endpoint is just a public URL — anyone on the internet could send a fake POST request to it pretending to be the real provider. To guard against that, providers sign each payload using a shared secret (agreed on when you registered the webhook) and include the signature in a header, like X-Signature above. Your server recomputes the same signature — typically an HMAC (Hash-based Message Authentication Code) over the raw request body, using that same shared secret — and only trusts the request if the computed signature matches the one in the header.
What HMAC Verification Confirms
That the payload genuinely came from someone holding the shared secret (presumably the real provider), and that it wasn't altered in transit — both of which a plain, unsigned POST can't guarantee.
What It Doesn't Do
It doesn't encrypt the payload (HTTPS/TLS already handles confidentiality in transit) — it only proves authenticity and integrity of the message itself.
Common Real-World Providers
Stripe sends webhooks for payment and subscription lifecycle events (succeeded, failed, refunded). GitHub sends webhooks for repository events (a push, a pull request opened, a comment posted) — the exact mechanism that powers a lot of CI/CD automation. Slack sends webhooks for message and interaction events, letting external apps react to things happening inside a workspace. All three follow the same shape this chapter describes: register a URL, get a signed POST the moment something happens.
Reliability: Retries and Idempotency
Providers generally can't guarantee your endpoint is always up, so most implement at-least-once delivery: if your endpoint doesn't respond with a 2xx quickly (or times out), they'll retry — which means your endpoint might genuinely receive the same event more than once. This is the same underlying problem Chapter 4's Idempotency-Key pattern solved for outgoing requests, just from the receiving side: each webhook payload includes a unique event id (like evt_1Nx8k above), and your handler should track which ids it's already processed, skipping any repeat instead of, say, charging a customer or sending a confirmation email a second time.
💻 Coding Challenges
Challenge 1: Polling vs Webhook
A food delivery app needs to know the instant a driver marks an order as delivered, to notify the customer immediately. Recommend polling or a webhook, and justify using this chapter's comparison.
Goal: Practice recognizing when the instant-notification property of webhooks genuinely matters.
Challenge 2: Verify a Webhook Signature
Describe, step by step, what a server should do upon receiving a webhook with an X-Signature header, to determine whether to trust the payload or reject it.
Goal: Practice explaining the HMAC verification process concretely, not just naming it.
Challenge 3: Handle a Duplicate Webhook Delivery
A payment.succeeded webhook with event id evt_1Nx8k arrives twice, a few seconds apart, because your server's first acknowledgement was slow. Describe how your handler should avoid sending the customer two confirmation emails.
Goal: Practice applying event-id-based deduplication to a concrete double-delivery scenario.
It's tempting to do the real work — sending a confirmation email, updating several database records, calling another service — directly inside the webhook handler, before responding. But if that work takes too long, the provider's request can time out waiting for your 2xx response, conclude the delivery failed, and retry — even though your server actually received and is still processing the original one. The fix mirrors the background-job pattern already covered in the Django, Rails, and Laravel courses: acknowledge receipt immediately with a fast 2xx, then hand the real work off to a background job or queue, processed asynchronously after the response has already gone out.
🎯 What's Next
The next chapter, Choosing the Right API Style, brings everything together — a decision framework comparing REST, SOAP, RPC/gRPC, GraphQL, WebSockets, and Webhooks by use case, so you can pick the right one deliberately instead of by habit.