Skip to main content
Webhooks are in beta. Event types and payload shapes may still change. We’ll email orgs with active endpoints before any breaking change.
Every webhook POST carries a signature so you can prove it came from Origami. Verify it before acting on the payload.

The contract

The signature is HMAC-SHA256 over the literal string {webhook-id}.{webhook-timestamp}.{raw-body} using your whsec_… secret as the HMAC key. We follow the canonical Standard Webhooks spec exactly: the prefix whsec_ is stripped and the remainder is base64-decoded to produce the raw key bytes. The Svix standardwebhooks SDK does this for you in one line. Headers we send on every POST: Receivers SHOULD:
  1. Reject signatures whose timestamp is more than ±5 minutes from their wall clock (replay protection).
  2. Compare with a constant-time byte equality (timingSafeEqual in Node, hmac.compare_digest in Python, etc.). A == compare leaks the signature byte-by-byte.
  3. Accept any v1,<sig> entry as a match — during a 24h secret rotation we send two.
  4. Dedupe on webhook-id with at least 5 minutes of retention.

One-line option (Node)

The standardwebhooks SDK strips the prefix and base64-decodes the remainder for you, so it’s byte-for-byte compatible with the snippets below.

Node

Python

Go

Ruby

Rust

curl + openssl

For ad-hoc verification of a captured payload (e.g. from a copy out of the dashboard’s delivery drawer):