Webhooks
Webhook integration
A webhook is a message another system sends to your server when something happens: a payment succeeds, an order is placed, a form is submitted, a document is signed. Webhooks are faster and lighter than repeatedly asking an API for changes, but they arrive whenever the sender chooses, may arrive twice or out of order, and could be faked by someone who discovers your endpoint. A safe webhook integration verifies every message, responds quickly and processes events reliably.
This page explains how to receive webhooks safely and dependably.
Illustrative diagram
- Event arrives
- Verify signature
- Acknowledge
- Queue
- Duplicate check
- Process
Receiving a webhook properly
Verify
Check the signature using the shared secret before trusting the message.
Output: Authentic event
Acknowledge
Return a success response quickly; GitHub, for example, asks for a response within 10 seconds.
Output: No sender timeout
Queue
Place the event on a queue for processing.
Output: Work done reliably
Check for duplicates
Skip events already processed, using the event or delivery ID.
Output: No double actions
Process
Update records, fetching current data from the API if needed.
Output: Systems in step
Verify every message
Anyone who learns your webhook address can send it a request. Without verification, an attacker could send a fake 'payment succeeded' event and trigger an order to ship. Senders such as Stripe and GitHub sign each webhook with a secret shared only with you; your endpoint must check that signature before acting. Stripe's documentation notes that verification uses the raw request body, so frameworks that alter the body can break it, and that a timestamp in the signature lets you reject old messages replayed by an attacker.
Keep webhook secrets out of code and rotate them periodically, as Stripe recommends.
Webhook realities to design for
| Reality | Design response |
|---|---|
| Events can arrive more than once | Record processed event IDs and skip repeats |
| Order is not guaranteed | Do not depend on sequence; fetch current state when needed |
| Senders retry failed deliveries | Acknowledge quickly and keep the endpoint available |
| Your server may be down | Redeliver or reconcile missed events afterwards |
| Payloads may change with versions | Check event types and versions before processing |
Acknowledge first, work later
Webhook senders expect a quick response. If your endpoint does slow work, such as updating accounting, generating documents or calling other APIs, before responding, the sender may time out and retry, producing duplicates and load. The reliable pattern, recommended by both Stripe and GitHub, is to verify the message, store it on a queue, respond immediately and process it in the background. The queue also smooths spikes, such as many subscriptions renewing at once at the start of the month.
Processing from a queue makes retries of your own simple when a downstream system is briefly unavailable.
Treat the webhook as a prompt
Because events can arrive late or out of order, a webhook is often best treated as a prompt to check the current state rather than as the final truth. For example, on receiving 'invoice paid', fetch the invoice from the API and act on its current status. That way, a delayed or repeated event cannot overwrite newer information with older data.
Securing the endpoint
Transport
- HTTPS with a valid certificate
- Endpoint only accepts the expected method
- No secrets in the URL
Verification
- Signature checked on the raw body
- Old timestamps rejected
- Secrets rotated periodically
Limits
- Only subscribe to event types you need
- Reject unexpected payload sizes
- Log failures without secrets
Testing webhook handling
Senders often provide tools to send test events to a development endpoint; Stripe, for example, offers a command-line tool that forwards events to a local server. Test not just the happy path but duplicates, events in an unexpected order, invalid signatures, old timestamps and your endpoint being unavailable for a while. Confirm that each case behaves as designed before going live.
Keep a record of test event types and expected outcomes so tests can be repeated after changes.
When webhooks are the right choice
Webhooks suit events you want to react to quickly, such as payments, orders or sign-ups, without constantly polling an API. They work best alongside an occasional reconciliation that checks for anything missed. For bulk historical data, or where a sender offers no webhooks, scheduled API calls remain necessary. The software integration page compares methods across a whole set of systems.
Subscribe only to what you need
Stripe advises listening only to the event types your integration requires; extra events add load without value. Review subscriptions when the integration changes.
Questions about webhook integration
What is a webhook?
A message another system sends to your server when something happens.
Why verify webhook signatures?
So fake messages cannot trigger actions such as shipping unpaid orders.
Why respond quickly?
Senders time out and retry; GitHub asks for a 2xx response within 10 seconds.
Can the same event arrive twice?
Yes; Stripe notes endpoints may occasionally receive duplicates, so record processed IDs.
Do webhooks arrive in order?
Not necessarily; Stripe does not guarantee order, so design for any sequence.
What if our server was down?
Use the sender's retries, redelivery tools or reconciliation to catch up.
Sources referenced
Platform features, guidance and rules change. We check the current versions before committing to an approach. This page is general information, not legal advice.
- Stripe: Receive Stripe events in your webhook endpoint (opens in a new tab) — reviewed 2026-10-23
- GitHub: Best practices for using webhooks (opens in a new tab) — reviewed 2026-10-23
Request a Custom Quote
Ask about Webhook integration
Thank you — your enquiry has been sent.
We have received your message and will reply by email. If you need to add anything, email info@letgetgrow.com.