ROOKDocs
Getting Started Guide

Webhook signing

Webhook deliveries are signed so you can authenticate that Rook sent the payload and that it was not modified in transit.

Each endpoint has a secret that starts with whsec_. Use the entire secret string, including the prefix, as the HMAC key.

Headers

HeaderValue
Rook-TimestampUnix time in seconds when the signature was computed.
Rook-Signaturev1= of the HMAC-SHA256 digest. Multiple v1= values may be comma-separated during secret rotation.

Signed payload

The signed material is the timestamp, a literal ASCII dot, then the raw request body bytes (no re-encoding):

Code
{timestamp}.{body}

Verify a delivery

1. Read Rook-Timestamp and Rook-Signature. Reject the request if either is missing. 2. Reject the delivery if the timestamp is more than 300 seconds from the current time (replay window). 3. Compute HMAC-SHA256(secret, "{timestamp}.{body}") and hex-encode the digest (lowercase). 4. Compare the digest to each v1= value in Rook-Signature using a constant-time equality check. Succeed if any matches.

bash
# timestamp and body from the inbound HTTP request
signed_payload="${timestamp}.${body}"
expected=$(printf '%s' "$signed_payload" | openssl dgst -sha256 -hmac "$webhook_secret" | awk '{print $2}')

Respond with 2xx only after the signature verifies. If verification fails, respond with 401 and do not act on the event.

Secret rotation

When you roll a secret, deliveries may include two v1= signatures for a short period. Accept the request if either digest matches.