Webhooks
Receive your organization's Clav events in your application as they happen, with signed delivery and automatic retries.
What they are
A webhook is an HTTPS address in your application that Clav calls whenever something happens in your organization. The notice arrives when the event happens, so your application does not need to poll the API.
Signed
Every request carries an HMAC-SHA256 signature proving it came from Clav and was not altered.
Retried
If your endpoint is down, the delivery is repeated automatically.
Filterable
Each webhook receives only the events you choose.
Who this guide is for
Organization administrators, and the developers building the integration that receives the events.
Creating a webhook
Open the Webhooks tab
In the organization settings, go to the Webhooks tab. Only administrators can create and remove webhooks.
Click New webhook
Enter the endpoint URL. It must use HTTPS and be reachable from the public internet.
Choose the events
Check the events this endpoint should receive. Leave every box unchecked to receive all events, including ones added in the future.
Store the secret
When you click Create webhook, the platform shows the signing secret. Copy it and keep it in a secrets vault: your server uses it to check signatures.
The secret is shown only once
There is no way to read the secret again. If you lose it, remove the webhook and create another one.
You can have more than one webhook in the same organization. Each event is delivered independently to every webhook subscribed to it.
What reaches your endpoint
Clav sends a POST with a JSON body and these headers:
| Header | Content |
|---|---|
content-type | application/json |
x-clav-event | Event name, for example wallet.verified. |
x-clav-delivery | Delivery identifier. Use it to discard duplicates. |
x-clav-signature | Signature in the format t=<timestamp>,v1=<hex>. |
The body always has the same envelope. What goes in data depends on the event:
{
"id": "65f0a1b2c3d4e5f60718293a-wallet.verified",
"event": "wallet.verified",
"occurredAt": "2026-09-16T12:04:11.000Z",
"data": { }
}The event catalog describes each event’s
data, and the signature verification
page shows how to validate the request.
How to respond
Respond with any 2xx status within 10 seconds. If processing takes longer,
put the event on a queue of your own, respond right away and process it later.
| Your endpoint’s response | What Clav does |
|---|---|
2xx | Marks it delivered. |
408 or 429 | Tries again. |
Other 4xx | Gives up. The error is treated as a final refusal. |
5xx, timeout or connection failure | Tries again. |
3xx | Tries again. Redirects are not followed. |
Retries
Each delivery gets up to 5 attempts. The wait between them starts at 5 seconds and doubles after each failure.
Before every attempt, Clav re-reads the webhook configuration. Removing the webhook or dropping the event from its list takes effect on the next attempt, without waiting for pending ones to finish.
At-least-once delivery
The same event can arrive more than once, for example when your endpoint
processes the request but the response is lost on the way back. In those cases
the value of x-clav-delivery (the same as the body’s id) repeats. Keep the
identifiers you have already processed and ignore repeats.
Arrival order is not guaranteed either. Use occurredAt when order matters.
Endpoint restrictions
For security, the webhook URL must:
- use
https://; - have a fully qualified domain name, not a local name;
- resolve only to public IP addresses.
Internal addresses (localhost, private networks, .local, .internal) are
rejected at creation. The check runs again on every delivery, so a domain that
starts pointing to a private IP stops receiving events.
To test on your machine, use a tunnel with a public HTTPS address.
Frequently asked questions
How do I rotate a webhook's secret?
Create a new webhook with the same URL, update the secret on your server and remove the old one. During the switch your endpoint receives each event twice, once per webhook, each with its own signature.
Can I change an existing webhook's URL?
Not from the platform. Create a webhook with the new URL and remove the old one.
What happens to events when no webhook is configured?
Nothing is queued. The events remain available on the platform and through the API, but they are not resent when a webhook is created later.