Skip to main content

Webhook Signature

Zyphe signs webhook requests with HMAC-SHA256 when your organization has a webhook secret configured. Verify the signature before parsing or processing the payload.

Signature format

The X-Signature header contains a Unix timestamp and a hexadecimal signature:

t=<timestamp>,v0=<signature_hex>

Zyphe constructs the signed value from the timestamp, a dot, and the exact JSON request body:

signed_payload = "{timestamp}.{raw_json_payload}"

The organization webhook secret is a hexadecimal string. Decode it into bytes, then calculate the hexadecimal HMAC-SHA256 digest of signed_payload.

Verification steps

  1. Read X-Signature and extract t and v0.
  2. Reject an invalid timestamp or one outside your accepted tolerance. A five-minute tolerance is a common starting point for replay protection.
  3. Read the raw, unmodified request body. Do not parse and re-serialize it before verification.
  4. Construct {t}.{raw_request_body}.
  5. Decode your hexadecimal webhook secret and calculate the HMAC-SHA256 digest.
  6. Compare the computed hexadecimal digest with v0 using a constant-time comparison.
  7. Parse and process the request only after all checks pass.

If the signature is missing, malformed, expired, or does not match, return an error and do not process the event. Keep the secret server-side and rotate it immediately if it is exposed.