Webhooks
A webhook tells your system the moment something happens in Clorvia — an invoice is created, a payment is recorded, a customer is updated — by sending a signed POST request to a URL you choose. This replaces having to poll the API on a timer, so your integrations stay in sync and use far fewer requests.
Register a webhook
- Go to Settings → APIs & Webhooks.
- Under Webhooks, click Create webhook.
- Enter the URL Clorvia should POST to (must be HTTPS and publicly reachable).
- Choose the events you want (see below).
- Save. A signing secret is generated — you’ll use it to verify deliveries.
Choose events
Events are named object.action, for example:
| Pattern | Fires when… |
|---|---|
invoice.created | a new invoice is created |
invoice.updated | an invoice changes (e.g. marked paid) |
party.created | a new customer or supplier is added |
payment.created | a payment is recorded |
You can use wildcards:
*.created— anything createdinvoice.*— any change to invoices*— every change
What Clorvia sends
A POST with a JSON body like:
{
"eventName": "invoice.updated",
"objectNameSingular": "invoice",
"action": "updated",
"recordId": "…",
"updatedFields": ["status"],
"record": { "id": "…", "invoiceNumber": "INV-1042", "status": "Paid", "totalAmount": 11800 },
"before": { "status": "Unpaid" },
"after": { "status": "Paid" },
"eventDate": "2026-06-04T10:15:00.000Z"
}Headers on every delivery:
| Header | Meaning |
|---|---|
X-Clorvia-Event | the event name (e.g. invoice.updated) |
X-Clorvia-Timestamp | when it was sent (Unix seconds) |
X-Clorvia-Signature | HMAC‑SHA256 signature (see below) |
X-Clorvia-Delivery | a unique id for this delivery |
Verify the signature
Always verify that a delivery really came from Clorvia before trusting it. The
signature is HMAC‑SHA256 of timestamp + "." + rawBody, using your webhook’s
signing secret, hex‑encoded.
const crypto = require('crypto')
function isValid(req, secret) {
const timestamp = req.headers['x-clorvia-timestamp']
const signature = req.headers['x-clorvia-signature']
const expected = crypto
.createHmac('sha256', secret)
.update(timestamp + '.' + req.rawBody) // the RAW request body, not re-serialized
.digest('hex')
// constant-time compare
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))
}Also reject deliveries whose X-Clorvia-Timestamp is more than a few minutes old
(replay protection).
Retries & reliability
- If your endpoint doesn’t return a
2xx, Clorvia retries with backoff. - Make your handler idempotent — use
X-Clorvia-Deliveryto ignore a delivery you’ve already processed. - Respond quickly (do heavy work asynchronously); return
200as soon as you’ve safely received the event. - You can see recent delivery attempts for each webhook in Settings → APIs & Webhooks.
Manage & remove
Edit a webhook’s URL, events, or secret any time, or delete it to stop deliveries. Deleting is immediate.