Ship with confidence

Consume signed webhooks safely

Webhooks notify your system that a durable event is available. Delivery is at least once: verify every signature, deduplicate event IDs, and fetch authoritative resources from the API.

Create an endpoint

{
  "project_id": "prj_REPLACE_ME",
  "url": "https://integrations.example.com/accesspreflight/webhooks",
  "events": ["scan.completed", "scan.failed"]
}

Use an HTTPS endpoint. The API shows the signing secret once. Store it in a secret manager, not in source control.

Signature format

The AccessPreflight-Signature header has this form:

t=<unix-seconds>,v1=<hex-hmac-sha256>

The signed message is:

<timestamp>.<exact raw request body bytes>

Compute HMAC-SHA256 with the endpoint secret and compare the expected and received digests in constant time. Reject stale timestamps according to your replay window.

Node.js verification example

import { createHmac, timingSafeEqual } from 'node:crypto'

const verify = ({ rawBody, signatureHeader, secret, now = Date.now() }) => {
  const fields = Object.fromEntries(
    signatureHeader.split(',').map((part) => part.split('=', 2)),
  )
  const timestamp = Number(fields.t)
  if (!Number.isSafeInteger(timestamp)) return false
  if (Math.abs(Math.floor(now / 1000) - timestamp) > 300) return false

  const expected = createHmac('sha256', secret)
    .update(`${timestamp}.`)
    .update(rawBody)
    .digest()
  const received = Buffer.from(fields.v1 || '', 'hex')
  return (
    received.length === expected.length && timingSafeEqual(received, expected)
  )
}

Capture the raw bytes before JSON parsing. Re-serializing parsed JSON changes the signed payload.

Acknowledge quickly

  1. Verify timestamp and signature.
  2. Persist the event ID with a unique constraint.
  3. Return 2xx.
  4. Process asynchronously.
  5. Fetch the referenced scan or delivery state through the API.

Webhooks carry IDs and summaries, not complete source or report content.

Delivery and replay

AccessPreflight retries failed deliveries for up to 24 hours. Duplicate deliveries are normal. A permanent failure pattern can disable an endpoint.

Use the delivery log to diagnose response codes and replay a specific delivery after fixing your consumer. Replays keep the event identity semantics, so the same deduplication rule remains safe.

Rotate with overlap

Secret rotation supports a 24-hour overlap. During the overlap, accept a valid signature from either secret, then remove the old secret from your verifier after the deadline.

Search documentation