Enricher
Introduction
Enricher is a component that can be used for calling web services and returning their response or a part of it. This JSON can be returned as it is or "enriched" into another JSON. It is built into Automation Engine AKA Audit, but can also be used as a separate component in another systems.
Web service requirements
In order to be called by enricher the web service should match the following requirements:
- HTTP Web service
- Should return JSON as a response in the HTTP response Body
- Should accept the parameters if any in the following way:
- GET
- URL parameters specified as a query argument i.e. /api/resource?parameter=value
- URL parameters specified as a part of the URL path i.e. /api/resource/parametervalue
- POST - supports multiple parameter modes based on
contentType(query string when omitted, form fields forapplication/x-www-form-urlencoded, or JSON body forapplication/json); see POST requests and content types
- GET
it is not recommended by RESTful specifications to use POST for data retrieval, but it can be done in some circumstances
- The web service should be protected in one of the following way:
- with a static Bearer token that should be passed in "Authorization" Header of the request
- with a Bearer token that should be retrieved from an authorization service using OAuth 2.0 authorization protocol. In this case Authorization Server Url, CertificateThumbprint, ClientId and Required Scopes must be specified
- with a Bearer token that should be retrieved from an authorization service using OAuth 2.0 authorization protocol. In this case Authorization Server Url, ClientId, ClientSecret and Required Scopes must be specified.
Configuration in Automation Engine
When Enricher is used within Automation Engine (Audit), the configuration is entered in the Enricher configuration field of the Reporting System Parameters screen. The configuration is a JSON object with a top-level name identifier and an invokers array. Each entry in invokers represents one external service call.

{
"name": "JsonEnricher",
"invokers": [
{
"name": "enricher-policy-info",
"type": "http",
"url": "https://url-to-call.com/service",
"httpMethod": "GET",
"authorizationServerUrl": "https://login.microsoftonline.com/",
"oAuth2ClientId": "clientId123",
"oAuth2ClientSecret": "secretsecret",
"requiredScopes": [
"micro_scope"
],
"input": {
"parameters": [
{
"name": "claimNumber",
"type": "selector",
"value": "$.payload.claim.number"
}
]
},
"output": {
"resultSelector": "",
"injectAs": "$.policyInfo"
}
}
]
}Multiple invokers can be defined in the array — each one will be called independently and its result injected into the payload at the path specified by output.injectAs.
Examples
The examples below show individual invoker configurations. Each object belongs inside the invokers array of the top-level Enricher configuration shown above.
HTTP GET with static token authorization
{
"name": "weather",
"type": "http",
"url": "https://weather.nu/external_api",
"httpMethod": "GET",
"bearerToken": "b09e2254-6ade-4e44-9c98-25eefed5599a",
"input": {
"parameters": [
{
"name": "country",
"type": "selector",
"value": "$.address.country"
},
{
"name": "date",
"type": "selector",
"value": "$.date"
}
]
},
"output": {
"resultSelector": "",
"injectAs": "$.weather"
}
}HTTP GET with OAuth 2.0 authorization using Authorization server and certificate
{
"name": "weather",
"type": "http",
"url": "https://weather.nu/external_api",
"httpMethod": "GET",
"authorizationServerUrl": "https://oauth.weather.nu",
"oAuth2CertificateThumbprint": "1d4b45e90df21fce012c9a804a5b7c166326c6cf",
"oAuth2ClientId": "some_id",
"requiredScopes": [
"weather:read"
],
"input": {
"parameters": [
{
"name": "country",
"type": "selector",
"value": "$.address.country"
},
{
"name": "date",
"type": "selector",
"value": "$.date"
}
]
},
"output": {
"resultSelector": "",
"injectAs": "$.weather"
}
}HTTP GET with OAuth 2.0 authorization using Authorization server and client credentials flow
{
"name": "weather",
"type": "http",
"url": "https://weather.nu/external_api",
"httpMethod": "GET",
"authorizationServerUrl": "https://oauth.weather.nu",
"oAuth2ClientId": "weather-client",
"oAuth2ClientSecret": "RAcmIxj0Tsn3_-GZjp6OomL-xRxoae9kZHvx81zLNj8",
"requiredScopes": [
"weather:read"
],
"input": {
"parameters": [
{
"name": "country",
"type": "selector",
"value": "$.address.country"
},
{
"name": "date",
"type": "selector",
"value": "$.date"
}
]
},
"output": {
"resultSelector": "",
"injectAs": "$.weather"
}
}POST requests and content types
For httpMethod: POST, the optional contentType property controls how input parameters are passed to the service:
contentType | Parameters are sent as | Request body |
|---|---|---|
| (omitted) | URL query string, e.g. /api/resource?parameter=value | empty |
application/x-www-form-urlencoded | form fields in the body | parameter=value&other=value |
application/json | properties of a single JSON object, keyed by parameter name | {"parameter": "value"} |
| any other value | not sent | empty |
The value is matched case-insensitively and any parameters such as ; charset=utf-8 are ignored. Note that an unsupported content type does not fail the invocation — the request is simply sent with an empty body.
JSON request body
With contentType: application/json, each input parameter becomes a property of the request body object. This is the only mode where a parameter value may be a JSON object or array — both as a static value and as a selector resolving to an object in the payload.
{
"name": "address-verification",
"type": "http",
"url": "https://api.example.com/verify",
"httpMethod": "POST",
"contentType": "application/json",
"input": {
"parameters": [
{
"name": "address",
"type": "selector",
"value": "$.customer.address"
},
{
"name": "options",
"type": "value",
"value": { "strict": true, "maxResults": 5 }
}
]
},
"output": {
"resultSelector": "",
"injectAs": "$.addressVerification"
}
}Given a payload where $.customer.address is an object, the service receives:
{
"address": { "street": "Main Street 1", "city": "Copenhagen" },
"options": { "strict": true, "maxResults": 5 }
}Two rules govern null handling in the JSON body:
- A
selectorthat resolves to nothing omits the property from the body. - A
valueparameter explicitly set tonullemits the property with a JSONnull.
A source parameter is passed as a string property containing the whole original payload, and parameter names are used as property names verbatim. If several parameters share a name, the last one wins.
Conditional invocation
An invoker can be configured to skip execution when a specific condition is not met. This is useful in cases where, for example, an external service call should not be made for a particular claim type.
To enable this, add an invocationCondition property to the invoker configuration. The condition is evaluated against the payload sent to the Enricher. If it evaluates to false, the invoker is skipped.
Important: The condition value must be a string (not a JSON object), and object keys must be wrapped in single quotes (
').
The following example shows an invoker that is called only when the claim type is not GLA (glass) and PaintOrderTime is less than 78:
{
"name": "weather",
"type": "http",
"url": "https://weather.nu/external_api",
"httpMethod": "GET",
"authorizationServerUrl": "https://oauth.weather.nu",
"oAuth2ClientId": "weather-client",
"oAuth2ClientSecret": "RAcmIxj0Tsn3_-GZjp6OomL-xRxoae9kZHvx81zLNj8",
"requiredScopes": [
"weather:read"
],
"invocationCondition": "{'and': [{'!=': ['$.ClaimData.EventType', 'GLA']}, {'<': ['$.Estimate.PaintOrderTime', 78]}]}",
"input": {
"parameters": [
{
"name": "country",
"type": "selector",
"value": "$.address.country"
},
{
"name": "date",
"type": "selector",
"value": "$.date"
}
]
},
"output": {
"resultSelector": "",
"injectAs": "$.weather"
}
}Condition structure
Each condition is composed of an operator key, a JSON path to a value in the payload, and optionally a static value to compare against:
{'<operator>': ['$.Path.To.Value', <compareValue>]}Note: JSON paths are case-sensitive and must exactly match the field names in the payload.
Because operators serve as object keys, the same operator cannot appear twice at the same level. Use grouping instead:
// Incorrect — duplicate keys
{'and': [conditionA], 'and': [conditionB]}
// Correct — grouped under a single 'and'
{'and': [{'==': [conditionA]}, {'!=': [conditionB]}]}Supported operators
Logic and boolean
| Operator | Description | Example |
|---|---|---|
if | Ternary — returns second or third value based on first | "{'==': [{'if': [false, 'yes', 'no']}, 'no']}" |
== | Loose equality | "{'==': ['$.Report.Count', 2.0]}" |
=== | Strict equality (type-sensitive) | "{'===': [2, 2.0]}" → false |
!= | Not equal | "{'!=': ['$.Report.CasesCount', 0]}" |
!== | Strict not equal | |
! | True if value is falsy | "{'!': '$.Report.FirstCaseEver'}" → true when value is false |
!! | True if value is truthy | "{'!!': '$.Report.FirstCaseEver'}" → true when value is true |
or | True if at least one value is true | "{'or': ['$.Report.IsGlass', '$.Report.IsFirst']}" |
and | True only if all values are true | "{'and': ['$.Report.IsGlass', '$.Report.IsFirst']}" |
Numeric
| Operator | Description | Example |
|---|---|---|
>, >=, <, <= | Comparison | "{'<': ['$.Estimate.PaintOrderTime', 78]}" |
max, min | Maximum / minimum of an array | "{'==': [{'max': [1,2,3]}, '3']}" |
+, -, *, / | Arithmetic | "{'==': [{'+': [1,2,3,6,3]}, '15']}" |
% | Modulo |
Array and string
| Operator | Description | Example |
|---|---|---|
in (array) | True if value exists in the array | "{'in': ['$.ClaimData.EventType', ['GLA', 'Water', 'Theft']]}" |
in (string) | True if first string is a substring of the second | "{'in': ['Spring', 'Springfield']}" → true |
cat | Concatenates an array of strings | "{'==': [{'cat': ['Hello, ', 'World!']}, 'Hello, World!']}" |
missing | Returns keys missing from an object | |
missing_some | True if a minimum number of keys are present |
Using JSON paths as values
Any static value in a condition can be replaced with a JSON path. All paths are resolved to their actual payload values before the condition is evaluated.
"invocationCondition": "{'==': [{'+': ['$.Report.PaintPrice', '$.Report.WheelPrice', '$.Report.WindScreenPrice']}, '$.Report.TotalPrice']}"This invokes the enricher only if the sum of the three price fields equals the total price.
Sharing an output path between invokers
More than one invoker is allowed to target the same output.injectAs path. The intended use is a set of invokers gated by mutually exclusive invocationConditions, so that only one of them runs for any given payload — for example, calling a different external service depending on the claim type while writing the result to the same path.
{
"name": "JsonEnricher",
"invokers": [
{
"name": "personal-injury-info",
"type": "http",
"url": "https://services.example/personal-injury",
"httpMethod": "GET",
"invocationCondition": "{'==': ['$.case.caseType', 'personalInjury']}",
"input": { "parameters": [] },
"output": { "injectAs": "$.caseInfo" }
},
{
"name": "property-info",
"type": "http",
"url": "https://services.example/property",
"httpMethod": "GET",
"invocationCondition": "{'==': ['$.case.caseType', 'property']}",
"input": { "parameters": [] },
"output": { "injectAs": "$.caseInfo" }
}
]
}If, for a given payload, more than one invoker on a shared path actually runs, their results are composed in configuration order and the last invoker wins (last-writer-wins); the earlier results are discarded rather than merged. When this happens a warning is logged for each discarded invoker, naming the conflicting path and the invoker that took precedence, so a genuine collision is visible without failing the enrichment.
Tip: When several invokers share an
injectAspath, make sure theirinvocationConditions are mutually exclusive so that exactly one runs per payload. Otherwise the declaration order silently determines which result is kept.
Last updated on