OpenAPI

GUIDES

Receive signed webhooks

Build a webhook receiver that verifies authenticity and deduplicates before side effects.

Receiver sequence

  1. Read the raw request body without normalizing JSON first.
  2. Require the Lucion webhook ID, timestamp, and signature headers.
  3. Reject timestamps outside the five-minute window.
  4. Verify HMAC-SHA256 over timestamp.event_id.raw_body with constant-time comparison.
  5. Deduplicate by event ID plus subscription ID, then apply the side effect.
Verification outline
const rawBody = await request.text();
const eventId = request.headers.get("X-Lucion-Webhook-Id");
const timestamp = request.headers.get("X-Lucion-Webhook-Timestamp");
const signature = request.headers.get("X-Lucion-Webhook-Signature");
const valid = await verifyWebhookSignature(signature, { secret, eventId, timestamp, rawBody });
// Verify the raw payload before JSON.parse and before side effects.
// Store eventId + subscriptionId as the idempotency key.