For platforms whose security policy requires an authenticated bearer token on inbound calls from zerohash. Covers how the flow works, what zerohash needs from you, and what to configure on your side. The security method is set by zerohash, not through the API. There is no API change to make.
1. Available security methods
zerohash offers four ways to authenticate an outbound webhook. One applies per platform.
| Security method | What zerohash sends on each webhook |
|---|---|
| RSA | x-zh-hook-rsa-signature-256, x-zh-hook-rsa-signature, x-zh-hook-timestamp |
| Shared Secret | x-zh-hook-signature-256, x-zh-hook-signature, x-zh-hook-timestamp |
| OAuth 2.0 Client Credentials | Authorization: Bearer <token> |
| OAuth 2.0 Client Credentials with RSA | Authorization: Bearer <token> plus the three RSA signature headers |
RSA is the default and remains zerohash's recommendation. The OAuth 2.0 options exist where a bearer token is mandatory.
2. Which method fits your listener
| If your webhook listener... | Choose |
|---|---|
| verifies the payload signature only | RSA |
| requires a bearer token only | OAuth 2.0 Client Credentials |
| requires a bearer token and verifies the payload signature | OAuth 2.0 Client Credentials with RSA |
OAuth 2.0 Client Credentials replaces payload signing. If your listener checks both, you need the combined method; tell zerohash during setup.
3. How the OAuth 2.0 flow works
Your identity provider (IdP) issues the token. zerohash is a client of it.
- You register zerohash as a client in your IdP and issue it a
client_id. - zerohash generates a dedicated key pair and gives you the certificate. You register it directly, or zerohash publishes it at a JWKS URL for your IdP to read. No client secret is involved: the private key never leaves zerohash and no shared secret travels over the wire.
- Before each delivery window, zerohash signs a short-lived JWT with that private key and exchanges it at your token endpoint for an access token. This is the JWT bearer client assertion flow, RFC 7523 (
private_key_jwt), withgrant_type=client_credentials. - zerohash caches the token and refreshes it in the background, so your IdP sees one token request per lifetime rather than one per webhook.
- Every webhook for your platform carries that token as
Authorization: Bearer <token>.
The assertion zerohash sends is signed RS256, carries a unique jti per request, and has a lifetime of five minutes or less.
4. What zerohash needs from you
Please provide all of the following, for each environment you will integrate with. Setup cannot begin until each is confirmed.
| Item | Why it is needed |
|---|---|
| Token endpoint URL | Where zerohash exchanges the signed assertion for an access token. Must be HTTPS. Provide the URL for each environment separately if they differ. |
client_id issued to zerohash | Identifies zerohash at your IdP. |
| Resource URI or scopes | ADFS-based IdPs expect a resource parameter; others expect scopes. Tell us which your IdP requires, and the exact value. |
Expected audience | zerohash defaults to your token endpoint URL with a trailing slash, which is what ADFS expects. Confirm this, or give the value your IdP validates against. |
| How zerohash's certificate is registered | Either you upload the certificate to your IdP directly, or your IdP reads it from a JWKS URL. Tell us which, and whether your IdP matches the key by certificate thumbprint (and in which case) or by x5t. This is the most common cause of a rejected token, so please be specific. |
| Access token lifetime | Lets zerohash size its refresh interval correctly. |
| Whether your listener also verifies the payload signature | Determines whether you receive the signature headers alongside the token. |
| Your webhook listener URL | Where zerohash delivers. Provide one per environment. |
| The events you want to receive | zerohash configures your event subscriptions. |
| Confirmation that zerohash's egress IPs are allow-listed | Without this, deliveries time out before reaching your listener. Request the IP ranges from your zerohash contact for each environment. |
| The contact who will receive zerohash's public keys | The signing certificate, and the RSA public key if you are verifying signatures. |
5. What to configure on your side
- Register zerohash in your IdP and issue the
client_id, resource or scopes. - Register zerohash's signing certificate, by direct upload or by reading the JWKS URL.
- Allow-list zerohash's egress IPs for each environment on your webhook listener.
- If you verify the payload signature, load the zerohash RSA public key for that specific environment. Each environment signs with its own key, so a key held for one will not verify traffic from another. Ask your zerohash contact for the key per environment.
- Accept the token on every event. The token is issued per platform, so if you receive events at more than one URL, all of them carry the same token.
6. What to expect in operation
- Deliveries fail closed. If zerohash cannot obtain a valid token, no webhook is sent. zerohash never falls back to an unauthenticated delivery.
- Failed deliveries retry. A delivery that fails, including one blocked by a token problem, is retried on a backoff schedule spanning several minutes before it is set aside. A short outage on your IdP or listener is absorbed without data loss.
- A rejected token is replaced automatically. If your listener returns
401, zerohash discards the cached token and fetches a new one. A burst of rejections produces a single token request, not one per webhook. - Token requests are infrequent. Expect roughly one per token lifetime per environment, not one per event.
7. Troubleshooting
| What you see | Likely cause | What to check |
|---|---|---|
| Your IdP rejects zerohash's token request | A mismatch in client_id, resource or audience, or your IdP cannot match the signing key to the certificate | Re-confirm those values and how the certificate is registered, including thumbprint case or x5t |
Your listener returns 401 and zerohash keeps retrying | The token is valid at the IdP but not accepted by the listener, or the payload signature cannot be verified | Confirm the listener trusts tokens from that IdP client, and that you hold the environment's RSA public key if you verify signatures |
| No webhooks arrive at all, and no requests appear in your logs | zerohash's egress IPs are not allow-listed, or the listener URL on file is wrong | Confirm the allow-list and the URL with your zerohash contact |
Webhooks arrive without an Authorization header | The platform is not yet switched to an OAuth 2.0 method | Raise it with your zerohash contact |
Contact your zerohash representative to begin setup or to change the security method on an existing integration.