Action Bindings
The Action Bindings screen is where the regulatory seller actions — the buttons that appear inside the invoice detail modal depending on the invoice status — are wired to a sequence of connector calls. Resend to PA on a 9904 invoice has to call the PA again, Payment Received on a 204 may need to update the source ERP and notify the buyer, Credit Note on a 206 may run a SQL query that flags the rejected line. The list of actions is fixed by the French e-invoicing regulation; what runs when the user clicks them is configured here.
The page is on the same footing as Notification Rules: both surfaces hold a multi-call list of connector calls with the same Description / Connector / Target / Parameters / Stop on failure shape and the same {call.N.fieldName} response-chaining contract.
The page applies regardless of source system — JD Edwards, SAP, NetSuite or a custom ERP. The connector dropdown lists every API and SQL connector merged with · API / · SQL suffixes, so the kind is visible at a glance.
Action bindings used to hold a single call per action. Since 2026.05.7 each binding holds a list of connector calls, with a per-call Stop on failure flag, response chaining via {call.N.fieldName} placeholders, and SQL-connector support next to api-connector. Existing single-call bindings keep working — the legacy flat keys are read into a one-entry call list on load and rewritten into the canonical action.N.call.M.* shape on the next save. See the 2026.05.7 release notes for the full list.
Opening the editor
- Sidebar → Management → Action Bindings.
- The page opens on the default
e-invoicingtemplate. Use the Scope selector to switch to a per-company override (e-invoicing-{kco}) — the binding list reloads from the selected template; the Save button writes back to the same scope.
At a glance
Scope selector
The Scope selector at the top of the page picks which template the bindings are saved against:
| Scope | Template | Effect |
|---|---|---|
| Default (e-invoicing) | e-invoicing | The fallback bindings every company inherits. Edit here when the same call sequence applies platform-wide. |
Company 00070 (e-invoicing-00070) | e-invoicing-00070 | Per-company override. Listed in the dropdown for every e-invoicing-{kco} template that exists. The runtime resolver looks up the per-company template first and falls back to the default — a binding present in both is overridden by the per-company one. |
The list of available company overrides is read from the templates catalogue: any template named e-invoicing-{kco} shows up as Company {kco}. To create one, copy the default e-invoicing template under the new name from Settings; this page then loads the new scope when picked.
The Save button writes back to the selected scope only — switching scope before saving discards unsaved edits to the previous one. The Unsaved changes badge appears next to the scope selector when the in-memory state diverges from what is on disk.
The action list
Each binding is rendered as a card. The card carries an Action dropdown at the top (locked to the seven regulatory IDs below), a list of connector calls in collapsible sub-cards, and a per-binding 🗑 delete button.
Regulatory action IDs
The dropdown lists seven IDs — the same buttons the invoice detail modal renders status-aware in the Actions tab. An action without a binding shows as disabled in the modal.
| Action ID | Label | Triggered on status |
|---|---|---|
paymentReceived | Payment Received | 205 (the regulatory status for Encaissement constaté). |
creditNote | Credit Note | 206 / 207 (rejected by the buyer, reissue as a credit note). |
correctedInvoice | Corrected Invoice | 206 / 207 (reissue with corrections instead of a credit note). |
sendCompleted | Send Completed | 208 (suspended-by-buyer, mark the in-progress flow as resolved). |
cancelAccounting | Cancel Accounting | 210 / 213 (litigation, reverse the accounting entry). |
newInvoice | New Invoice | 213 (litigation closed, issue a fresh invoice for the same delivery). |
resendPA | Resend to PA | 9904 / 9907 (PA technical rejection, resubmit the same UBL). |
Each ID can be bound at most once per scope. The dropdown filters out IDs that are already bound, so accidental duplicates are not possible. Removing a binding frees the ID for reuse.
Calls list
Below the Action ID, the binding holds a list of connector calls rendered as collapsible cards. The card header shows the call index (#1, #2, …) and either the Description field or connector · target when the description is empty.
| Field | Description |
|---|---|
| Description | Free-form short label for this call (e.g. Update CRM customer status). Rendered as the collapsed-card header so a binding with several calls reads as a punch-list at a glance. Persisted only as UI metadata. |
| Connector | Dropdown listing every API and SQL connector merged with · API / · SQL suffixes so the kind is visible. |
| Target | Dropdown loaded from api.connectors.listEndpoints(connector) for an API connector, or api.sqlConnectors.listQueries(connector) for a SQL connector. Disabled until a connector is picked. |
| Parameters | Pre-populated from the target's declared parameters, one labelled row per parameter. Values can mix free text and {{placeholder}} tokens. When the target declares no parameters, a free-form Params row replaces the per-row layout. |
| On failure | Single checkbox. When ticked, a failure on this call halts the chain and skips every remaining call. Default off — the chain continues by default, the same continue-on-error behaviour as notification rules. |
+ Add Call at the bottom of each binding appends a new call. Newly-added calls auto-expand for editing; loading a binding from disk collapses every call so the page reads as a quick overview.
Placeholders — invoice values
Parameter values support {{fieldName}} placeholders that are resolved at click time from the row the user is acting on. Available fields:
| Placeholder | Source |
|---|---|
{{fedoc}} | Document number (UHDOC / UHFEDOC). |
{{fedct}} | Document type (UHDCT). |
{{kco}} | Company code (UHKCO). |
{{ublNumber}} | UBL identifier of the invoice (UHK74UBLNB). |
{{statusCode}} | Current status code (UHK74RSCD). |
{{customerName}} | Customer name (UHALPH). |
{{totalHT}} | Total amount before VAT. |
{{totalTTC}} | Total amount including VAT. |
{{currency}} | ISO 4217 currency code. |
{{amountDue}} | Outstanding balance. |
{{invoiceType}} | Document UBL invoice type (380, 381, …). |
{{orderRef}} | Customer purchase-order reference. |
{{contractRef}} | Customer contract reference. |
Free text and placeholders can mix — Y;reason={{statusCode}} is a valid value.
Response chaining
When the binding holds two or more calls, every call's outputs are folded back into the dispatch context under call.N.* keys, and subsequent calls reference them with {call.N.fieldName} placeholders in their parameter values.
| Field | Source — API connector call | Source — SQL connector call |
|---|---|---|
call.N.success | true when HTTP status < 400. | true when the statement ran without error. |
call.N.statusCode | HTTP status code returned by the endpoint. | — |
call.N.statementType | — | SELECT / INSERT / UPDATE / DELETE / MERGE. |
call.N.rowCount | — | For SELECT — number of rows returned. |
call.N.updateCount | — | For non-SELECT — number of rows affected. |
call.N.error | Error message when success is false. | Same. |
call.N.<name> | Every endpoint.N.response.<name> mapping the connector defines. | Every column of the first row of the result, by name. |
Example: a Resend to PA binding that first re-submits the invoice to the PA via an API call, then writes an audit row in the source ERP via a SQL call, sets the SQL parameter submission_uuid to {call.1.uuid} (the uuid field of the API connector's response mapping). If the API call fails and Stop on failure is ticked, the SQL call never runs and the audit trail records STOP · 1 remaining call(s) skipped.
How a binding fires
When the user clicks an action button in the invoice detail modal:
- The frontend resolves the per-company template first (
e-invoicing-{kco}) and falls back toe-invoicingif no override exists. - The matching
action.Nblock on that template is read; if no binding is found, the modal disables the button (the click never reaches step 3). - The bound calls fire in declaration order. Each call goes through
executeConnectorAction, which routes to/api/connectors/{name}/call/{endpoint}for an API connector or/api/sql-connectors/{name}/call/{query}for a SQL connector. - Outputs are folded into
call.N.*. The next call's{{placeholder}}and{call.N.…}values are resolved against the merged context. - A
FAILon a call with Stop on failure halts the chain and reportsSTOP · N remaining call(s) skipped. Otherwise the chain continues with the next call. - The aggregate result is surfaced in a banner inside the invoice modal — Action complete · 2 of 2 calls succeeded on success, the failure reason on error.
The dispatch is synchronous; the modal stays open until every call has returned. Long-running SQL queries are bounded by the SQL connector's Query timeout setting; long-running HTTP calls are bounded by the API connector's Default timeout.
Tips & best practices
- Start at the default scope. Configure
e-invoicingfirst, override per company only when one customer needs a different connector or extra parameter. The fallback resolver keeps the picture readable. - One purpose per binding. Resend to PA should not also update the ERP and notify finance — split into separate calls inside the same binding instead. The Description field on each call makes the chain readable from the collapsed view.
- Use Stop on failure on the upstream call only. A typical chain is
submit to PA · audit in ERP · notify finance. Tick Stop on failure on the first call only — if the PA submission fails, the audit row is meaningless. Failures on the audit step or the notification step are not reasons to skip the rest. - Reference earlier calls with
{call.N.fieldName}. A SQL audit row that needs the PA submission UUID grabs it from{call.1.uuid}rather than re-querying the PA. The chain stays consistent on retries. - Test with the same scope you will use. A binding saved against
e-invoicingbut tested against an invoice on company00070runs the per-company override if one exists — switch scope first when validating. - Preserve
{{placeholder}}exactness. The placeholder names listed above are the only ones the runtime substitutes; a typo ({{customer}}instead of{{customerName}}) is left as the literal string and shipped to the connector as-is. The Test panel on the connector pages catches the mismatch. - Disable a binding by clearing it. There is no enabled / disabled flag — to suspend an action, remove its binding (the button greys out in the modal) or remove the offending call (the rest of the chain still runs).