Community content. Review instructions before giving them to an AI agent — treat modules like open-source code.
Webhook Handling
How to receive any provider's webhooks safely: signature verification, idempotent processing, fast acknowledgment, and ordering assumptions.
Mby @markdownersPublished July 12, 2026 · Updated August 21, 2026 · ~2 min read
0 downloads · Used in: E-commerce checkout context
A webhook endpoint is a public URL that anyone on the internet can POST to. Treat every incoming webhook as untrusted input until its signature is verified — this applies to payment webhooks (building on Payment System Basics@markdowners/payment-system-basics) and equally to any other provider's webhooks.
Signature verification
- Always verify the provider's signature (HMAC or equivalent) on every incoming webhook before processing it, using the raw, unparsed request body — most signature schemes sign the exact byte sequence sent, and re-serializing a parsed JSON body before verifying will produce a different signature and false rejections (or worse, false acceptances if you skip verification instead of fixing this).
- Never trust a webhook based on the request coming from an expected IP range alone, and never trust an unsigned webhook just because the payload "looks right" — treat signature verification as non-optional, not a nice-to-have.
Idempotency
- Every webhook event has an ID; store processed event IDs and skip reprocessing on a duplicate delivery — providers explicitly document that the same event may be delivered more than once, and your handler must be safe to run twice with the same event.
- Design the handler's side effects (updating an order, sending an email) to be idempotent themselves as a second layer of defense, not just relying on the dedup check.
Fast acknowledgment
- Respond
200quickly (parse, verify, enqueue for processing) rather than doing slow work (sending emails, calling other APIs) synchronously inside the webhook handler — most providers retry on timeout, and a slow handler causes duplicate deliveries and, eventually, the provider disabling your endpoint for being unreliable. - If heavier processing is required, verify and acknowledge first, then hand off to a background job/queue.
Ordering and consistency
- Never assume webhooks arrive in the same order events occurred — a "payment succeeded" event can arrive before or after a related "order updated" event depending on provider retry timing. Design handlers to check current state before applying an update, not to assume a specific sequence.
- Use the event's own timestamp/version, not arrival order, when a handler needs to determine which of two related events is authoritative.
Failure handling
- Log every webhook receipt (event type, ID, verification result) even on failure, so a missed or misprocessed event is diagnosable after the fact rather than silently lost.
- Return a non-2xx status only when you genuinely want the provider to retry — returning an error for a permanently unprocessable event (e.g. a malformed payload you can never fix by retrying) just wastes retries; log it and return 200 instead, then alert separately.
Local development
- Use the provider's CLI/forwarding tool to receive real webhook events locally — don't rely on manually simulating payloads, which drifts from the real shape over time. See Stripe Integration@markdowners/stripe-integration for provider-specific detail.
Requires
- Payment System Basics@markdowners/payment-system-basics
You might also add
- Stripe Integrationsuggested
Badge
Link back to this module from your own README.
[](https://markdowners.com/m/markdowners/webhook-handling)Discussions about this module
No discussions about this module yet.
Start a discussion
Comments (0)
Sign in to comment. Sign in
No comments yet. Be the first to add one.