Skip to main content

SaaS webhook security: signatures, retries and idempotent handling

Secure webhook delivery and receivers with HMAC verification, HTTPS, replay-aware event handling, idempotent processing and monitored retries.

In this guide

How do you secure a SaaS webhook receiver?

A webhook sends an event to an HTTPS endpoint when something changes. Because an endpoint may be called by anyone who can reach it, verify the provider's signature before trusting or processing the payload. HMAC can authenticate a message when the sender and receiver share a secret; it does not automatically prevent duplicate delivery, replay or business-level mistakes.

Verify the signature over the original request body

Follow the provider's exact signing format and verify the signature against the raw bytes before parsing or normalising JSON. Use a vetted cryptographic library and a constant-time comparison. GitHub documents an HMAC-SHA256 signature over the payload; other providers may use different headers or formats, so never assume they are interchangeable.

Use HTTPS and keep the signing secret out of the URL

Require HTTPS with certificate verification and store each endpoint secret in managed secret storage. Do not put the secret in a query string, source code, client-side configuration or logs. Limit who can view, rotate or replace the secret and record changes without storing its value.

Validate event type, tenant and allowed actions

After signature verification, validate the expected event type, payload shape, tenant, resource and state transition. A valid signature proves the message used a shared secret; it does not prove the requested business action is allowed in the current account or still current. Recheck authorization and state before applying the change.

Webhook delivery and receiver checklist
Provider / eventSignature and key versionDeduplication keyRetry and ordering policyAlert owner / test date

How should a receiver handle retries and duplicate events?

Acknowledge quickly and process asynchronously

Verify the request, persist a small delivery record and enqueue the work before returning the provider's expected success response. Avoid slow database workflows or third-party calls in the request window. Follow the specific provider's timeout and retry behavior; GitHub, for example, recommends responding to its deliveries within ten seconds.

Make event processing idempotent

Use a stable provider delivery ID or event ID with a uniqueness constraint in your durable inbox. If the same signed delivery arrives again, acknowledge it without repeating the side effect. For business actions such as payment updates, also check the current resource state because different event IDs may describe the same underlying change.

Plan for delayed and out-of-order messages

Do not assume delivery order is business order. Compare a provider version, event timestamp or resource version where available, and fetch current provider state when a stale event could cause an incorrect transition. Make retry, dead-letter and manual replay paths visible and safe to run twice.

How do you operate webhook integrations over time?

Rotate secrets with a controlled overlap

Create a replacement secret, update the provider and monitor successful deliveries before removing the old key. If your protocol permits, verify against a short list of active key versions during the change window. Set a removal deadline; indefinite dual verification makes a retired secret useful to an attacker.

Subscribe only to needed events and monitor delivery health

Limit subscriptions to events the integration handles. Track accepted, rejected, delayed and repeatedly failing deliveries by endpoint and tenant, but redact payload secrets and personal data from telemetry. Alert on sustained failure or backlog and provide a scoped tool for authorized redelivery.

Test signature, replay and outage cases

Test invalid signatures, changed payload bytes, missing headers, repeated IDs, secret rotation, provider timeouts, receiver outages and oversized payloads. Confirm an invalid request is rejected before side effects, a retry does not duplicate work and operators can safely replay a missed event.

SaaS webhook questions

Should I parse JSON before checking the signature?

No, when the provider signs the original body. Read the raw request bytes, verify the provider's signature as documented and only then parse and validate the payload. A framework's body parser may need a raw-body route or middleware configuration.

Can I trust a webhook because it came from a known IP address?

An IP allowlist can add a network control when the provider publishes stable ranges, but it does not replace signature validation. Provider ranges can change; maintain them from the official source and keep TLS verification enabled.

Should webhook retries run the business action again?

A retry should safely complete work that did not finish, not repeat an already committed side effect. Persist a delivery ID, make the handler idempotent and reconcile the resource's current state before applying changes.