Verifying Webhook Signatures

Every webhook delivery from WhoComply is signed with your endpoint's signing secret. Always verify the signature before processing the payload.

Signature Format

Each request includes an X-Whocomply-Signature header:

X-Whocomply-Signature: t=1713369600,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8f9

The header contains two values separated by a comma:

  • t — Unix timestamp (seconds) when the signature was generated
  • v1 — HMAC-SHA256 hex digest

Verification Steps

  1. Extract the t and v1 values from the header
  2. Build the signed payload: {t}.{raw_request_body}
  3. Compute HMAC-SHA256 of that payload using your signing secret
  4. Compare your computed signature with v1 (constant-time comparison)
  5. Check that t is within 5 minutes of your server's current time (replay protection)

Code Examples

# Extract values
HEADER="t=1713369600,v1=5257a869..."
TIMESTAMP=$(echo "$HEADER" | grep -o 't=[0-9]*' | cut -d= -f2)
SIGNATURE=$(echo "$HEADER" | grep -o 'v1=[a-f0-9]*' | cut -d= -f2)

# Compute expected signature
EXPECTED=$(echo -n "${TIMESTAMP}.${BODY}" | \
  openssl dgst -sha256 -hmac "$SIGNING_SECRET" | awk '{print $2}')

# Compare
if [ "$EXPECTED" = "$SIGNATURE" ]; then
  echo "Valid"
fi

Replay Protection

The timestamp t prevents replay attacks. Reject any webhook where the timestamp is more than 5 minutes from your server's clock. This ensures an attacker cannot re-send an intercepted webhook payload later.

Was this page helpful?