This article is for developers who receive Illizeo webhooks: the shape of the request, its headers, the content of the message, signature verification, the expected response and how to handle duplicates. The subscription itself is created in the application (see Creating and managing a webhook).
Before you start #
- Expose a public
https://address. http addresses, and those leading to an internal network, are refused when saving and at every delivery. - Get the webhook’s signing secret from the administrator. It starts with
whsec_and is shown only once, on creation or rotation: keep it like a password.
The request #
Each delivery is a POST request whose body is a JSON object (Content-Type: application/json). It carries these headers:
| Header | Content |
|---|---|
Illizeo-Event |
The event code, for example absence.approved. |
Illizeo-Event-Id |
The event identifier, the same for every attempt and for every webhook listening to it. |
Illizeo-Delivery |
The identifier of the delivery to this webhook, the same from one attempt to the next. |
Illizeo-Signature |
The signature, in the form t=<unix timestamp>,v1=<hexadecimal signature>. |
User-Agent |
Illizeo-Webhooks/1.0 |
The message #
The body always contains five fields:
id: the event identifier (repeated inIllizeo-Event-Id);event: the event code;occurred_at: the date and time of the fact, in ISO 8601 format;tenant: the company account (its subdomain);data: the identifiers and states specific to the event.
Example: {"id":"…","event":"absence.approved","occurred_at":"…","tenant":"…","data":{"absence_id":…,"employee_id":…,"absence_type_id":…,"from":"…","to":"…","status":"…"}}
The message carries identifiers, dates, states and, for some events, quantities (hours, for example). It never contains a person’s name, a social security number, a salary amount or an attachment. For details, read the resource back through the API with a token (see Public API: developer guide). The data fields of each event are listed in the Webhook event catalogue.

Verifying the signature #
- Read the raw request body, before any JSON decoding: the signature covers the bytes received.
- Split the
Illizeo-Signatureheader: the value aftert=is the timestamp, the one afterv1=the signature. - Compute an HMAC-SHA256 with the webhook secret as key, over the string made of the timestamp, a dot and the raw body:
<t>.<raw body>. Express the result in hexadecimal. - Compare it with
v1using a constant-time comparison (for examplecrypto.timingSafeEqualin Node.js,hash_equalsin PHP,hmac.compare_digestin Python). - Reject the message if the timestamp is more than 5 minutes away from your clock: this blocks the replay of an intercepted message.
The window that shows the secret gives a Node.js example, under Verifying a delivery. Each attempt is signed when it is sent, with the secret in force: after a secret rotation, every delivery, retries included, is signed with the new one. There is no period during which both secrets are valid: coordinate the rotation with the administrator.

Responding #
- Answer with a 2xx code within 10 seconds. Any other code, no answer, or a redirect (which is not followed) counts as a failure.
- Answer first, process afterwards: queue the message on your side, then read the resource back through the API if needed.
- After a failure, Illizeo retries the delivery 1 minute, 5 minutes, 30 minutes, 2 hours and then 12 hours later, six attempts in all. A webhook that fails continuously for three days is deactivated.
Duplicates and order of arrival #
- The same event may arrive more than once, for example if your response took longer than 10 seconds while the message was processed. Keep the
Illizeo-Event-Idvalues already processed and ignore a duplicate. - Retries can make an event arrive after a more recent one. Rely on
occurred_at, or read the current state of the resource through the API.
The test message #
The Send a test button on the webhook page sends a ping event, signed like the others, whose data contains endpoint_id and a short message. Answer it with a 2xx code like any other message. A test is never retried.
Good to know #
- The API documentation, in the application, lists every event and the fields of its
data, in its Webhook events card. - The event families of a module (Scheduling, Annualised working time, Budget, BDESE, Swiss payroll, Flex Office) are only emitted if the module is enabled in the space.
