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:

  1. Prepare JSONata configurations.
  2. Prepare Domain Specific Languages (DSLs).
  3. Prepare domain configurations.
Note: Open Integration transformation only supports integrations that use Siebel APIs or external application APIs that communicate with Siebel CRM and require access to Siebel metadata for transformation processing.

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.

A valid DSL includes the following top-level keys:
  • Required top-level keys:
    • input
    • output
    • steps
    • response
    • transitions
  • Optional top-level key is global.

Input and Output

You can use input and output to define the OpenAPI contract for /integration/{integrationId}:
  • input defines the OpenAPI request body schema.
  • output defines the OpenAPI 200 response schema.
  • Step execution uses steps, inputSpecification, and response.
The following rules apply:
  • Top-level input and output are 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 type: "externalSchema", restDef, and $ref. The schema is imported from the configured external REST OpenAPI and rewritten to a local #/components/schemas/... reference.

For externalSchema, the following rules apply:

  • restDef is required and must match resources.externalREST[].spokesystem in the integration config.
  • $ref is required and must target a concrete schema. For example, #/components/schemas/OrderRequest, /components/schemas/OrderRequest.
  • $ref values #, /, and #/ are invalid.
  • When multiple restDef systems are used in one DSL, imported component names are namespaced to avoid collisions.
Examples:
  • 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 }
      }
    }
    
    
  • IntegrationObject Usage:
    
    "input": {
      "type": "object",
      "properties": {
        "account": {
          "type": "IntegrationObject",
          "IntegrationObject": "Account"
        }
      }
    },
    "output": {
      "type": "object",
      "properties": {
        "contacts": {
          "type": "array",
          "items": {
            "type": "IntegrationObject",
            "IntegrationObject": "Contact"
          }
        }
      }
    }
    
  • externalSchema Usage:

    
    "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

You can use steps to define the executable workflow steps. Supported step types are:
  • BusinessService
  • Workflow
  • RESTOutbound
  • EventPublish
Note: The 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 transformationSpec is not set, transformation is skipped for that source.
  • Transformation specs can access global storage without additional settings.

Transformation Specifications

You can use transformationSpec to define transformation behavior. It can appear in:
  • dataCollection[].transformationSpec
  • transformation[].transformationSpec
  • Response payload transformation blocks
The transformation pipeline runs in this order:
  1. Collect data from dataCollection.
  2. Run transformation[] sequentially.
  3. Run optional script hooks:
    • preTransformationScript
    • postTransformationScript
  4. Run optional transformationScript after the transformation chain.
Transformation specification files look up behaviour:
  • 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.

You can configure embedded expressions in:
  • Transition conditions
  • output and storeInputToGlobal mapping expressions
  • REST or Event header, path, and query dynamic values
  • Event publish partitionKey
  • Retry retryOnCondition
  • Response statusCode expressions 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:
  • WorkflowInput contains 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 step input.
  • WorkflowHeaders contains 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'].
When defining expressions, choose the variable source based on the data that you need:
  • Use WorkflowInput and WorkflowHeaders to access the original request payload and request headers. These variables provide the initial context that was supplied when the workflow started.
  • Use input when 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 global to 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 status and output:
    "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 global through 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-level global list.
  • 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))

After the delay is calculated, the runtime applies the following rules:
  • Bounds the delay by retryMaxDelayMilliseconds, if configured.
  • Applies retryJitterMilliseconds, if configured.

Validation and Compatibility Rules

The following schema-level constraints apply:
  • One of retryOnlyOnStatusCodes, retryExcludeStatusCodes, or retryOnCondition is required.
  • One of retryMaxAttempts or retryTotalTimeoutMilliseconds is required.
  • retryDelayMilliseconds is 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 BusinessService or Workflow steps 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:

  • success
  • error

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 exception to the collected payload context when exception information is available.
  • Both statusCode and headers support 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

The following minimum schema rules apply:
  • $start is required.
  • Each state entry requires transitions[].
  • Each transition requires target.
  • condition is optional.
  • When condition is present, it must use the ${...} expression format.
Valid targets are:
  • 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.
The terminal states produce the following responses:
  • $end produces response.success.
  • $errorEnd produces response.error

A transition without a condition act as an unconditional fallback.

Condition Evaluation Context

A transition condition can read the following values:
  • WorkflowInput
  • WorkflowHeaders
  • Global
  • Step context keys, such as <StepName>.output
  • On the exception path, hasExceptionOccurred and exception

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

The following example shows an ordered if/else 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

Loop-back transitions are supported, such as transitions that target an earlier step. Design loop-back transitions with explicit guards. You must use the following approach:
  • 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, against baseConfigSchema.json.
  • Siebel connectivity rules, including useCG with the correct URL field.
  • UI resource and loginpath dependency.
  • Domain configuration, domain-configurations/*.json, against integrationConfigSchema.json.
  • Integration path format, including whether the path contains nested paths after /integrations/<id>.
  • Required externalDsl.
  • Required externalREST and outboundEventSchema.
  • 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.
For the merged configuration check, merged apigen must contain at least one of the following:
  • resources
  • integrations

Additional Integration Checks

The pipeline enforces the following checks for integration scripts and reusable functions:

  • Each scripts/*.js file must contain exactly one executeTransformationScript function.
  • Script files must not contain extra function declarations.
  • .js file names in jsonata-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.json under apigen.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 transformationSpec file resolvable under the domain transformation-spec folders.
  • Ensure that every restSpec alias exists in apigen.externalREST.
  • Ensure that every queue alias exists in apigen.outboundEvents.
  • Optionally validate the configuration before packaging by running one of the following commands:
    ./gen.sh –codegen
    or
    gen.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.integrations to define integration endpoint paths. Each key is an integration endpoint path in this format openintegration/v1.0/integration/<name>.

    Each integration entry includes:
    • Required externalDsl
    • Optional resources.externalREST[]
    • Optional resources.inboundEventRegistration

      Example:

      {
        "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>.externalDsl
      • apigen.externalREST.<alias> for RESTOutbound.restSpec
      • apigen.outboundEvents.<alias> for EventPublish.queue
    • apigen.externalREST:

      Use apigen.externalREST to define external REST aliases used by RESTOutbound.restSpec in the DSL.

      Each alias requires:
      • baseURL
      • authentication
      Supported authentication modes are:
      • basic, with username and password.

      • oidc-client-credentials, with client-id, client-secret, identity-uri, scope, and optional oidc-flow.

    • apigen.outboundEvents:

      Use apigen.outboundEvents to define outbound event aliases used by EventPublish.queue in 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.json from the template. Use the root file openint-deploy/integrations_template.json as a starter template when you create a domain configuration.

      To create integration.json :

      1. Copy integrations_template.json to integration-configurations/<Domain>/domain-configurations/integration.json
      2. Replace placeholder map keys, such as #Unique System Name, with real aliases.
      3. Replace placeholder values with domain-specific values.
      4. Remove template-only guidance fields, such as #Map and #Mandatory.
      5. For each apigen.externalREST.<alias>.authentication, configure exactly one authentication mode:
        • basic
        • oidc-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"
              }
            }
          }
        }
        

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>

Each integration entry requires externalDsl.

The optional resources.externalREST[] entries require:

  • spokesystem
  • describe
  • openAPIFilepath

The optional resources.inboundEventRegistration entry requires:

  • topic
  • partitions
Sample:
{
  "$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[].transformationSpec
  • inputSpecification.transformation[].transformationSpec
  • response.<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, or ar.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.

Example content:
{
  "status": {
    "A": "Approved",
    "R": "Rejected"
  }
}
Example JSONata expression:
$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.

Use translated mappings when:
  • 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

When openint-spec-validator runs, it validates:
  • config.json against baseConfigSchema.json.
    • Domain configuration files against integrationConfigSchema.json.
    • The merged config to ensure it contains at least one of apigen.resources or apigen.integrations.
    • Referenced External DSL files for semantic and schema correctness.
    • Script function contracts in scripts/.
    • Reusable function file name uniqueness across selected domains.
Validation failure details are written to:
  • openint-deploy/failed_config_openapi_keys.txt
  • openint-deploy/failed_external_dsls.txt

Integration Configuration Checklist

Before you run the pipeline, verify the following items:

  1. Add the domain in config.json under apigen.integration-domains.
  2. Create or update domain-configurations/integration.json.
  3. Ensure every externalDsl file exists in external-dsl/.
  4. Ensure every RESTOutbound.restSpec alias exists in apigen.externalREST.
  5. Ensure every EventPublish.queue alias exists in apigen.outboundEvents.
  6. Ensure every transformationSpec file exists under jsonata-configurations/transformation-spec/.
  7. Keep reusable function file names unique across selected domains.