Webhooks
Required Access Level
Admin or Super Admin
What are Webhooks for?
Webhooks let Flowi Agentic notify external systems automatically when events happen on the platform, without the external system having to poll for them.
Typical uses:
- Notify an ERP when a purchase instance is approved
- Push data to an external dashboard when a task is completed
- Trigger automation in another system when a process ends
How they work
When an event happens in Flowi Agentic, the system sends an HTTP POST request to the URL registered on the webhook, with the event data in the body (JSON).
Registering a webhook
- Go to Integration → Webhooks
- Click New Webhook
- Fill in:
- Name — how you identify the webhook
- URL — the external endpoint that will receive the notifications
- Events — which event types fire this webhook
- Secret — the key used for HMAC validation (optional, but recommended)
- Click Save
Where a webhook may send
Each tenant declares the allowed destinations for its webhooks, under Integration → Webhooks → Allowed destinations — one host per line:
erp.customer.com
*.partner.com*.partner.com reaches api.partner.com and does not reach partner.com. The port is ignored in the comparison. It is the same format as the destination list of AI Agents — the two halves of the same control.
Why this exists: before it, a webhook sent the tenant's process events to whatever URL an administrator had typed, and nothing answered "if this webhook fires, where does the data go" before it fired. The list answers that, and the screen shows, for every webhook, its effective host and its state:
| State | What it means |
|---|---|
| Declared destination | the host is on the list — it will be delivered |
| No list declared | nothing bounds the destination; the installation allows it, but nobody declared anything |
| Outside the destination list | the host is not on the list — it will not be delivered |
| No destination declared | the installation requires a list and this tenant has none |
A destination that is not on the list is refused on save, with the host in the error text. If the list changes after the webhook was registered, the delivery is refused at send time and recorded as BLOCKED in the history, with the reason — it is not a network failure, and it is not retried.
The listed state is computed from the host written in the URL, and from nothing else. The check that the address is not internal happens at two other moments — when the webhook is saved and on every send — and is not part of that state: a host that started resolving to an internal address after registration is still shown as Declared destination and is refused at delivery time.
An internal address is never a destination
localhost, 127.0.0.1, the private ranges (10., 172.16-31., 192.168.), link-local and the cloud metadata endpoints (169.254.169.254) are refused even if you write them on the list. The list widens external reach; it does not revoke that protection.
New installation: WEBHOOKS_EGRESS_DEFAULT_POLICY=deny
With allow (the default, for compatibility) a tenant with no list delivers to any external address. With deny, a tenant with no list delivers nothing, and whoever integrates says where. Twin of AI_HTTP_TOOL_DEFAULT_POLICY.
What happened to webhooks that already existed
The upgrade filled each tenant's list with the hosts of the webhooks it already had. Nothing that was delivering stopped delivering, and the list was born true: it is the set of destinations that were actually in use. Registering a new destination became two steps — declare the host, then register the webhook.
HMAC validation
If you configure a secret, Flowi Agentic signs every payload with HMAC-SHA256 and sends the signature in the header:
X-FlowIa-Signature: sha256=<signature>On the receiving system, validate the signature with the same secret: it proves the body came from here and was not altered on the way.
What the signature does not say is when the request was made. There is no timestamp and no sequence number in the headers, and a retry re-sends the same body with the same signature — the same event can arrive up to three times, all of them valid. Treat every delivery as idempotent, using the event's own data to recognise what has already been processed.
Available events
| Event | Fired when |
|---|---|
instance.started | A process instance is started |
instance.completed | An instance completes |
instance.failed | An instance fails |
task.created | A new task is created |
task.completed | A task is completed |
task.overdue | Not implemented — see the warning below |
task.overdue is not fired
A due date passing is not an engine event: nothing happens at the moment the date goes by. Delivering that event would require a periodic sweep of open tasks, and the platform runs no such sweep. If you register a webhook only for it, you will receive nothing.
When delivery happens
The event records the delivery as pending and a background job sends it — within a minute, not at the instant of the event. The call to your server is deliberately kept outside the process transaction: were it made inside, an instance completing would hold database resources for the whole response time of your endpoint, timeout included.
And if the process rolls its transaction back, the delivery rolls back with it. An instance that never started does not announce that it started.
Retry
If a delivery fails (the external server returns an error or does not respond), Flowi Agentic re-queues it and tries again every minute, up to three attempts. After that the delivery is marked FAILED and is not tried again. The history is kept on each webhook.
There is no exponential backoff — the interval is fixed.
Monitoring deliveries
In the webhook list, click one to see the 50 most recent deliveries of that webhook: the event, the status (SUCCESS, PENDING, RETRYING, FAILED, BLOCKED), the HTTP code your server returned, the number of attempts and the date. The body that was sent is not shown on that screen.