Webhooks notify your tools (Power Automate, n8n, Zapier, Make, your information system) as soon as something happens in the CRM: an account created, an opportunity won, dues paid… Your tool no longer needs to poll the API: Illizeo sends it the event, signed, and sends it again if it does not answer. This article explains how to create a subscription, what your tool receives, how to verify the signature and what happens when deliveries fail. It is intended for CRM administrators and for developers who build the receiver.
Before you start #
- The CRM module must be enabled, and your Illizeo subscription must include webhooks: without them, the Webhooks and integrations tile does not appear.
- Permissions in the role matrix, CRM menu, Access level: “CRM settings — View” to see subscriptions and their deliveries; “CRM settings — Create” to create one; “CRM settings — Edit” to edit, enable or disable them, rotate a secret, send a test or retry a delivery; “CRM settings — Delete” to delete one.
- You need an active API token, created in Settings › Manage Illizeo › API Tokens (see Creating and managing API tokens), with read access to the objects to receive (“CRM — accounts”, “CRM — contacts”, “CRM — opportunities”, “CRM — activities”). A subscription only receives what that token can read.
Opening the CRM webhooks #
Open Settings › CRM › Webhooks and integrations. The page lists the CRM subscriptions, with for each one:
- Webhook: its name, receiving address and API token;
- Events: those it listens to;
- Last delivery, or “Never”;
- Status: Active or Inactive, a switch to go from one to the other, and the failure signals: “2 failed retries in a row”, Failing since a date, or Disabled after failures;
- Actions: view the subscription’s page, edit it or delete it.
Below the list, the Integrations card offers the files for Power Automate and n8n (see Connecting the CRM to Power Automate and Connecting the CRM to n8n).

Creating a subscription #
- Click New webhook (or, on an empty list, Create the first webhook).
- Give a Name that identifies the receiving system.
- Enter the Receiving address: an https address on the public internet. An internal network address (127.0.0.1, 10.x.x.x, or a name that resolves to a private address) is refused, both when saving and at every delivery.
- Under API token, choose one of your active tokens: only the tokens you created are offered. The field reminds you: “Only your own tokens are offered: the subscription only receives what this token can read.” Without an active token, the screen invites you to create one.
- Under Events, tick those to receive: only the CRM family is offered.
- Click Create webhook.
- The Signing secret window shows the secret: copy it and give it to the receiving system. It will not be shown again; if lost, rotate it. The Verifying a delivery section gives a code sample. Click I have saved it.

A subscription created by Power Automate from its connector also appears in this list, linked to the connection’s token.
Events #
Each event has a code, which your tool receives in the event field. For it to go to a subscription, the token must carry the read access shown, and the person who created the token must be able to read the record, with their permissions and scope, as on screen.
| Code | On screen | Data besides the object | Token read access |
|---|---|---|---|
crm.account.created, .updated, .archived |
Account created, Account updated, Account archived | the account record (object) |
CRM — accounts |
crm.account.merged |
Accounts merged | the kept record, merged_id (the absorbed account) |
CRM — accounts |
crm.contact.created, .updated |
Contact created, Contact updated | the contact record | CRM — contacts |
crm.contact.attached |
Contact attached to an account | the record, account_id |
CRM — contacts |
crm.opportunity.created |
Opportunity or case created | the record, kind (sale or follow_up) |
CRM — opportunities |
crm.opportunity.stage_changed |
Stage changed | the record, kind, stage_id |
CRM — opportunities |
crm.opportunity.won, .lost |
Opportunity won or case succeeded, Opportunity lost or case abandoned | the record, kind, outcome (the label of the pipeline’s outcome) |
CRM — opportunities |
crm.activity.created |
Activity created | the activity record | CRM — activities |
crm.quote.sent, .accepted |
Quote sent, Quote accepted | opportunity_id, number, status |
CRM — opportunities |
crm.membership.created |
Membership created | club_id, account_id, contact_id, status |
CRM — accounts |
crm.dues.paid, .overdue |
Dues paid, Dues overdue | membership_id, event_id, number, status |
CRM — accounts |
crm.event_registration.created |
Event registration | crm_event_id, contact_id, status, matching |
CRM — contacts |
crm.import.completed |
Import completed | target, created, updated, rejected |
CRM — accounts |
- An event is sent whatever path the action takes: the screen, the API, an import (one event per record created) or a nightly task (“Dues overdue”, for example).
- “Dues paid” is only sent for the payment that settles the dues. “Opportunity won or case succeeded” covers both sales and follow-up pipelines:
kindtells them apart (see Follow-up pipelines: support and business set-up files). - A private activity belonging to someone other than the token’s creator is never sent. A contact from the public form is only named in a registration if the token can read them. An import is only sent to a token whose creator holds “CRM import and export — View”.
What your tool receives #
A POST call, in JSON, to the receiving address. The body carries:
| Field | Content |
|---|---|
id |
The event ID: the same for all its retries; use it to process an event only once. |
event |
The event code. |
occurred_at |
The date and time of the event (ISO 8601). |
tenant |
Your organisation’s identifier. |
data |
object_type and object_id, then, for an account, contact, opportunity or activity, object: the record in its API v1 form, read with the token’s permissions; for the others, the IDs and statuses in the table above. |
The headers carry Illizeo-Event (the code), Illizeo-Event-Id (the event ID), Illizeo-Delivery (the delivery number) and Illizeo-Signature. An object the token cannot read is never sent, not even its ID.

Verifying the signature #
The Illizeo-Signature header has the form t=<timestamp>,v1=<signature>. The signature is an HMAC-SHA256, in hexadecimal, computed with your secret over <t>.<raw body>.
- Read
tandv1from the header. - Recompute the HMAC-SHA256 of the timestamp, a full stop and the body exactly as received, byte for byte, before parsing the JSON.
- Compare your result with
v1using a constant-time comparison. If they differ, reject the call. - Refuse a timestamp that is too old (five minutes recommended), so that a recorded call cannot be replayed.
- Ignore an
idalready processed, then answer quickly with a 2xx code and process the event afterwards.
A subscription’s page #
Click a subscription to open its page:
- Send a test immediately sends a signed
pingevent, never retried, which does not count towards your usage; - Rotate secret creates a new one, shown only once: the old one stops working;
- Edit changes the name, address or events; only the person who created the subscription can change its token, for one of their own;
- the Delivered (30 d), Retrying, Failed (30 d) and Pending counters, and the Failed retries in a row;
- the Deliveries, which can be filtered by status (Delivered, Retrying, Failed, Pending): Date, Event, Status, Attempts, Response (HTTP code and duration) and Next retry. Show payload shows what was sent; Retry now sends the delivery again, once.

Failures, retries and suspension #
- A delivery succeeds when your receiver answers with a 2xx code within ten seconds. Any other answer, a redirect (never followed) or no answer is a failure.
- A failure is retried automatically after 1 min, 5 min, 30 min, 2 h, then 12 h: six attempts in all. After that, the delivery is Failed and only goes again by hand, with Retry now, for a single attempt.
- After five failed retries in a row, across all deliveries, or three days of continuous failures, the subscription is suspended: it becomes Inactive, its pending retries stop, and its creator is notified, in the bell and by email, if they can still edit the CRM settings.
- To resume it: fix the receiver, click Send a test, then enable it again from the list. The failure count only goes back to zero with the first real delivery that succeeds: until then, a new failure suspends the subscription again.
- The delivery log is kept for 30 days. Deleting a subscription also deletes its log.

Good to know #
- An action that is undone (an error that cancels the save, an import simulation) sends nothing: the delivery only goes once the action is written.
- Demonstration data never triggers a delivery, and nothing is sent when the CRM module is switched off.
- Each successful delivery counts once towards your subscription’s API usage, retries included. If the usage cap is reached, deliveries stop, without retries. The test does not count.
- The API token list only offers your own active tokens: a subscription receives what the person who created its token can read. A subscription linked to someone else’s token receives nothing.
- Revoking a subscription’s token, or letting it expire, stops it from receiving anything: choose another one with Edit.
- Creating, editing and deleting a subscription are logged; the secret’s value never is.
FAQ #
The subscription is active, but nothing arrives. #
Check that the token is active, that it carries read access to the object (“CRM — opportunities” for a quote, for example) and that its creator can read the record: a sales rep whose scope is “Mine” only receives their own records. Also check the subscription’s page: a Retrying or Failed delivery shows your receiver’s answer.
My tool receives the same event twice. #
A retry can arrive if your receiver answered too late or with an error even though it had processed the call. Keep the id values already processed and ignore duplicates.
