Webhooks
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:
What a delivery looks like
A single POST, with a JSON body, to the URL you registered.
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.
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.
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.
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.
The event type: ended.
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.
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.
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.
Payload class discriminator — always this value for an execution event. If the same endpoint also receives flow events, branch on it first.
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.
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.
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:
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.