Skip to navigation

Webhooks

Let INFONITE tell your backend what happened, instead of asking it over and over
View as Markdown

An execution takes as long as an institution takes. Polling for the end — the synchronous way — means asking a question whose answer is “not yet” almost every time, for every execution you have in flight.

A webhook is the asynchronous way, and it inverts that: you register an HTTPS URL, and INFONITE sends your backend an HTTP POST the moment something happens, server to server. You do nothing until there is something to do.

These events carry no data. That is the design.

An execution event tells you that something happened — it never carries extracted records. The data is read back over an authenticated call, which is what keeps somebody’s financial life off a public endpoint. If you are looking for the encrypted-payload delivery, that is a flow feature, and it exists there because a flow session has a key you supplied.

Setting one up is the same for every product: an endpoint (the destination) and a rule (this event goes there), configured once per application in the Console. Receiving Webhooks is the whole procedure — including the authentication header, the URL rules and the test delivery. This page is about what this product sends you.

Answer 2xx the moment the payload reaches you, whatever your own processing does with it afterwards: any other status is recorded as a failed delivery even though the event arrived. Answering a delivery has the handler to copy.


The four events

Every one carries the same envelope, so a single handler can serve all four. You subscribe to as many or as few as you need.

The name in each card — started, action_required, auth_ended, ended — is the value that arrives in the event field of the payload, and the one a webhook rule is bound to.

Which ones you actually need

Two of the four earn their place in most integrations, and the other two are shortcuts. It is worth deciding on purpose rather than subscribing to everything:

EventWhy you would want it
endedThe one you need. It is the only event that says the results are there, the only one delivered for an execution that never got to run, and the only one we re-deliver if your endpoint was down.
action_requiredThe one you cannot replace with patience. The execution expires unless you answer, on the institution’s timetable. Without it you are polling every few seconds for every run in flight.
auth_endedA shortcut to the verdict on the credentials, seconds into a run that may take minutes — and, with tokenization, the proof that a stored access still works: AUTH_OK is also the moment a ticket becomes exchangeable, because the credentials behind it are stored only when the login succeeds. Redundant if you can wait for ended, where the same reason arrives.
startedA clock, not an instruction. It separates queue time from working time, which is what you need when somebody asks why a case is slow.

What a delivery looks like

A single POST, with a JSON body, to the URL you registered.

A delivery, as your server sees it
POST /webhooks/infonite?case=A-1029 HTTP/1.1
Host: api.yourcompany.com
Content-Type: application/json
Authorization: Bearer <the secret you gave us>
{
"event_class": "ExecutionEvent",
"app_id": "4aa3dcbab3287e2385bb5cec",
"customer_id": "my-customer-1",
"execution_id": "6aa3d8b418d1c5dc9a8e3d36",
"session_id": "5aa3dca503e37e6809539a58",
"external_execution_id": "case-A-1029",
"locking_hash": "v1.36GHPwfDK-UUZGG4fb1jtg",
"producer": "engine",
"event": "ended",
"date": "2026-09-12T10:17:31+00:00",
"customer_available": true,
"status_reason": "COMPLETED",
"status_message": null
}

The execution is over and nothing else will change on it. status_reason says how it ended — COMPLETED, PARTIAL when some features answered and others did not, or the reason it could not. This is the event that closes your case: read the results now.

app_idstringRequiredformat: "object-id"

The application this execution was launched with — the one your secret belongs to. Worth keeping when your product uses more than one, a sandbox and a production app being the usual case: every record and every event we send carries it.

customer_idstringRequired

The customer_id you supplied when the execution was initialised, returned as you sent it — so an answer can be routed to the right case with no lookup on your side.

execution_idstringRequiredformat: "object-id"

The execution this belongs to — the value you poll for the state and address every results endpoint with. Always present here: an event exists because an execution does.

event"ended"Required

The event type: ended.

datestringRequiredformat: "datetime"

When the event was raised, in UTC. Deliveries can arrive out of order — a retry is delivered after whatever came next — so order your own records by this, not by arrival.

customer_availablebooleanRequired

Whether the execution was started as one a person can answer (customer_interaction_available). When false, a challenge from the source cannot be solved and the execution ends instead of waiting.

status_reasonenumRequired

The precise reason for the state at the moment of the event — one of the execution reasons, or a feature's own when producer names a feature. Branch on this and not on the message: it is a stable code. Every reason by family.

session_idstring or nullOptionalformat: "object-id"
external_execution_idstring or nullOptional
locking_hashstring or nullOptional
event_class"ExecutionEvent"OptionalDefaults to ExecutionEvent

Payload class discriminator — always this value for an execution event. If the same endpoint also receives flow events, branch on it first.

producer"engine" or enumOptionalDefaults to engine

Who raised it: engine for the execution itself — the login, typically — or the feature's own code when a single feature is what needs something. An action_required from the accounts reader says accounts_read, so you know what is being asked for before reading the form.

status_messagestring or nullOptional
datamap from strings to any or nullOptional

customer_id and external_execution_id are yours. They are the strings you supplied when you started the execution, so a handler can route the event straight to the right case without a lookup table.

event_class is the discriminator to branch on first if the same endpoint also receives flow events: ExecutionEvent is a direct execution, anything else is not.

The destination URL

The rules a destination has to satisfy — HTTPS, a public host, no query string of its own — are the same for every product and live in Receiving Webhooks. What is specific here is what the platform writes into the path: any of these is replaced with the event’s own value before the call is made.

VariableBecomes
{execution_id}the execution this event belongs to
{external_execution_id}your own reference, if you attached one when you started it
{session_id}the session the execution belongs to
{customer_id}your identifier for the credentials’ owner
{app_id}your application
{locking_hash}the fingerprint of the fixed part of the credentials
{producer}engine, or the feature’s code when one feature raised the event
{event}the event name, e.g. ended
{status_reason}the precise reason at the time of the event
{customer_available}whether the execution can pause for a person

So https://api.yourcompany.com/webhooks/infonite/{external_execution_id} arrives as …/webhooks/infonite/case-A-1029, and your router can pick your own case out of the path with no lookup at all.

Sending your own context along

hooks_extra_data is a flat dictionary you set per execution, when you start it. Every key and value in it is appended to the delivery as query parameters, and the same template variables work inside them:

At execution start
{
"engine_reference": "DEMOBANKXXXXFIN100ES9999-mobile",
"customer_id": "my-customer-1",
"hooks_extra_data": {
"case": "A-1029",
"stage": "underwriting",
"event": "{event}"
}
}

Your endpoint then receives ?case=A-1029&stage=underwriting&event=ended. It is the natural place for the correlation id of whatever process launched the execution.

hooks_extra_data is not a place for secrets. Query strings end up in access logs, proxies and browser-adjacent tooling. Authentication belongs in the header.


Configuring your webhooks

Endpoints and rules are per APPLICATION, and they are the same two pieces for every product on the platform: Receiving Webhooks is where they are explained, with the Console screens and the test delivery.

Engine rules fire on direct executions only. When an engine runs inside a flow, that flow’s rules deliver the events instead — otherwise one journey would notify you twice, from two vocabularies.