Skip to main content
Always verify webhook signatures before processing any event. Skipping this step opens your application to spoofed requests.

How Signatures Work

HOST Pay signs every outgoing webhook using HMAC-SHA256. The signing input is:
Where:
  • timestamp is the Unix epoch value from the X-Webhook-Timestamp header (as a string).
  • compact_json_body is the raw request body serialized with no extra whitespace.
The resulting signature is hex-encoded and placed in the X-HostPay-Signature header with a v1= prefix (e.g., v1=abc123...).

Verification Steps

  1. Extract the raw timestamp from X-Webhook-Timestamp.
  2. Read the raw request body before parsing it as JSON.
  3. Construct the signed string: timestamp + "." + raw_body.
  4. Compute HMAC-SHA256(secret, signed_string) and hex-encode it.
  5. Compare your result to the value after the v1= prefix using a constant-time comparison.
  6. Optional but recommended: Reject requests where the timestamp is more than 5 minutes old to prevent replay attacks.
The official SDKs implement all of the steps above — constant-time comparison and replay protection included. Pass the raw request body and headers straight from your framework:
Deliveries older than 5 minutes are rejected by default (pass a custom tolerance in seconds to change this).

Verifying Manually

Implementing the check yourself in another language:
Read the raw request body before any JSON parsing — re-serializing the parsed body changes whitespace and breaks signature verification.