---
updatedAt: 2026-03-31T09:17:30.000Z
agentTools:
  projectIndex: https://docs.zerohash.com/llms.txt
---

# Webhook Security

Zero Hash webhooks use request headers to ensure secure message delivery and verification. Our preferred method for securing webhooks is **RSA-based signing**, which avoids transmitting shared secrets and enables strong authenticity guarantees. We also support **HMAC token-based signatures** which can be configured for your platform, please reach out to your zerohash representative for more information.

**📢  Security Enhancement**\
To strengthen webhook security against replay attacks, we’ve introduced a new mechanism that includes a timestamp and new signature headers. These additions allow you to verify not only the authenticity of a webhook, but also its timeliness, helping prevent intercepted messages from being reused maliciously.

<br />

***

**🔄 Graceful Transition Plan**\
To allow a smooth migration, both the existing and new security headers will be sent during a grace period. We encourage clients to begin validating the new headers as soon as possible, as the old headers will be deprecated in the future.

✅ Current headers: Will continue to be sent during the transition.

✅ New headers: Available now for improved protection.

❌ Deprecated: The old signature-only verification will be phased out after the grace period (timeline to be announced).

<br />

***

**🔧 Header Reference**

**Standard Headers**

| Name                        | Type     | Description                                                                           |
| --------------------------- | :------- | ------------------------------------------------------------------------------------- |
| `x-zh-hook-notification-id` | `string` | Unique identifier for the notification. Use for idempotency checks.                   |
| `x-zh-hook-payload-type`    | `string` | Type of payload (e.g., participant\_status\_changed, payment\_status\_changed, etc.). |

Depending on your security configuration, additional headers may also be included:

<br />

**Current Security Headers (Legacy)**

| Name                          | Description                                                                              |
| ----------------------------- | ---------------------------------------------------------------------------------------- |
| `x-zh-hook-signature-256`     | `to_hex(hmac(sha_256(payload), your-secret))`used if token-based signing was configured. |
| `x-zh-hook-rsa-signature-256` | `to_hex(rsa(sha_256(payload), zh-sec-key))`— RSA signature of payload.                   |

<br />

**New Security Headers (Replay Attack Protection)**

| Name                      | Description                                                                                                                                                                               |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `x-zh-hook-timestamp`     | UNIX timestamp (in milliseconds) when the webhook request was generated. Clients should validate that this value is within an acceptable window (e.g., ±5 minutes) of their system clock. |
| `x-zh-hook-signature`     | `to_hex(hmac(sha256(payload + timestamp), your-secret))` — includes timestamp in signature for replay protection.                                                                         |
| `x-zh-hook-rsa-signature` | `to_hex(rsa(sha256(payload + timestamp), zh-sec-key))` — RSA signature of payload + timestamp.                                                                                            |

<br />

***

**🛡️ Recommended Verification Process**

1. **Extract** the following from the headers:
   1. `x-zh-hook-timestamp`
   2. `x-zh-hook-signature` or `x-zh-hook-rsa-signature`
2. **Check the timestamp**:
   1. Ensure it's within ±5 minutes of your system time to guard against replay attacks.
3. **Reconstruct the signed message:**
   1. Concatenate `payload + timestamp` (as raw strings, no delimiters).
4. **Validate the signature:**
   1. For HMAC: Compute `hmac(sha256(payload + timestamp), your-secret)`.
   2. For RSA: Verify `rsa(sha256(payload + timestamp), zh-public-key)`.

<br />

> 📘 Note: the "zh-public-key" will be provided to you by a zerohash representative. This is **not** the public key associated with an API key.

***

**:compass: IP Addresses**

Zero Hash’s webhook requests will originate from the following IP addresses, should you need an allow-list:

* `18.189.25.175/32`
* `3.18.218.32/32`
* `3.22.145.85/32`

<br />

## Sample Webhook Signatures

[block:tutorial-tile]
{
  "backgroundColor": "#00fa97",
  "emoji": "🤝",
  "id": "6626ec1075936900247031d5",
  "link": "https://zerohash.readme.io/v1.0/recipes/webhook-signatures",
  "slug": "webhook-signatures",
  "title": "Webhook Signatures"
}
[/block]