# Change data with config modifiers

When exchanging data between systems, you don’t always get data exactly the way you want it. A <u>**config modifier**</u> solves this by allowing you to create conditional rules that automatically change a data payload. Whether you need to add a missing value, move a field to a different location, or delete sensitive information, config modifiers provide the flexibility to reshape data to meet your unique needs.

## Config operations

Several operations run during log processing, but config operations are the fundamental part of data exchange. [Learn about operations](/basics/data-exchange-with-redox/operations-for-data-processing). 

First, we create <u>**base configs**</u>, which contain instructions for converting data to and from the appropriate format, based on a subscription’s settings. 

You can create <u>**config modifiers**</u>, which are custom instructions for processing incoming or outgoing data. Usually, the input payload is output immediately after Redox applies a base config. 

Config modifiers might be independent, but they’re typically applied on top of a Redox base config. 

> **Confidential data in config modifiers**
>
> The contents of a config modifier might contain confidential data, like personal health information (PHI). Because of that, the contents are only visible to the organization that manages the config modifier. 
>
> If your organization doesn’t own the config modifier, you’ll see its name, flavor, and status without the contents in the operation details of log inspector.

## Common use cases for config modifiers

Config modifiers can help with many use cases. You’ll usually find opportunities to use config modifiers during implementation testing if you or your connection don’t receive data you expect. 

<details>
<summary>Use case 1: Hardcode a specific field</summary>

Different sites expect different things. You can hardcode fields and values so that your connection always gets the required data. For example, you might expect a certain document ID type or sending facility code in every message.

<u>Scenario</u>: You’re receiving a `PatientAdmin` data model from your connection. 

<u>Problem</u>: Your connection (i.e., source system) isn’t populating the MSH.4 (i.e., `FacilityCode`) segment. Your system expects the sending facility code in `Meta.FacilityCode`. 

<u>Goal</u>: Populate the `FacilityCode` with a specific value. In this case, you know the code should always be `acme-123`.

<u>Input payload</u>: In this input payload, you see the facility code is missing from the `Meta` object.

**Example: Input payload for hardcoding a field**

```json
{
  "Meta": {
    "DataModel": "PatientAdmin",
    "EventType": "Arrival"
  }
}
```

<u>**Selector**</u>: First, define where you want the config modifier to populate a value.

**Example: Selector for hardcoding a field**

```json
$.Meta.FacilityCode
```

<u>**Schema**</u>: Next, build your schema to hardcode the `FacilityCode` value on each `PatientAdmin` message from this source feed with this keyword:

- `constant`: Since you want to output the same value on each message, you need to use the `constant` keyword. [Learn about constant](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/constant).

**Example: Config modifier schema for hardcoding a field**

```yaml
constant: acme-123
```

<u>Output payload</u>: This config modifier would result in the hardcoded `FacilityCode` value in the `Meta` object.

**Example: Output for hardcoding a field**

```json
{
  "Meta": {
    "DataModel": "PatientAdmin",
    "EventType": "Arrival",
    "FacilityCode": "acme-123"
  }
}
```

</details>

<details>
<summary>Use case 2: Populate fields with values from different segments</summary>

Different sites configure their messages differently, so data might be found in unusual places. Redox base configs account for most of these variations. But if a value is missing from the segment you expect, you could write a config modifier to pull that value from another segment. For example, your connection sends the time the visit starts in an unexpected segment.

<u>Scenario</u>: You receive a `Scheduling.New` message from your connection (i.e., the source system). 

<u>Problem</u>: Your system expects `VisitDateTime` to be populated with the time the visit starts, but in testing, you notice you’re receiving the time the visit ends. Also, the value isn’t in your preferred date-time format.

<u>Goal</u>: Populate the `VisitDateTime` from SCH 11.1 (the time the visit starts) instead of SCH.11.4 (the time the visit ends).

<u>Input payload</u>: In this input payload, the desired start time (`20240603165602`) is located at `SCH.11[0].1.1`.

**Example: Input payload for populating a field**

```json
{
  "SCH": {
    ...
    "11": [
      {
        "1": {
          "1": "20240603165602"
        },
        "2": {
          "1": ""
        },
        "3": "",
        "4": {
          "1": "20240603175602"
        }
      }
    ]
  }
}

```

<u>**Selector**</u>: First, define where you want the config modifier to populate a value.

**Example: Selector for populating a field**

```json
$.Visit.VisitDateTime
```

<u>**Schema**</u>: Next, build your schema to retrieve the value at SCH 11.1 and reformat it with these keywords: 

- `use`: You need to access the initial HL7v2 payload, which is outside the scope of the selector path. That means you need to include `use`. [Learn about use](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/use).
- `get`: You need to define where to get the value from to populate the selector path. 
- `plugin`: You need the date-time value to be in ISO-8601 format, so you need to use a plugin to reformat. [Learn about plugin](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/plugin).
  - `name`: Use the `date-time` plugin to format the value.
  - `action`: To reformat the incoming value into ISO-8601, use `parse`.
  - `parameters.standard`: Identifies the current format of the incoming value, which is in HL7 format.

**Example: Config modifier schema for populating a field**

```yaml
use: initialPayload
get: SCH.11[0].1.1
plugin:
   name: date-time
   action: parse
   parameters:
      standard: HL7
```

<u>Output payload</u>: This config modifier results in using the desired start time in the correct format.

**Example: Output payload for populating a field**

```json
{
  ...
  "Visit": {
    ...
    "VisitDateTime": "2024-06-03T16:56:02.000Z"
  }
 }

```

</details>

<details>
<summary>Use case 3: Account for inconsistent messaging</summary>

Sometimes a site is inconsistent with their own message formatting. A site might populate a value in one field in some messages but leave it blank or populate a different field for other messages. This can happen if your connection handles IDs and codes differently based on the visit or order type.

<u>Scenario</u>: Your connection sends a Visit ID in one segment for some types of visits, but in a different segment for other types of visits. 

<u>Problem</u>: Sometimes the input payload looks like Example 1, and sometimes it looks like Example 2. Redox handles the visit ID correctly for Example 1. But in Example 2, Redox uses `null` for the visit ID because it’s not where we expect.

<u>Goal</u>: Populate visit ID regardless of the visit type.

<u>Input payload</u>: These input payloads show the different locations visit ID might be. 

**Example: Input payload 1 for accounting for inconsistent messaging**

```json
{
  ...
  "PV1": {
    ...
    "19": {
      "1": "1234"
    }
  }
}
```

**Example: Input payload 2 for accounting for inconsistent messaging**

```json
{
  ...
  "PV1": {
    ...
    "50": {
      "1": "1234"
    }
  }
}
```

<u>**Selector**</u>: First, define where you want the config modifier to output a value.

**Example: Selector for accounting for inconsistent messaging**

```json
$.Visit.VisitNumber
```

<u>**Schema**</u>: Next, build your schema to look for visit ID depending on whether PV1.19.1 is populated or not with these keywords: 

- `use`: You need to access the initial HL7v2 payload, which is outside the scope of the selector path. That means you need to include `use`. [Learn about use](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/use).
- `if`: The action to take is a conditional decision. That means you need to include `if` to define the logic for each condition. [Learn about if](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/if).
  - `operator`: First, Redox should check that the value exists, so you should enter `all`. [Learn about operator](https://docs.redoxengine.com/permalink/2sG9WePgS0JG03JoQqB3BL/#operator).
  - `terms`: Next, Redox should check whether PV1.19.1 exists, so that value is our singular term. [Learn about terms](https://docs.redoxengine.com/permalink/2sG9WePgS0JG03JoQqB3BL/#terms).
    - `get`: Define where to get the value from to populate the selector path. [Learn about get](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/get).
  - `then`: Define what should happen when the `if` scenario is true. In this case, use PV1.19.1 if it exists. [Learn about then](https://docs.redoxengine.com/permalink/2sG9WePgS0JG03JoQqB3BL/#then-else).
    - `get`: If PV1.19.1. exists, retrieve its value. [Learn about get](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/get).
  - `else`: Define what should happen when the `if` scenario isn’t true. In this case, use PV1.50.1 if PV1.19.1 doesn’t exist. [Learn about else](https://docs.redoxengine.com/permalink/2sG9WePgS0JG03JoQqB3BL/#then-else). 

**Example: Config modifier schema for accounting for inconsistent messaging**

```yaml
use: initialPayload
if:
  operator: all
  terms:
    - get: PV1.19.1
  then:
    get: PV1.19.1
  else:
    get: PV1.50.1
```

<u>Output payload</u>: This config modifier results in populating the visit ID, regardless of whether PV1.19.1 is populated or not.

**Example: Output payload for accounting for inconsistent messaging**

```json
{
  ...
  "Visit": {
    ...
    "VisitNumber": "1234"
  }
}
```

</details>

<details>
<summary>Use case 4: Remove characters from a text string</summary>

Sometimes a site can’t parse or receive data you have in its existing format. If the data format is incompatible, it might return an error or the site won’t receive important data.

<u>Scenario</u>: Your connection doesn’t accept underscores for the Observation codes under `OBX.3.1`.

<u>Problem</u>: We can’t simply use the `text` plugin for `replace` where we replace all the underscores with an empty string because it will return as `undefined`.

<u>Goal</u>: Remove the underscores under every Observation code (`OBX.3.1`)

<u>Input payload</u>: In this input payload, you see the text string with extra underscore (`_`) characters. 

**Example: Input payload for removing characters from a text string**

```json
  "PATIENT_RESULT": [
    {
      "ORDER_OBSERVATION": [
        {
          ...
          "OBSERVATION": [
            {
              ...
              "OBX": {
                ...
                "3": {
                  "1": "STD_DEV_SMBG",
                  "2": "Standard deviation across SMBG values in 14 days",
                  "3": null
                }
              }
            }
          ]
        }
      ]
    }
  ]
```

<u>**Selector**</u>: First, define which text string you want to remove characters from.

**Example: Selector for removing characters from a text string**

```json
$.PATIENT_RESULT[*].ORDER_OBSERVATION[*].OBSERVATION[*].OBX.3.1
```

<u>**Schema**</u>: Next, build your schema to look for the unnecessary characters and remove from the text string with these keywords: 

- `pipe`: You need to use the output of the first keyword action as the input of the second. [Learn about pipe](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/pipe).
- `plugin:` Plugins are common actions you can leverage for your schema. 
  - `text-split`: The text plugin is for manipulating string values. The split action removes the underscore (`_`) characters. [Learn about the text plugin](https://docs.redoxengine.com/permalink/4r50wuxhs82bzn2BU9l03H/#plugin-text-formatting).
  - `array-join`: The array plugin is for manipulating array values. The join action combines the text string that was split after removing the underscore (`_`) characters. [Learn about the array plugin](https://docs.redoxengine.com/permalink/4r50wuxhs82bzn2BU9l03H/#plugin-arrays).

**Example: Config modifier schema for removing characters from a text string**

```yaml
pipe:
  - plugin:
      name: text
      action: split
      parameters:
        separator: _
  - plugin:
      name: array
      action: join
      parameters:
        separator: ''
```

<u>Output payload</u>: This config modifier results in removing the extra underscore (\_) characters from `OBX.3.1`.

**Example: Output payload for removing characters from a text string**

```json
  "PATIENT_RESULT": [
    {
      "ORDER_OBSERVATION": [
        {
          ...
          "OBSERVATION": [
            {
              ...
              "OBX": {
                ...
                "3": {
                  "1": "STDDEVSMBG",
                  "2": "Standard deviation across SMBG values in 14 days",
                  "3": null
                }
              }
            }
          ]
        }
      ]
    }
  ]

```

</details>

## Config modifier parts

There are three significant parts to build when you’re setting up a config modifier. [Learn how to set up a config modifier](/how-to-use-redox/change-data-with-config-modifiers/set-up-config-modifiers).

<details>
<summary>1. Flavor</summary>

A config modifier can either write new data to or delete existing data from a payload. Usually, the output of applying a Redox base config serves as the input payload for a config modifier. 

Each config modifier has a specific <u>**flavor**</u>, or type. Currently, we support two flavors:

- The <u>**`Delete`**</u> flavor allows you to remove specific parts of a payload.
- The <u>**`Put`**</u> flavor allows you to write data—either replacing existing data or creating new data—to specific parts of a payload.

</details>

<details>
<summary>2. Selector</summary>

Config modifiers specify a selector or JSON path that points to the part(s) of a payload that you want to create, replace, or delete. [Learn how to choose or write selectors](/how-to-use-redox/change-data-with-config-modifiers/choose-or-write-config-modifier-selectors). 

A <u>**config modifier link**</u> is specific to the following:

- selector path
- subscription
- event type(s)
- processing location

If multiple config modifiers have the _same_ selector path, they _can’t_ be linked to the same subscription, event type(s), and processing location.

If multiple config modifiers have _different_ selector paths, they _can_ be linked to the same subscription, event type(s), and processing location. During execution, the output from the first config modifier to process becomes the input for the second, and so on.

</details>

<details>
<summary>3. Schema (for Put flavors only)</summary>

For <u>`Put`</u> flavors, there’s also a schema with instructions for how to build or replace data at the specified selector. The schema is built with Redox keywords. 

One config modifier can create, replace, or delete values or fields at one selector or path at a time. However, the path value might be an array with multiple values. You must create a config modifier for every selector you want to alter in a payload. 

[Learn how to build a schema. ](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema)

</details>

![A diagram shows a Put flavor, a selector that determines the field path to act upon, and a schema built of multiple keywords to define the actions to take to produce the output.](https://images.ctfassets.net/cl3wt5ehhnlv/15fX0DDjiwZmwhOcGpaCHg/f3855f032ca78f69a2c33928462a9160/Config-modifier-parts-put-flavor.png)

*Config modifier parts: Put flavor*

![A diagram shows a Delete flavor with a selector that determines the field path to delete to produce the output.](https://images.ctfassets.net/cl3wt5ehhnlv/49d1W2967nF6vzkhQ2mL8H/974fa5bcdf0e510a1b6bd7abc8e29980/Config-modifier-parts-delete-flavor.png)

*Config modifier parts: Delete flavor*

## AI assistant for config modifiers

We provide an AI-powered assistant, <u>**Config Modifier Assistant**</u>, to help you build a config modifier schema with natural-language prompts. But you'll find it helpful to review our build guide to understand how Redox keywords work. [Learn how to build a schema. ](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema)

## Linking to log stages

To run a config modifier, you must link it to the correct:

1. subscription
2. event type(s) within that subscription
3. log stage, or <u>**processing location**</u>

You can link config modifiers to inbound or outbound data to most log stages ([learn about log stages](https://docs.redoxengine.com/permalink/790exE7anSFdJdupyjnidt/#processing-stages-and-operations)), and so can your connection. [Learn how to set up a config modifier](/how-to-use-redox/change-data-with-config-modifiers/set-up-config-modifiers). 

### Processing order

If a subscription has multiple config modifiers linked to it, you can set the processing order of when the config modifiers should run. \<Learn how to set the processing order\>.

> **Processing order of one subscription**
>
> Processing order is scoped to individual subscriptions. Meaning, if you change the processing order of one subscription, it doesn't affect the processing order of another, even if they share config modifiers. 

## Changes based on conditions

Config modifiers are schemas with keywords that define how to alter data based on certain criteria. Think of them like IF / THEN statements. If the conditions of the schema aren’t met, the config modifier isn’t applied to a log. If a config modifier is applied, there may be changes either to the shape of data, individual values, or both. 

> **Config modifier vs. translation set**
>
> Both config modifiers and translation sets can alter specific values in a payload.
>
> When should you use a config modifier versus a translation set?
>
> - A <u>translation set</u> maps a list of values from one code set to another. It’s useful if you have lots of values you want to change based on different code sets used by different systems. This is a static mapping that looks for a particular value and translates it to a corresponding value. [Learn about translation sets](/how-to-use-redox/create-translation-sets-and-links).
> - A <u>config modifier</u> contains flexible instructions based on conditions. For example, you could map a specific value to another _only if_ another specified field is present. Essentially, a config modifier allows you to define conditional or fallback behavior. Also, you can only define instructions for values at one field path at a time. If you wanted to change lots of values in different locations, you’d have to create a config modifier for each one.

## Multiple input payloads

A config modifier can have two input payloads: 

1. JSON version of the original request or response
2. Output from a previous operation in log processing

This means you can define a config modifier that reads a value from the original payload even if that value is removed during a previous operation. The config modifier can recreate it in the processed payload at the linked processing stage. 

![A diff view of input and output payloads shows what changed before and after the operation executed.](https://images.ctfassets.net/cl3wt5ehhnlv/4lyHXt5xSjge6DgrYoUPbB/51218886bfe3c6e3a59aaa723bfbb632/Logs-log-inspector-diff-view.png)

*Input and output payloads*

## Promoting config modifiers

During implementation, you can build and test a config modifier in a staging environment. Once you’re confident it works, you can promote it to production. 

Promoting an asset saves you time and avoids introducing errors by having to rebuild it in a different environment. [Learn how to promote assets](/how-to-use-redox/copy-promote-or-restore-assets).

## Restoring config modifiers

Every time you edit a config modifier, you create a new version of the asset. If you run into errors or unexpected outcomes after editing, you can restore to a different version to help troubleshoot and find where any errors were introduced. [Learn how to restore assets](/how-to-use-redox/copy-promote-or-restore-assets). 

## Articles in this section

- [Set up config modifiers](/how-to-use-redox/change-data-with-config-modifiers/set-up-config-modifiers)
- [Choose or write config modifier selectors](/how-to-use-redox/change-data-with-config-modifiers/choose-or-write-config-modifier-selectors)

## [Build a config modifier schema](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema)

Dive into our reference guide for how to use keywords to build a config modifier schema.

- [omit](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/omit)
- [constant](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/constant)
- [references](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/references)
- [use](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/use)
- [get](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/get)
- [properties](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/properties)
- [if](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/if)
- [concat](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/concat)
- [switch](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/switch)
- [pipe](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/pipe)
- [merge](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/merge)
- [prefer](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/prefer)
- [items](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/items)
- [default](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/default)
- [plugin](/how-to-use-redox/change-data-with-config-modifiers/build-a-config-modifier-schema/plugin)
