Skip to main content

Inbound Webhook

External systems write data into Soln through the inbound webhook endpoint: the request body is the flow input, and the flow writes it into the local form according to the canvas mappings.

Only inbound + webhook flows expose this address. Query data and message push flows have their own endpoints, see Query Data and Message Push.

How To Request​

ItemValue
MethodPOST
URL<runtime-origin>/api/open-link/inbound/webhooks/<flowCode>
Content typeMust start with application/json; otherwise the request fails with OPEN_LINK_CONTENT_TYPE_INVALID
Body sizeAt most 10 MiB; a larger body fails with OPEN_LINK_PAYLOAD_TOO_LARGE
AuthenticationSend the headers of the inbound authentication profile of that OpenLink (shared token, Bearer token, or signature), and pass the whitelist check first
Optional headersX-Idempotency-Key prevents duplicate writes; X-Request-Id is recorded as the external request ID

<runtime-origin> is the workspace runtime address, the same address you use to open Soln in the browser, and <flowCode> is the flow code such as open_link_flow_0505058add3a. The start node of the flow shows the complete webhook URL, and Request example in the design canvas produces a call example you can copy.

Request Body​

The body must be a JSON object. How fields are passed depends on whether the canvas has a transform node.

With A Transform Node: Send External Field Codes​

Keys are external field codes and values are the field values:

{
"order_no": "SO-2026-0001",
"amount": 128.5,
"customer": { "code": "C-1001" },
"ordered_at": "2026-09-18T10:00:00.000Z"
}
  • Field codes come from the external form field definitions
  • Foreign key and relation fields pass the referenced field, such as customer.code; nested objects are read by path
  • Fields that no mapping uses are ignored, and extra fields do not affect execution

Without A Transform Node: Send Local Form Field API Names​

When the canvas has a target node but no transform node, Soln writes the request body directly as local form data, so keys are local form field API names:

{
"order_no": "SO-2026-0001",
"amount": 128.5
}

Child Table Data​

Child table data goes into the input.childTables array:

{
"order_no": "SO-2026-0001",
"input": {
"childTables": [
{
"externalObjectCode": "order_lines",
"rows": [
{ "line_no": "1", "sku": "A-100", "qty": 2 },
{ "line_no": "2", "sku": "A-200", "qty": 1 }
]
}
]
}
}

Each child table is matched to the child table pairs configured on the canvas by externalObjectCode (externalObjectId also works), not by array position, and rows that match no pair are not written.

Optional Envelope And Callback​

  • When the body only contains payload (and optionally callback), Soln uses the content of payload as input data
  • callback is an asynchronous callback control object: { "url": "https://...", "headers": { ... } }, used to call back the external system after the flow finishes
  • A callbackId in the body is used as the idempotency key, equivalent to X-Idempotency-Key
  • The field contract for workflow callback flows is in Workflow Integration

Response​

SituationResponse
AcceptedHTTP 202 with accepted, duplicate, logId, traceId, status, flowCode, callbackRequested, and statusQueryUrl
Duplicate submissionSubmitting the same idempotency key again returns duplicate: true with the existing logId and does not write again
FailureA non-2xx response whose body is { code, requestId, message?, detail? }

Acceptance only means the request entered the queue. Read the execution result with a GET request to statusQueryUrl:

curl --request GET \
'https://runtime.example.com/api/open-link/inbound/webhooks/executions/<logId>?traceId=<traceId>'

The result contains status, completed, localRecordId, durationMs, errorCode, errorMessage, and the callback delivery state.

Common Errors​

errorCodeMeaning
OPEN_LINK_CONTENT_TYPE_INVALIDThe content type is not JSON
OPEN_LINK_JSON_VALUE_INVALIDThe body is not valid JSON
OPEN_LINK_PAYLOAD_TOO_LARGEThe body is larger than 10 MiB
OPEN_LINK_EXECUTION_PAYLOAD_INVALIDThe body is not a JSON object
OPEN_LINK_WEBHOOK_SOURCE_DENIEDThe source did not pass the whitelist
OPEN_LINK_WEBHOOK_AUTH_INVALIDInbound credential verification failed
OPEN_LINK_WEBHOOK_TIMESTAMP_EXPIREDThe signature timestamp is outside the allowed clock window
OPEN_LINK_WEBHOOK_CALLBACK_INVALIDThe callback control object is invalid
OPEN_LINK_FLOW_DEFINITION_NOT_PUBLISHEDThe flow has no published version to run
OPEN_LINK_IDEMPOTENCY_KEY_CONFLICTThe same idempotency key was used for another flow
OPEN_LINK_INBOUND_RATE_LIMIT_EXCEEDEDThe per-minute request limit was exceeded
OPEN_LINK_INBOUND_CONCURRENCY_LIMIT_EXCEEDEDThe maximum concurrent request limit was exceeded

Call Examples​

Both examples use signature authentication: the signature covers METHOD\npath\ntimestamp\nraw body, the timestamp must be the current time, and the signature must be recomputed for the real body. The value in the examples only shows the format.

Main Table Only​

curl --request POST \
'https://runtime.example.com/api/open-link/inbound/webhooks/open_link_flow_0505058add3a' \
--header 'Content-Type: application/json' \
--header 'X-App-Id: app_Aqg9LRZahMDuMRS9' \
--header 'X-OpenLink-Timestamp: 1789712190157' \
--header 'X-OpenLink-Signature: <recompute for the real body>' \
--data '{"order_no":"SO-2026-0001","amount":128.5,"customer":{"code":"C-1001"}}'

Main Table With Child Tables​

curl --request POST \
'https://runtime.example.com/api/open-link/inbound/webhooks/open_link_flow_0505058add3a' \
--header 'Content-Type: application/json' \
--header 'X-App-Id: app_Aqg9LRZahMDuMRS9' \
--header 'X-OpenLink-Timestamp: 1789712190157' \
--header 'X-OpenLink-Signature: <recompute for the real body>' \
--data '{
"order_no": "SO-2026-0001",
"amount": 128.5,
"customer": { "code": "C-1001" },
"input": {
"childTables": [
{
"externalObjectCode": "order_lines",
"rows": [
{ "line_no": "1", "sku": "A-100", "qty": 2 },
{ "line_no": "2", "sku": "A-200", "qty": 1 }
]
}
]
}
}'

The externalObjectCode of a child table must match the external object code selected in the child table pair on the canvas, and the main fields and input.childTables are submitted in the same body. When the canvas has no transform node, use local form field API names for the main fields instead.

Both examples use signature authentication. For shared token or Bearer token authentication, replace the three signature headers with the matching header, as described in Inbound Auth.