Preparing Integration Configurations
Integration configurations define how external requests are processed end to end when they interact with Siebel CRM. They provide a declarative way to compose and govern integrations by combining the following capabilities:
- Orchestration through DSL-based step sequencing and control flow.
- Data transformation mappings.
- Resilience features, such as retries and error handling.
- Event-driven publish and subscribe patterns.
Integration configurations help you to:
- Standardize how integrations run.
- Control success and failure paths.
- Change integration behavior with minimal custom code.
This approach supports scalable, extensible, and maintainable connectivity between Siebel and other enterprise applications.
Before you configure an integration, identify the business process that you want to automate. For example, an external application might submit a service request, Siebel CRM might validate and process the request, and another enterprise system might need to be notified when processing is complete.
Integration configurations define this end-to-end process, including how requests enter Siebel CRM, how data is transformed, which actions are executed, how errors are handled, and how external systems participate in the integration flow.
To prepare integration configurations:
- Prepare JSONata configurations.
- Prepare Domain Specific Languages (DSLs).
- Prepare domain configurations.
Preparing JSONata Configurations
In many integrations, the payload received from an external system does not match the format required by Siebel CRM. JSONata mappings enable you to transform incoming and outgoing payloads by using declarative expressions instead of custom code.For example, an external application might use different field names or data structures than those required by Siebel CRM.
JSONata provides a concise, declarative way to select, filter, combine, and transform JSON data. JSONata mappings can convert the payload into the required format before processing and transform Siebel CRM responses into the format expected by the external application.This helps integrations map between external API contracts and the structures expected by Siebel processes, and from Siebel processes back to external API contracts, without custom procedural code.
Transformation mappings in integration configurations use the JSONata expression language to define how request and response payloads are reshaped. By embedding JSONata-based mappings in the configuration, you can implement and change payload transformations in a controlled and maintainable way.
This approach helps keep integration logic consistent and easier to test and support.
Sample JSONata Configuration
(
$items := $.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].ListOfSWIOrderItem.SWIOrderItem;
$safeNumber := function($val) {
$trim($string($val)) != "" ? $number($val) : 0
};
$buildTree := function($nodes, $parentId, $headerPriceListId) {
$map(
$filter($nodes, function($n) {
$n.'Parent Order Item Id' = $parentId
}),
function($node) {
(
$children := $buildTree($nodes, $node.Id);
$purchaseChild := $filter($nodes, function($c) {
$c.'Parent Order Item Id' = $node.Id and
$contains($c.Name, "-PURCHASE")
})[0];
$purchasePriceToAdd := $purchaseChild ? $safeNumber($purchaseChild.'Net Price') : 0;
$netPrice := $safeNumber($node.'Net Price');
$listPrice := $safeNumber($node.'List Price');
$hasDiscountPercent :=
$exists($node.'Discount Percent') and
$trim($string($node.'Discount Percent')) != '';
$hasDiscountAmount :=
$exists($node.'Discount Amount') and
$trim($string($node.'Discount Amount')) != '';
$hasUnitPrice :=
$exists($node.'Unit Price') and
$trim($string($node.'Unit Price')) != '';
$hasPriceListId :=
$exists($node.'Price List Id') and
$trim($string($node.'Price List Id')) != '';
$resolvedPriceType :=
$hasDiscountPercent ? 'discountPercentageOverride' :
$hasDiscountAmount ? 'amountOverride' :
$hasUnitPrice ? 'discountOverride' :
null;
$priceListId :=
$hasPriceListId ? $node.'Price List Id' : $headerPriceListId;
$base := {
'@type': 'ProductOrderItemOSMDBE',
'id': $node.Id,
'action':
$lowercase($node.'Action Code') = 'new'
? 'add'
: $lowercase($node.'Action Code'),
'quantity': $node.Quantity,
'productOffering': {
'id': $node.'External Product Id',
'name': $node.'Name'
},
'priceList': {
'id': $priceListId,
'name': ''
},
'itemPrice': [
$merge([
{
'priceType': $node.'Price Type',
'recurringChargePeriod': $node.'Unit of Measure',
'price': {
'dutyFreeAmount': {
'value': $listPrice,
'unit': $node.'Currency Code'
},
'taxIncludedAmount': {
'value': $listPrice,
'unit': $node.'Currency Code'
}
}
},
$resolvedPriceType
? {
'priceAlteration': [
{
'priceType': $resolvedPriceType,
'price': {
'dutyFreeAmount': {
'unit': $node.'Currency Code',
'value': $netPrice
},
'taxIncludedAmount': {
'unit': $node.'Currency Code',
'value': $netPrice
}
}
}
]
}
: {}
])
],
'itemTotalPrice': (
$promoType := $node.'Promotion Role';
$mrc := $safeNumber($node.'Promotion MRC Total');
$nrc := $safeNumber($node.'Promotion NRC Total');
$promoType = 'Bundled Promotions'
? [
{
'priceType': 'recurring',
'price': {
'dutyFreeAmount': {
'value': $mrc,
'unit': $node.'Currency Code'
},
'taxIncludedAmount': {
'value': $mrc,
'unit': $node.'Currency Code'
}
}
},
{
'priceType': 'oneTime',
'price': {
'dutyFreeAmount': {
'value': $nrc,
'unit': $node.'Currency Code'
},
'taxIncludedAmount': {
'value': $nrc,
'unit': $node.'Currency Code'
}
}
}
]
: []
),
'product': {
'@type': 'ProductRefOrValueOSMDBE',
'id': $node.'Asset Integration Id',
'serviceId': $node.'Service Id',
'name': 'emulator',
'productSpecification': {
'id': $node.'External Class Id',
'name': $node.'Class Name'
},
'productCharacteristic': (
$xa := $node.ListOfSWIOrderItemXA.SWIOrderItemXA;
$map(
$type($xa) = "array"
? $xa
: $type($xa) = "object"
? [$xa]
: [],
function($c) {
{
'name': $c.Name,
'value': $c.Value,
'valueType': $c.'Property Type Code'
}
}
)
)
}
};
$filteredChildren := $filter($children, function($v) {
$not($contains($v.productOffering.name, "-PURCHASE"))
});
$count($filteredChildren) > 0
? $merge([
$base,
{
'productOrderItem': $filteredChildren
}
])
: $base
)
}
)
};
{
"@type": "ProductOrderOSM_Create",
'externalId':
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].Id,
'description':
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].Description,
'priority':
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].'Order Priority',
'orderTotalPrice': [
{
'priceType': 'recurring',
'price': {
'dutyFreeAmount': {
'value': $safeNumber(
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].'MRC Total'
),
'unit':
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].'Currency Code'
},
'taxIncludedAmount': {
'value':
$safeNumber(
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].'Tax Amount MRC'
) +
$safeNumber(
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].'MRC Total'
),
'unit':
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].'Currency Code'
}
}
},
{
'priceType': 'oneTime',
'price': {
'dutyFreeAmount': {
'value': $safeNumber(
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].'NRC Total'
),
'unit':
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].'Currency Code'
},
'taxIncludedAmount': {
'value':
$safeNumber(
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].'Tax Amount NRC'
) +
$safeNumber(
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].'NRC Total'
),
'unit':
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].'Currency Code'
}
}
}
],
'billingAccount': {
'id':
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].'Billing Account Id',
'name':
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].'Billing Account'
},
'productOrderItem': [
$buildTree(
$items,
"",
$.get_product_order.SiebelMessage.ListOfSWIOrderIO.SWIOrder[0].'Price List Id'
)
]
}
)
For information about JSONata, refer the JSONata documentation.
Preparing DSLs
After you define the required data transformations, define the integration execution flow by using a domain-specific language (DSL). A domain-specific language (DSL) defines the runtime behavior of an integration as a configuration-driven workflow. You can use a DSL to model an integration as a sequence of executable steps that coordinate multiple actions, such as invoking Siebel CRM operations, applying transformations, and publishing or consuming events.
DSL provides built-in control flow constructs that define how the integration proceeds under different outcomes. These constructs include:
- Step sequencing to control execution order.
- Success and failure transitions to route processing based on outcomes.
- Conditional branching to support different paths for different scenarios.
- Loops and iteration to iterate over a specific step or an entire workflow as needed.
-
Retries and error-handling behavior to improve resilience and standardize responses.
- Required top-level keys:
inputoutputstepsresponsetransitions
- Optional top-level key is
global.
Input and Output
input and output to define the OpenAPI
contract for /integration/{integrationId}:inputdefines the OpenAPI request body schema.outputdefines the OpenAPI200response schema.- Step execution uses
steps,inputSpecification, andresponse.
- Top-level
inputandoutputare required. - Both values must be JSON objects.
- Both values must include top-level
"type": "object". - Describe generation fails if
"type": "object"is missing.
The following schema nodes are supported in input and
output keys:
| Parameter | Description |
|---|---|
| Inline object | Uses type: "object" and recursively processes
properties. Additional schema attributes (for
example, description, required,
additionalProperties, and
example) are preserved. |
| Inline array | Uses type: "array" and items.
Additional array attributes (for example, minItems,
maxItems, uniqueItems) are
preserved. |
| Inline primitive schema | Copies primitive schemas, such as string,
integer, number, and
boolean, to OpenAPI as-is. Attributes such as
format, enum,
default, minimum,
maximum, nullable are
preserved. |
| Siebel IO reference | Uses type: "IntegrationObject" and
IntegrationObject: "<IO Name>". The value is
replaced with a $ref to a generated component
schema resolved from Siebel metadata. |
| External OpenAPI reference |
Uses For
|
-
Inline request and response schemas:
"input": { "type": "object", "required": ["customerId", "items"], "properties": { "customerId": { "type": "string" }, "priority": { "type": "string", "enum": ["LOW", "NORMAL", "HIGH"], "default": "NORMAL" }, "items": { "type": "array", "minItems": 1, "items": { "type": "object", "required": ["sku", "qty"], "properties": { "sku": { "type": "string" }, "qty": { "type": "integer", "minimum": 1 } } } } } }, "output": { "type": "object", "properties": { "orderId": { "type": "string" }, "status": { "type": "string" }, "acceptedAt": { "type": "string", "format": "date-time", "nullable": true } } } -
IntegrationObjectUsage:"input": { "type": "object", "properties": { "account": { "type": "IntegrationObject", "IntegrationObject": "Account" } } }, "output": { "type": "object", "properties": { "contacts": { "type": "array", "items": { "type": "IntegrationObject", "IntegrationObject": "Contact" } } } } -
externalSchemaUsage:"input": { "type": "object", "properties": { "quoteRequest": { "type": "externalSchema", "restDef": "pricing-rest", "$ref": "#/components/schemas/QuoteRequest" } } }, "output": { "type": "object", "properties": { "quoteResponse": { "type": "externalSchema", "restDef": "pricing-rest", "$ref": "#/components/schemas/QuoteResponse" } } }
Step Types and Fields
steps to define the executable workflow steps. Supported
step types are:BusinessServiceWorkflowRESTOutboundEventPublish
RestOutbound step type is supported
only for the out-of-the-box integrations delivered with Open Integration. Using this
step type in custom integrations is not supported.The following table lists the fields supported for each step type and indicates whether a field is required for Business Service, Workflow, REST Outbound, and Event Publish step types.
| Field | BusinessService | Workflow | RESTOutbound | EventPublish | Description |
|---|---|---|---|---|---|
type |
Required | Required | Required | Required | Step execution type. |
service |
Required | No | No | No | Siebel business service name. |
method |
Required | No | Required | No | Business service method or HTTP method. |
serviceName |
No | Required | No | No | Siebel workflow process. |
restSpec |
No | No | Required | No | External REST alias. |
endPoint |
No | No | Required | No | Relative REST path. |
pathParams |
No | No | Optional | No | Path token values. |
queryParams |
No | No | Optional | No | Query string values. |
inputHeaders |
No | No | Optional | Optional | Request or event headers. |
queue |
No | No | No | Required | Outbound event alias. |
partitions |
No | No | No | Optional | Fixed partitions. |
partitionKey |
No | No | No | Optional | Dynamic partition key. |
inputSpecification |
Required | Required | Required | Required | Data assembly pipeline. |
retryConfig |
Optional | Optional | Optional | Optional | Retry behavior. |
output |
Optional | Optional | Optional | Optional | Updates global values from step output. |
storeInputToGlobal |
Optional | Optional | Optional | Optional | Updates global values from step input. |
Data Collection
You can use dataCollection in inputSpecification to
collect data for a step or response. Each entry requires source.
The optional field is transformationSpec.
The supported source values are:
| Source | Runtime Behavior |
|---|---|
WorkflowInput |
Collects the original inbound payload. Applies source-level
transformationSpec if provided. |
WorkflowHeaders |
Collects the inbound request headers map. Applies source-level
transformationSpec if provided. |
<StepName> |
Collects the step output for the named step. Before source-level
transformation, runtime augments the input with
global. On the error path, runtime also
augments the input with exception. |
The final collected object contains one key for each source name. Runtime also adds
root-level global. In the error path, runtime also adds root-level
exception.
Important behavior:
- Source processing is parallel, so ordering is not guaranteed.
- If a referenced step has not produced output, source data is absent for that key.
- If source-level
transformationSpecis not set, transformation is skipped for that source. - Transformation specs can access global storage without additional settings.
Transformation Specifications
transformationSpec to define transformation behavior. It
can appear in:dataCollection[].transformationSpectransformation[].transformationSpec- Response payload transformation blocks
- Collect data from
dataCollection. - Run
transformation[] sequentially. - Run optional script hooks:
preTransformationScriptpostTransformationScript
- Run optional
transformationScriptafter the transformation chain.
- Runtime reads transformation specs from
integration-configurations/<domain>/jsonata-configurations/transformation-spec/. - Only valid listed domains from the merged config are considered.
- Relative subpaths, such as
folder/file.json, are supported. - Spec content is cached in memory after the first read.
You must use unique file names across domains to avoid ambiguous first-match behavior. Keep transformations idempotent where possible for retry safety.
Embedded Expressions and Conditions
Open Integration evaluates conditions and expressions with Apache JEXL.
Expression fields use this wrapper ${…}. Runtime removes the wrapper
and evaluates the expression inside it. If a value does not use
${...}, the direct provided value is used.
- Transition conditions
outputandstoreInputToGlobalmapping expressions- REST or Event header, path, and query dynamic values
- Event publish
partitionKey - Retry
retryOnCondition - Response
statusCodeexpressions and header expressions
You must use null-safe expressions and keep expressions free of side effects, and use
global.* as the stable cross-step state interface.
WorkflowInput and WorkflowHeaders
WorkflowInput and WorkflowHeaders are
workflow-level special variables in embedded expressions:WorkflowInputcontains the original inbound request payload for the integration API. You must treat it as read-only and use it when you need stable access to original request fields, independent of transformed stepinput.WorkflowHeaderscontains inbound HTTP headers for the integration API request. You must treat it as a read-only map of header names to values, and use it for correlation, channel, auth-context propagation, and response or header enrichment.
To access the workflow-level special variables:
- Use dot notation for standard keys
WorkflowInput.accountId. - Use bracket notation for keys with special characters or spaces, or for
explicit header lookup
WorkflowHeaders['x-correlation-id'].
- Use
WorkflowInputandWorkflowHeadersto access the original request payload and request headers. These variables provide the initial context that was supplied when the workflow started. - Use
inputwhen you need to reference the current step input. This is particularly useful after data collection or transformation steps that modify the data before it is passed to the next step. - Use
globalto access values that are computed or stored during workflow execution and need to be shared across multiple steps.
Transition conditions
Transition conditions control how the workflow moves from one state to another. The workflow evaluates transitions in the configured order and takes the first matching transition.
After a condition matches, the workflow invokes the target step and then continues into the target state.
Transition conditions typically read state produced by previously executed steps.
This state is often stored in global.
You must use embedded expressions for transition conditions and dynamic values.
Embedded Expression Examples
- Transition based on
global:"condition": "${global.account_status == ‘Active’}" - Transition based on workflow input:
"condition": "${WorkflowInput.promotionId != null && WorkflowInput.promotionId != ''}" - REST output global mapping by using
statusandoutput:"output": { "global.rest_status": "${status}", "global.external_ref": "${status == 200 ? output.externalReference : null}" } - Dynamic header from input and
global:"inputHeaders": { "account-id": "${global.account_id}", "channel": "${WorkflowHeaders['x-channel']}" } - Retry condition:
"retryOnCondition": "${output.errorCode != null && output.errorCode != ''}"
Embedded Expression Authoring Rules
When you author embedded expressions, follow these rules:
- Use
global.*as the stable cross-step state interface. - Update
globalthrough step output mappings before you use those values in later transition conditions. - Handle nullable values defensively, such as
x != null && .... - For keys with spaces or special characters, use quoted or bracket access patterns.
- Keep expressions free of side effects.
output and storeInputToGlobal
You can use output and storeInputToGlobal as global
update maps:
- Use the following key format:
global.<name> - Use the following value format:
${…}The value must be an embedded expression.
The following validation rules apply:
- The key must start with
global. <name>must exist in the top-levelgloballist.-
The value must satisfy the embedded expression format.
retryConfig
You can use retryConfig to control retry eligibility, delay
strategy, and retry stop conditions.
The following table lists the fields available in the retryConfig
section:
| Field | Type | Description |
|---|---|---|
retryMaxAttempts |
Integer | Total number of attempts, including the initial call. For
example, 5 means the initial attempt plus up to 4
retries. |
retryOnlyOnStatusCodes |
Integer array | HTTP status codes for which retry is attempted. For example,
[502, 503, 504]. |
retryExcludeStatusCodes |
Integer array | HTTP status codes for which retry is skipped. For example,
[400]. |
retryOnCondition |
String embedded expression | Expression that is evaluated at runtime after an attempt. If the
expression evaluates to true, retry is
attempted. |
retryDelayMilliseconds |
Integer | Base delay in milliseconds before retry. For example,
1000 is a 1-second base delay. |
retryBackoffMultiplier |
Number | Scales the delay across attempts by using exponential or factor
backoff. If set to 1.0, the delay stays
fixed. |
retryMaxDelayMilliseconds |
Integer | Upper limit for the computed retry delay. |
retryJitterMilliseconds |
Integer | Random plus or minus jitter applied to the computed delay to help avoid synchronized retries. |
retryTotalTimeoutMilliseconds |
Integer | Maximum total elapsed time allowed for all attempts and waits. |
Delay Progression Model
The retry delay typically uses this progression model: delay =
retryDelayMilliseconds * (retryBackoffMultiplier ^ (attempt_number -
1))
- Bounds the delay by
retryMaxDelayMilliseconds, if configured. - Applies
retryJitterMilliseconds, if configured.
Validation and Compatibility Rules
- One of
retryOnlyOnStatusCodes,retryExcludeStatusCodes, orretryOnConditionis required. - One of
retryMaxAttemptsorretryTotalTimeoutMillisecondsis required. retryDelayMillisecondsis required.
Custom Validator Constraints
| Step Type | Retry Rules |
|---|---|
BusinessService |
Must use retryOnCondition. Must not use
retryOnlyOnStatusCodes or
retryExcludeStatusCodes. |
Workflow |
Must use retryOnCondition. Must not use
retryOnlyOnStatusCodes or
retryExcludeStatusCodes. |
EventPublish |
Must not use retryOnCondition,
retryOnlyOnStatusCodes, or
retryExcludeStatusCodes. |
RESTOutbound |
Can use expression-based retry with
retryOnCondition, or status-code-based retry
with retryOnlyOnStatusCodes or
retryExcludeStatusCodes. |
Recommended Retry Patterns:
-
Status-Code-Based Retry for RESTOutbound: You must use status-code-based retry for RESTOutbound steps when retries depend on HTTP response status codes. For example
"retryConfig": { "retryOnlyOnStatusCodes": [502, 503, 504], "retryMaxAttempts": 5, "retryDelayMilliseconds": 1000, "retryBackoffMultiplier": 2.0, "retryMaxDelayMilliseconds": 10000, "retryJitterMilliseconds": 500, "retryTotalTimeoutMilliseconds": 60000 } -
Expression-Based Retry for Business Service or Workflow: You must use expression-based retry for
BusinessServiceorWorkflowsteps when retries depend on a runtime expression. For example:"retryConfig": { "retryOnCondition": "${output.'Error Code' == 'TEMPFAIL'}", "retryMaxAttempts": 3, "retryDelayMilliseconds": 500, "retryBackoffMultiplier": 1.0, "retryTotalTimeoutMilliseconds": 5000 }
response
You can use response to define success and error responses for the
workflow. response must contain both of the following sections:
successerror
Each section supports:
- (Required)
payload - (Optional)
statusCode - (Optional)
Headers
The payload follows the same structure as step
inputSpecification.
Error-path behavior:
- For error scenario collection, runtime adds
exceptionto the collected payload context when exception information is available. - Both
statusCodeandheaderssupport embedded expressions.
Sample Payload:
"response": {
"success": {
"payload": {
"dataCollection": [
{
"source": "Augment_Account_REST",
"transformationSpec": "complex-data-collection.json"
}
],
"transformation": [
{
"transformationSpec": "complex-success-transformation.json"
}
]
},
"statusCode": "${global.rest_status >= 200 && global.rest_status < 300 ? 200 :(global.rest_status >= 400 && global.rest_status < 500 ? 400 : 500)}",
"headers": {
"X-Flow-Result": "success",
"X-External-Ref": "${global.external_ref}"
}
},
"error": {
"payload": {
"dataCollection": [
{
"source": "Augment_Account_REST",
"transformationSpec": "complex-data-collection.json"
}
],
"transformation": [
{
"transformationSpec": "complex-error-transformation.json"
}
]
},
"statusCode": 500,
"headers": {
"X-Flow-Result": "error"
}
}
}
Transitions
You must use transitions to define the workflow state machine. Each
key in transitions is a state name and contains a
transitions[] array.
Schema Rules
- $start is required.
- Each state entry requires
transitions[]. - Each transition requires
target. conditionis optional.- When
conditionis present, it must use the${...}expression format.
- Any declared step name
- $end
- $errorEnd
- $start
Runtime Execution Model
Execution begins at $start.
- Runtime evaluates $start.transitions in order.
- The first matching transition decides the next target.
- If the target is a step, runtime executes that step.
- After step execution, runtime evaluates that step state’s transitions[] in order.
- Runtime continues until $end or $errorEnd is reached.
- $end produces
response.success. -
$errorEnd produces
response.error
A transition without a condition act as an unconditional fallback.
Condition Evaluation Context
WorkflowInputWorkflowHeadersGlobal- Step context keys, such as
<StepName>.output - On the exception path,
hasExceptionOccurredandexception
Use global.* for branch decisions that depend on prior step results.
Use WorkflowInput and WorkflowHeaders for routing
based on the original request. Keep one final unconditional transition as a fallback
for deterministic routing.
Branching Pattern
"transitions": {
"$start": {
"transitions": [
{
"target": "Validate_Request"
}
]
},
"Validate_Request": {
"transitions": [
{
"condition": "${global.validation_status == 'VALID'}",
"target": "Fetch_Account"
},
{
"condition": "${global.validation_status == 'INVALID'}",
"target": "$errorEnd"
},
{
"target": "$errorEnd"
}
]
},
"Fetch_Account": {
"transitions": [
{
"target": "$end"
}
]
}
}
In this pattern, the first true condition wins. The last unconditional transition
works as the default else branch.
Exception-Aware Routing
You can branch differently on the exception path by using
hasExceptionOccurred or exception.
"transitions": {
"Invoke_External_REST": {
"transitions": [
{
"condition": "${global.hasExceptionOccurred == true}",
"target": "Build_Error_Response"
},
{
"condition": "${global.rest_status >= 200 && global.rest_status < 300}",
"target": "$end"
},
{
"target": "$errorEnd"
}
]
},
"Build_Error_Response": {
"transitions": [
{
"target": "$errorEnd"
}
]
}
}
Loops and Safety
- Maintain loop counters or flags in
global. - Add upper-bound checks in conditions.
- Always include a deterministic exit path to $end or $errorEnd.
Pipeline Validation Rules
The pipeline runs validation by using
openint-spec-validator.jar.
The pipeline validates the following items:
- Base configuration,
config.json, againstbaseConfigSchema.json. - Siebel connectivity rules, including
useCGwith the correct URL field. - UI resource and
loginpathdependency. - Domain configuration,
domain-configurations/*.json, againstintegrationConfigSchema.json. - Integration path format, including whether the path contains nested paths after
/integrations/<id>. - Required
externalDsl. - Required
externalRESTandoutboundEventSchema. - Merged configuration.
- External DSL schema validation against
externalDSLSchema.json. - External DSL semantic validation, including transition targets, expression format, global mapping, and referenced transformation files.
- Step-specific retry rules.
- Additional integration checks.
apigen must contain at
least one of the following:resourcesintegrations
Additional Integration Checks
The pipeline enforces the following checks for integration scripts and reusable functions:
- Each
scripts/*.jsfile must contain exactly oneexecuteTransformationScriptfunction. - Script files must not contain extra function declarations.
.jsfile names injsonata-configurations/reusable-functions/must be unique across selected domains.
Failure Artifacts
If validation fails, the pipeline writes failure details to the following files:
openint-deploy/failed_config_openapi_keys.txt
openint-deploy/failed_external_dsls.txt
Authoring Checklist
Before you package the configuration, verify the following items:
- Add the domain in
config.jsonunderapigen.integration-domains. - Wire the integration in
domain-configurations/integration.json. - Author the DSL according to the schema definition and validation rules.
- Declare every global variable used by
global.<name>mappings. - Keep each
transformationSpecfile resolvable under the domaintransformation-specfolders. - Ensure that every
restSpecalias exists inapigen.externalREST. - Ensure that every
queuealias exists inapigen.outboundEvents. - Optionally validate the configuration before packaging by running one of the
following commands:
or./gen.sh –codegengen.bat --codegen
DSL Schema and Design-Time Validation
Orchestration flows are authored as Domain-Specific Language (DSL) definitions. Each DSL definition must conform to the published DSL schema.
The schema defines the supported DSL structure and semantics, including permitted step types, required attributes, and valid control-flow constructs such as transitions, conditions, loops, and retry definitions. This schema-driven approach helps make integrations consistent and predictable.
Open Integration includes a DSL Validator that runs during the design-time pipeline. The validator checks whether a DSL definition is well formed and schema compliant before it is deployed or executed. It also detects common configuration issues, such as missing required fields, invalid step references, or unsupported constructs.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "WorkflowConfig",
"type": "object",
"required": ["input", "output", "steps", "response", "transitions"],
"additionalProperties": false,
"properties": {
"input": {
"type": "object"
},
"output": {
"type": "object"
},
"global": {
"type": "array",
"items": { "type": "string" },
"description": "Optional list of string global variable names."
},
"steps": {
"type": "object",
"minProperties": 1,
"description": "A map (object) of steps. Step names (keys) MUST be unique as per JSON object specification.",
"additionalProperties": {
"oneOf": [
{
"type": "object",
"required": ["type", "restSpec", "endPoint", "method", "inputSpecification"],
"description": "RESTOutbound Step.",
"properties": {
"type": { "const": "RESTOutbound" },
"restSpec": { "type": "string" },
"endPoint": { "type": "string" },
"method": { "type": "string" },
"pathParams": { "type": "object" },
"queryParams": { "type": "object" },
"inputHeaders": { "type": "object" },
"inputSpecification": { "$ref": "#/definitions/inputspecification" },
"retryConfig": { "$ref": "#/definitions/retryConfig" },
"output": { "$ref": "#/definitions/globalstringmap" },
"storeInputToGlobal": { "$ref": "#/definitions/globalstringmap" }
},
"additionalProperties": false
},
{
"type": "object",
"required": ["type", "service", "method", "inputSpecification"],
"description": "Business Step.",
"properties": {
"type": { "const": "BusinessService" },
"service": { "type": "string" },
"method": { "type": "string" },
"inputSpecification": { "$ref": "#/definitions/inputspecification" },
"retryConfig": { "$ref": "#/definitions/retryConfig" },
"output": { "$ref": "#/definitions/globalstringmap" },
"storeInputToGlobal": { "$ref": "#/definitions/globalstringmap" }
},
"additionalProperties": false
},
{
"type": "object",
"required": ["type", "serviceName", "inputSpecification"],
"description": "Workflow Step.",
"properties": {
"type": { "const": "Workflow" },
"serviceName": { "type": "string" },
"inputSpecification": { "$ref": "#/definitions/inputspecification" },
"retryConfig": { "$ref": "#/definitions/retryConfig" },
"output": { "$ref": "#/definitions/globalstringmap" },
"storeInputToGlobal": { "$ref": "#/definitions/globalstringmap" }
},
"additionalProperties": false
},
{
"type": "object",
"required": ["type", "queue", "inputSpecification"],
"description": "EventPublish Step",
"properties": {
"type": { "const": "EventPublish" },
"queue": { "type": "string" },
"inputSpecification": { "$ref": "#/definitions/inputspecification" },
"output": { "$ref": "#/definitions/globalstringmap" },
"retryConfig": { "$ref": "#/definitions/retryConfig" },
"storeInputToGlobal": { "$ref": "#/definitions/globalstringmap" },
"inputHeaders": { "type": "object" },
"partitions": {
"type": "array",
"items": { "type": "integer" }
},
"partitionKey": { "type": "string" }
},
"additionalProperties": false
}
]
}
},
"response": {
"type": "object",
"required": ["success", "error"],
"properties": {
"success": { "$ref": "#/definitions/responseCollectorSpec" },
"error": { "$ref": "#/definitions/responseCollectorSpec" }
},
"additionalProperties": false
},
"transitions": {
"type": "object",
"properties": {
"$start": { "$ref": "#/definitions/transitionStep" }
},
"patternProperties": {
"^(?!\\$start).+$": { "$ref": "#/definitions/transitionStep" }
},
"required": ["$start"],
"additionalProperties": false
}
},
"definitions": {
"inputspecification": {
"type": "object",
"properties": {
"dataCollection": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["source"],
"properties": {
"source": { "type": "string" },
"transformationSpec": { "type": "string" }
},
"additionalProperties": true
}
},
"transformation": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["transformationSpec"],
"properties": {
"transformationSpec": { "type": "string" },
"preTransformationScript": { "type": "string" },
"postTransformationScript": { "type": "string" }
},
"additionalProperties": true
}
},
"transformationScript": { "type": "string" }
},
"required": ["transformation"],
"additionalProperties": true
},
"responseCollectorSpec": {
"type": "object",
"description": "Terminal workflow response collector with payload spec and optional HTTP metadata.",
"properties": {
"payload": { "$ref": "#/definitions/inputspecification" },
"statusCode": {
"description": "Optional HTTP status code for workflow terminal response.",
"oneOf": [
{ "type": "integer", "minimum": 100, "maximum": 599 },
{
"type": "string",
"minLength": 1,
"pattern": "^(\\$\\{[\\s\\S]*\\}|[1-5][0-9]{2})$"
}
]
},
"headers": {
"type": "object",
"description": "Optional response headers map for workflow terminal response.",
"additionalProperties": {
"type": "string",
"minLength": 1
}
}
},
"required": ["payload"],
"additionalProperties": false
},
"globalstringmap": {
"type": "object",
"propertyNames": {
"type": "string",
"pattern": "^global\\..+"
},
"additionalProperties": {
"type": "string"
},
"description": "A map where each key starts with 'global.' and the value is a string."
},
"transitionStep": {
"type": "object",
"required": ["transitions"],
"properties": {
"transitions": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["target"],
"properties": {
"target": { "type": "string" },
"condition": { "type": "string" }
},
"additionalProperties": false
}
}
},
"additionalProperties": false
},
"retryConfig": {
"type": "object",
"properties": {
"retryMaxAttempts": {
"type": "integer",
"minimum": 1,
"description": "Max number of attempts (including original call)"
},
"retryOnlyOnStatusCodes": {
"type": "array",
"items": { "type": "integer", "minimum": 100, "maximum": 599 },
"description": "Only retry for these HTTP status codes",
"minItems": 1,
"uniqueItems": true
},
"retryExcludeStatusCodes": {
"type": "array",
"items": { "type": "integer", "minimum": 100, "maximum": 599 },
"description": "Do not retry for these HTTP status codes",
"minItems": 1,
"uniqueItems": true
},
"retryOnCondition": {
"type": "string",
"minLength": 1,
"description": "Expression to evaluate if retry should occur"
},
"retryDelayMilliseconds": {
"type": "integer",
"minimum": 0,
"description": "Initial delay (ms) between retries"
},
"retryBackoffMultiplier": {
"type": "number",
"minimum": 1.0,
"default": 1.0,
"description": "Factor for exponential backoff"
},
"retryMaxDelayMilliseconds": {
"type": "integer",
"minimum": 0,
"description": "Max pause (ms) between retries"
},
"retryJitterMilliseconds": {
"type": "integer",
"minimum": 0,
"description": "Maximum random offset (ms) for retry delay"
},
"retryTotalTimeoutMilliseconds": {
"type": "integer",
"minimum": 1,
"description": "Maximum total time (ms) for all retries"
}
},
"additionalProperties": false,
"allOf": [
{
"anyOf": [
{ "required": ["retryMaxAttempts"] },
{ "required": ["retryTotalTimeoutMilliseconds"] }
]
},
{
"required": ["retryDelayMilliseconds"]
}
]
}
}
}
Preparing Domain Configurations
After you define the integration flow, configure the environment-specific settings required for runtime execution.
For example, a DSL might reference an external service, while the actual endpoint URLs, authentication settings, entry points, and event topics are defined separately in the domain configuration.
An Open Integration configuration document, in JSON format, supports the orchestration DSL and defines both runtime and design-time settings in a single structured file. It separates configuration from DSL logic so the same orchestration flow can be reused while environment-specific details, such as endpoints and security, are managed separately.
The Integration Configuration document typically includes the following details:
- Endpoint configuration, including:
- A list of supported endpoints referenced by the integration.
- The mapping that links an endpoint to a specific DSL.
- External REST endpoint, or spoke system, details, such as target URLs and connection parameters.
- Authentication and security configuration for external system calls, such as the required authentication type and the corresponding information.
- Eventing configuration, including the publish or subscribe topics used when the integration publishes events.
Use this section to prepare the domain configuration document that connects the integration flow to endpoints, external systems, security settings, and eventing configurations.
By centralizing these details in a JSON document, Open Integration separates orchestration logic from connectivity details. This improves maintainability and simplifies updates when endpoints, credentials, or event topics change.
The base folder for integration configurations is
openint-deploy/integration-configurations.
Domain Folder Layout
Each domain uses the following folder layout:
integration-configurations/
<Domain>/
domain-configurations/
integration.json
external-dsl/
*.json
restoutbound/
*.json
jsonata-configurations/
transformation-spec/
translated-mappings/
reusable-functions/
scripts/
*.js
Domain Configuration File
The domain-configurations/integration.json file defines the domain
configuration. During the design-time pipeline, gen.sh or
gen.bat merges this file into
merged_config.json.
The main sections are:
apigen.integrations:Use
apigen.integrationsto define integration endpoint paths. Each key is an integration endpoint path in this formatopenintegration/v1.0/integration/<name>.Each integration entry includes:- Required
externalDsl - Optional
resources.externalREST[] - Optional
resources.inboundEventRegistrationExample:
{ "apigen": { "integrations": { "openintegration/v1.0/integration/checkAccount": { "externalDsl": "demo-siebelBS-REST.json" }, "openintegration/v1.0/integration/DBEEventConsume": { "externalDsl": "DBE-To-Siebel-Contact-Publish.json", "resources": { "externalREST": [ { "spokesystem": "describeSystem", "describe": "/tmf632/describe", "openAPIFilepath": "tm632.json" } ], "inboundEventRegistration": { "topic": "OSM-Orders-Produce", "partitions": [0], "integrationUser": "lapple" } } } } } }Integration Linkage
External DSL files reference these integration configuration sections:
apigen.integrations.<path>.externalDslapigen.externalREST.<alias>forRESTOutbound.restSpecapigen.outboundEvents.<alias>forEventPublish.queue
apigen.externalREST:Use
apigen.externalRESTto define external REST aliases used byRESTOutbound.restSpecin the DSL.Each alias requires:baseURLauthentication
Supported authentication modes are:-
basic, withusernameandpassword. -
oidc-client-credentials, withclient-id,client-secret,identity-uri,scope, andoptional oidc-flow.
apigen.outboundEvents:Use
apigen.outboundEventsto define outbound event aliases used byEventPublish.queuein the DSL.Sample:
{ "apigen": { "outboundEvents": { "dbe-event-publish": { "topic": "OSM-Orders" }, "siebel-event-publish": { "topic": "SiebelOrderUpdate" } } } }OpenIntegration uses this section to publish messages to configured topics.
Create integration.json
You must create
integration.jsonfrom the template. Use the root fileopenint-deploy/integrations_template.jsonas a starter template when you create a domain configuration.To create integration.json :
- Copy
integrations_template.jsontointegration-configurations/<Domain>/domain-configurations/integration.json - Replace placeholder map keys, such as
#Unique System Name, with real aliases. - Replace placeholder values with domain-specific values.
- Remove template-only guidance fields, such as
#Mapand#Mandatory. - For each
apigen.externalREST.<alias>.authentication, configure exactly one authentication mode:basicoidc-client-credentials
Sample
integration.json{ "apigen": { "integrations": { "openintegration/v1.0/integration/checkAccount": { "externalDsl": "demo-siebelBS-REST.json" }, "openintegration/v1.0/integration/DBEEventConsume": { "externalDsl": "DBE-To-Siebel-Contact-Publish.json", "resources": { "externalREST": [ { "spokesystem": "dbe-osm", "describe": "/tmf632/describe", "openAPIFilepath": "tm632.json" } ], "inboundEventRegistration": { "topic": "OSM-Orders-Produce", "partitions": [0] } } } }, "externalREST": { "castlemock": { "baseURL": "https://example.com", "authentication": { "basic": { "username": "user", "password": "password" } } }, "dbe-osm": { "baseURL": "https://example.com", "authentication": { "oidc-client-credentials": { "client-id": "client", "client-secret": "secret", "identity-uri": "https://idcs.example.com", "scope": "urn:example:scope" } } } }, "outboundEvents": { "dbe-event-publish": { "topic": "OSM-Orders" }, "siebel-event-publish": { "topic": "SiebelOrderUpdate" } } } }
- Copy
- Required
Design-Time Schema Validation
At design time, the pipeline validates all domain
domain-configurations/integration.json files against the Domain
Integration Schema JSON.
The schema requires:
- Top-level
apigen apigen.integrations- Valid integration paths that match
openintegration/<version>/integration/<name>
- Valid integration paths that match
Each integration entry requires externalDsl.
The optional resources.externalREST[] entries require:
spokesystemdescribeopenAPIFilepath
The optional resources.inboundEventRegistration entry requires:
topicpartitions
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "OpenInt Integration Configuration Schema",
"description": "Schema for validating OpenInt integrations configuration file",
"type": "object",
"required": ["apigen"],
"additionalProperties": false,
"properties": {
"apigen": {
"type": "object",
"description": "API generation configuration settings",
"required": ["integrations"],
"properties": {
"integrations": {
"type": "object",
"description": "Map of integration definitions by their API paths",
"patternProperties": {
"^openintegration/(v[0-9]+\\.[0-9]+)/integration/[^/]+$": {
"type": "object",
"description": "Individual integration configuration",
"required": ["externalDsl"],
"properties": {
"resources": {
"type": "object",
"description": "Resources used by this integration",
"properties": {
"externalREST": {
"type": "array",
"items": {
"type": "object",
"required": ["spokesystem", "describe", "openAPIFilepath"],
"properties": {
"spokesystem": {
"type": "string"
},
"describe": {
"type": "string"
},
"openAPIFilepath": {
"type": "string"
}
},
"additionalProperties": false
}
},
"inboundEventRegistration": {
"type": "object",
"required": ["topic", "partitions"],
"properties": {
"topic": {
"type": "string"
},
"partitions": {
"type": "array",
"items": {
"type": "integer"
}
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
"externalDsl": {
"type": "string",
"description": "Name of the external DSL file defining this integration"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
"externalREST": {
"type": "object",
"description": "Configuration for external REST API endpoints",
"patternProperties": {
"^.*$": {
"type": "object",
"description": "Configuration for a specific external system",
"required": ["baseURL", "authentication"],
"properties": {
"baseURL": {
"type": "string",
"description": "Base URL for the external system's REST API",
"format": "uri"
},
"authentication": {
"type": "object",
"description": "Authentication configuration for the external system",
"anyOf": [
{
"required": ["basic"]
},
{
"required": ["oidc-client-credentials"]
}
],
"properties": {
"basic": {
"type": "object",
"description": "Basic authentication credentials",
"required": ["username", "password"],
"properties": {
"username": {
"type": "string",
"description": "Username for basic authentication"
},
"password": {
"type": "string",
"description": "Password for basic authentication"
}
},
"additionalProperties": false
},
"oidc-client-credentials": {
"type": "object",
"description": "OIDC client credentials authentication",
"required": ["client-id", "client-secret", "identity-uri", "scope"],
"properties": {
"client-id": {
"type": "string",
"description": "OAuth2 client ID"
},
"client-secret": {
"type": "string",
"description": "OAuth2 client secret"
},
"identity-uri": {
"type": "string",
"description": "OIDC identity provider URI",
"format": "uri"
},
"oidc-flow": {
"type": "string",
"description": "OIDC authentication flow type",
"enum": ["client-credentials", "user-assertion"]
},
"scope": {
"type": "string",
"description": "OAuth2 scope for the authentication request"
}
},
"additionalProperties": false
}
}
}
},
"additionalProperties": false
}
}
},
"outboundEvents": {
"type": "object",
"description": "Configuration for outbound event publishing",
"patternProperties": {
"^.*$": {
"type": "object",
"description": "Configuration for a specific outbound event topic",
"required": ["topic"],
"properties": {
"topic": {
"type": "string",
"description": "Event topic name for publishing messages"
}
},
"additionalProperties": false
}
}
}
},
"additionalProperties": false
}
}
}
External DSL Files
Use external-dsl/*.json files to define integration workflow
behavior and step orchestration. For detailed field-level information, see
Preparing DSLs.
REST Outbound Files
Use restoutbound/*.json files to store OpenAPI files for external
systems referenced by integrations. These files are referenced by
resources.externalREST[].openAPIFilepath. Runtime and schema
reference flows use these specifications for external payload definitions.
Transformation Specifications
Transformation mappings in Integration Configurations use the JSONata expression language to define how request and response payloads are reshaped.
Transformation spec files are consumed by these External DSL fields:
inputSpecification.dataCollection[].transformationSpecinputSpecification.transformation[].transformationSpecresponse.<success|error>.payload.*.transformationSpec
Store transformation specs in
jsonata-configurations/transformation-spec/*.json.
Reusable Functions
Use jsonata-configurations/reusable-functions/* for shared reusable
function files used during transformation execution.
Validation requires .js file names to be unique across all selected
domains.
Translated Mappings
Use jsonata-configurations/translated-mappings/* to provide lookup
dictionaries for JSONata transformations.
The JSONata function getTranslatedMapping(value, type, locale) uses
these mappings to convert source values, such as codes, into translated or display
values. If a key is not found, runtime returns the original value unchanged.
Folder contract:
- Location:
integration-configurations/<domain>/jsonata-configurations/translated-mappings/ - Each file name is treated as a locale, such as
en.json,fr.json, orar.json - JSON content can contain nested objects
- Runtime flattens nested keys with dot notation
Runtime constructs lookup keys in this format
<type>.<locale>.<value>.
With the current runtime behavior, <type> is the domain folder
name under integration-configurations.
For example,
integration-configurations/OrderDomain/jsonata-configurations/translated-mappings/en.json.
{
"status": {
"A": "Approved",
"R": "Rejected"
}
}
$getTranslatedMapping("status.A",
"OrderDomain", "en")If the mapping exists, runtime returns Approved. If the mapping is
missing, runtime returns the original input, such as status.A.
- The output payload must be locale-specific.
- You need shared code-to-label translation logic across multiple transformation specs.
- You want to avoid repeated translation maps in JSONata expressions.
Validation Summary for Integrations
openint-spec-validator runs, it validates:config.jsonagainstbaseConfigSchema.json.- Domain configuration files against
integrationConfigSchema.json. - The merged config to ensure it contains at least one of
apigen.resourcesorapigen.integrations. - Referenced External DSL files for semantic and schema correctness.
- Script function contracts in
scripts/. - Reusable function file name uniqueness across selected domains.
- Domain configuration files against
openint-deploy/failed_config_openapi_keys.txtopenint-deploy/failed_external_dsls.txt
Integration Configuration Checklist
Before you run the pipeline, verify the following items:
- Add the domain in
config.jsonunderapigen.integration-domains. - Create or update
domain-configurations/integration.json. - Ensure every
externalDslfile exists inexternal-dsl/. - Ensure every
RESTOutbound.restSpecalias exists inapigen.externalREST. - Ensure every
EventPublish.queuealias exists inapigen.outboundEvents. - Ensure every
transformationSpecfile exists underjsonata-configurations/transformation-spec/. - Keep reusable function file names unique across selected domains.