Skip to main content
Your endpoint is a public URL. Anyone can POST to it. Verify the signature before you act on a payload. X-LazyApp-Signature is sha256= followed by an HMAC-SHA256 of the raw request body, keyed with your endpoint’s signing secret.

Implementation

Three ways this goes wrong

The most common mistake. Any JSON framework that re-serialises the body will reorder keys or change whitespace, and the HMAC will never match. Capture the raw bytes before parsing.
A normal string comparison returns early on the first differing byte, which leaks the secret to an attacker who can measure it. Use timingSafeEqual, hmac.compare_digest or hash_equals.
A valid signature proves the payload came from LazyApp, not that it is fresh. Deduplicate on X-LazyApp-Delivery so a replayed delivery cannot double-apply.

Rotating a secret

Use POST /v1/webhooks/{webhook}/rotate-secret or rotate from the console. Replays continue to verify because they are re-signed with the current secret by default.

Meta’s inbound signature

Separately, LazyApp verifies Meta’s own X-Hub-Signature-256 on every inbound WhatsApp webhook and deduplicates redelivered events before they reach your workspace. You do not need to handle that — it happens before anything is written.