# plugin

## Definition

In a config modifier schema, use `plugin` to define a bundle of functionality to produce a value. You can use one of these sub-keywords to construct a plugin:

| **Sub-keyword** | **Notes** |
| --- | --- |
| `name` | Defines the name of the plugin to apply. |
| `action` | Specifies the action to perform with this plugin. |
| `parameters` | Lists individual operations for a given `plugin.action`. |

## Order of execution

This keyword executes in the following order:  

1. `omit`
2. `constant`
3. `references`
4. `use`
5. `get`
6. Mutually exclusive keywords at this level:
   - `properties` 
   - `if` 
   - `concat` 
   - `switch` 
   - `pipe` 
   - `merge` 
   - `prefer` 
   - `items`
7. `default`
8. **`plugin`**

## Common plugins

<details>
<summary>Plugin: Dates with time </summary>

Bundles functionality for handling date values with time. This is referenced as `name: date-time`.

The array options are:

- `now`
- `parse`
- `render`

Review examples for each below. 

#### `now`

Generates the current `DateTime` and then renders the output.

##### Required parameters

| **Parameter** | **Notes** |
| --- | --- |
| `standard: string` (mutually exclusive with `custom`) | A named identifier for the format of the input. The default is `ISO`. [Learn about accepted formats](https://docs.redoxengine.com/permalink/4r50wuxhs82bzn2BU9l03H/#accepted-formats). |
| `custom: string` (mutually exclusive with `standard`) | A custom-defined format for how to parse the input (ex: `yyyy MM/dd HH:mm:ss`). [Learn about accepted formats](https://docs.redoxengine.com/permalink/4r50wuxhs82bzn2BU9l03H/#accepted-formats). |

##### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `timeZone: string` | The time zone of the input. [See possible time zone values](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). The default is `UTC`. If the input already includes an offset or time zone information then this parameter is unused. |

##### Example

You have a `Notes` message that doesn’t populate `Note.ServiceDateTime`, which usually maps to TXA.4.1.  Instead you can map either from `Note.DocumentationDateTime` if it exists, and if not, Redox can generate the current time into a string with the date-time plugin and `now` action.

**Example: Now input**

```json
{
  "Note": {
      ...
      "DocumentationDateTime": "2025-11-26T06:25:46.868381Z"
  },
}
```

**Example: Now selector for date-time plugin**

```json
$.TXA.4.1
```

**Example: Now in config modifier for date-time plugin**

```yaml
prefer:
- use: initialPayload
  get: Note.DocumentationDateTime
  plugin:
    name: date-time
    action: render
    parameters:
      standard: HL7
      timeZone: America/Los_Angeles
- plugin:
    name: date-time
    action: now
    parameters:
      standard: HL7
      timeZone: America/Los_Angeles
```

**Example: Now output for date-time plugin**

```json
{
  "TXA": {
    "2": "Behavioral Health Response Service Outreach",
    "4": {
      "1": "20251125222546"
    },
    ....
  },
}
```

#### `parse`

Identifies how to read an incoming `date-time` value; outputs an `ISO-8601` string.

##### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `standard: string` (mutually exclusive with `custom`) | A named identifier for the format of the input. The default is `ISO`. [Learn about accepted formats](https://docs.redoxengine.com/permalink/4r50wuxhs82bzn2BU9l03H/#accepted-formats). |
| `custom: string` (mutually exclusive with `standard`) | A custom-defined format for how to parse the input (ex: `yyyy MM/dd HH:mm:ss`). [Learn about accepted formats](https://docs.redoxengine.com/permalink/4r50wuxhs82bzn2BU9l03H/#accepted-formats). |
| `timeZone: string` | The time zone of the input. [See possible time zone values](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). The default is `UTC`. If the input already includes an offset or time zone information then this parameter is unused. |
| `outputTimeZone: string` | The time zone of the output. The default is `UTC`. |

##### Example

You need to map either OBR.7.1 or OBR.6.1 to the `Order.CollectionDateTime` in an `Order.New` message ([review the Redox Order schema](https://docs.redoxengine.com/permalink/order-new)). However, the OBR.7.1 and OBR.6.1 date-times are in HL7v2 format and we need them to be converted into ISO format. You can do this with the `date-time` plugin and the `parse` action. You can pass a `standard` parameter of `HL7` to indicate that the input format is `HL7`.

**Example: Parse input for date-time plugin**

```json
{
  "ORDER": [
    {
      ...,
      "ORDER_DETAIL": {
        "OBRRQDRQ1RXOODSODT_SUPPGRP": {
          "OBR": {
            "1": "1",
            "2": {
              "1": "7502027492",
              "2": "EPC"
            },
            "3": {
              "1": "1070331"
            },
            "4": {
              "1": "CAR755",
              "2": "HOLTER MONITOR (BARDY) 3 TO 7 DAYS MAIL OUT",
              "3": "BARDYEAP"
            },
            "5": "R",
            "6": {
              "1": "20250625090558"
            },
            ...
          }
        }
      }
    }
  ]
}
```

**Example: Parse selector for date-time plugin**

```json
$.Order.CollectionDateTime
```

**Example: Parse in config modifier for date-time plugin**

```yaml
use: initialPayload
if:
  operator: none
  terms:
    - get: ORDER[0].ORDER_DETAIL.OBRRQDRQ1RXOODSODT_SUPPGRP.OBR.7.1
  then:
    get: ORDER[0].ORDER_DETAIL.OBRRQDRQ1RXOODSODT_SUPPGRP.OBR.6.1
  else:
    get: ORDER[0].ORDER_DETAIL.OBRRQDRQ1RXOODSODT_SUPPGRP.OBR.7.1
plugin:
  name: date-time
  action: parse
  parameters:
    standard: HL7
```

**Example: Parse output for date-time plugin**

```json
{
  "Order": {
    ...
    "CollectionDateTime": "2025-06-25T09:05:58.000Z"
  }
}
```

#### `render`

Reads an `ISO-8601` string and outputs into the specified format.

##### Required parameters

| **Parameter** | **Notes** |
| --- | --- |
| `standard: string` (mutually exclusive with `custom`) | A named identifier for the format of the input. The default is `ISO`. [Learn about accepted formats](https://docs.redoxengine.com/permalink/4r50wuxhs82bzn2BU9l03H/#accepted-formats). |
| `custom: string` (mutually exclusive with `standard`) | A custom-defined format for how to parse the input (ex: `yyyy MM/dd HH:mm:ss`). [Learn about accepted formats](https://docs.redoxengine.com/permalink/4r50wuxhs82bzn2BU9l03H/#accepted-formats). |

##### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `timeZone: string` | The time zone of the input. [See possible time zone values](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). The default is `UTC`.  If the input already includes an offset or time zone information then this parameter is unused. |

##### Example

You need to map the `authoredOn` property in the `ServiceRequest` resource in a FHIR message to OBR.7.1. Since FHIR date-times are in ISO, you need to change the format that HL7v2 specs format. You can do this with the `date-time` plugin and the `render` action, which takes in an ISO input and outputs it to your desired format. 

For this case, you should set the parameter `standard` to `HL7`. You also pass a parameter of `timeZone` to indicate what time zone offset you’d like to apply since the input is in UTC time.

**Example: Render input for date-time plugin**

```json
    {
      "fullUrl": "https://fhir.redoxengine.com/fhir-sandbox/ServiceRequest/47842e584c94471c8c2de382b4c3ce9f",
      "resource": {
        "resourceType": "ServiceRequest",
        "identifier": {
          "value": "HAI_ISRN_20251124184000189",
          "system": "urn:oid:1.2.840.114350.1.13.12345.1.7.2.798268"
        },
        "requester": {
          "type": "Practitioner",
          "reference": "https://fhir.redoxengine.com/fhir-sandbox/Practitioner/35ce589e33c9431fa0a85304e0aedf90"
        },
        "authoredOn": "2025-11-24T18:40:00Z",
        "note": [
          {
            "text": "TVT"
          }
        ]
      }
    },
```

**Example: Render selector for date-time plugin**

```json
$.PATIENT_RESULT[0].ORDER_OBSERVATION[0].OBR.7.1
```

**Example: Render in config modifier for date-time plugin**

```yaml
references:
  authoredOn:
    use: initialPayload
    get: entry
    plugin:
      name: array
      action: find
      parameters:
        match:
          resource.resourceType: ServiceRequest
use: authoredOn
get: resource.authoredOn
plugin:
  name: date-time
  action: render
  parameters:
    standard: HL7
    timeZone: America/New_York
```

**Example: Render output for date-time plugin**

```json
{
  "PATIENT_RESULT": [
    {
      "ORDER_OBSERVATION": [
        {
          "NTE": [
            {
              "3": [
                "TVT"
              ]
            }
          ],
          "OBR": {
            ...,
            "7": {
              "1": "20251124134000"
            }
          },
          ...
        }
       }
      ]
    }
  ]
}
```

</details>

<details>
<summary>Plugin: Dates</summary>

Bundles functionality for handling date values. This is referenced as `name: date`.

The array options are:

- `now`
- `parse`
- `render`

Review examples for each below. 

#### `now`

Generates the current `date` and then renders the output.

##### Required parameters

| **Parameter** | **Notes** |
| --- | --- |
| `standard: string` (mutually exclusive with `custom`) | A named identifier for the format of the input.  [Learn about accepted formats](https://docs.redoxengine.com/permalink/4r50wuxhs82bzn2BU9l03H/#accepted-formats). |
| `custom: string` (mutually exclusive with `standard`) | A custom-defined format for how to parse the input (ex: `yyyy MM/dd`). [Learn about accepted formats](https://docs.redoxengine.com/permalink/4r50wuxhs82bzn2BU9l03H/#accepted-formats). |

##### Example

**Example: Now input**

```json
{
  "Note": {
      ...
      "DocumentationDateTime": "2025-11-26T06:25:46.868381Z"
  },
}
```

**Example: Now in config modifier for date plugin**

```yaml
plugin:
  name: date
  action: now
  parameters:
    standard: HL7
```

**Example: Now output for date plugin**

```json
"20220729"
```

#### `parse`

Identifies how to read an incoming `date` value.

##### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `standard: string` (mutually exclusive with `custom`) | A named identifier for the format of the input. The default is `ISO`. [Learn about accepted formats](https://docs.redoxengine.com/permalink/4r50wuxhs82bzn2BU9l03H/#accepted-formats). |
| `custom: string` (mutually exclusive with `standard`) | A custom-defined format for how to parse the input (ex: `yyyy MM/dd`). [Learn about accepted formats](https://docs.redoxengine.com/permalink/4r50wuxhs82bzn2BU9l03H/#accepted-formats). |

##### Example

You want to map the Guarantor’s date of birth from the HL7v2 message. Since the input format is in HL7, you need to use the `date` plugin with the `parse` action while passing in the parameter of `standard` and setting it to HL7. The `parse` action outputs the input similar to the output of `date-time` without timestamps.

**Example: Parse input for date plugin**

```json
{
  "PATIENT": {
    ...
    "INSURANCE": [
      {
        ...
        "GT1": [
          {
            ...
            "8": {
              "1": "19460228"
            },
            "9": "female",
            "11": {
              "1": "1"
            }
          }
        ]
      },
      ...
    }
  }
}
```

**Example: Parse selector for date plugin**

```json
$.Visit.Insurances[*].Insured.DOB
```

**Example: Parse in config modifier for date plugin**

```yaml
use: initialPayload
get: PATIENT.INSURANCE[0].GT1[0].8.1
plugin:
  name: date
  action: parse
  parameters:
    standard: HL7
```

**Example: Parse output for date plugin**

```json
{
  ...
  "Visit": {
    ...
    "Insurances": [
      {
        ...
        "Insured": {
          ...,
          "DOB": "1946-02-28"
        }
      }
    ]
  }
}
```

#### `render`

Identifies how to create an output `date` value.

##### Required parameters

| **Parameter** | **Notes** |
| --- | --- |
| `standard: string` (mutually exclusive with `custom`) | A named identifier for the format of the input.  [Learn about accepted formats](https://docs.redoxengine.com/permalink/4r50wuxhs82bzn2BU9l03H/#accepted-formats). |
| `custom: string` (mutually exclusive with `standard`) | A custom-defined format for how to render the input (ex: `yyyy MM/dd`). [Learn about accepted formats](https://docs.redoxengine.com/permalink/4r50wuxhs82bzn2BU9l03H/#accepted-formats). |

##### Example

You might have an incoming message with a Clinical Info object with the date formatted like `yyyyMMdd`, but you need the output to be formatted to `MM/dd/yyyy`. The date is associated with the Clinical Info object with a Description of `Start date`. You can find the object that matches, then convert the Value into the expected date format.

**Example: Render input for date plugin**

```json
{
  ...
  "Order": {
    "ApplicationOrderID": "534-120225",
    "ClinicalInfo": [
      ...
      {
        "Abbreviation": null,
        "Code": "RECSTDTC1",
        "Codeset": null,
        "Description": "Start date",
        "Notes": [
        ],
        "Units": null,
        "Value": "20251202"
      }
    ]
    ...
  }
}
```

**Example: Render selector for date plugin**

```json
$.Order.ClinicalInfo[*]
```

**Example: Render in config modifier for date plugin**

```yaml
if:
  operator: equals
  terms:
    - get: Description
    - constant: Start date
  then:
    merge:
      - {}
      - properties:
          Value:
            get: Value
            plugin:
              name: date
              action: render
              parameters:
                custom: MM/dd/yyyy
  else:
    comment: do nothing
```

**Example: Render output for date plugin**

```json
{
  ...
  "Order": {
    "ApplicationOrderID": "534-120225",
    "ClinicalInfo": [
      ...
      {
        "Abbreviation": null,
        "Code": "RECSTDTC1",
        "Codeset": null,
        "Description": "Start date",
        "Notes": [
        ],
        "Units": null,
        "Value": "12/02/2025"
      }
    ],
    ...
  }
}
```

</details>

<details>
<summary>Plugin: Social Security numbers</summary>

Bundles functionality for handling Social Security number values. This is referenced as `name: ssn`.

#### `format`

Formats a string into a Social Security number in either of these formats: `xxx-xx-xxxx` and `xxxxxxxxx`. Any leading or trailing whitespace is trimmed and non-numeric characters are removed.

> **No validation**
>
> Validation of a “correct” Social Security number isn't performed. A valid shape but invalid content (ex: `000-12-3456`) won't be rejected.

##### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `dashes: boolean` | Controls if the output is rendered with or without dashes. If not specified, the default is `true`. |

##### Example

You’re receiving a response message from Verato’s API in which the Social Security number is a full string without dashes. However, you need it to match Redox data model, which includes dashes.

**Example: Format input for ssn plugin**

```json
{
  ...
  "entry": [
    {
      "resource": {
        "resourceType": "Patient",
        "identifier": [
          {
            "value": "999679966",
            "system": "http://hl7.org/fhir/sid/us-ssn"
          },
          {
            "value": "3Y67hJYUopQywm8frKLGBf",
            "assigner": {
              "display": "tissuehealth.restore_first_health_1959743"
            }
          }
        ],
        ...
      }
      ...
    }
  ]
}
```

**Example: Format selector for ssn plugin**

```json
$.entry[?(@.resource.resourceType=="Patient")].resource.identifier
```

**Example: Format in config modifier for ssn plugin**

```yaml
items:
  if:
    operator: equals
    terms:
      - get: system
      - constant: http://hl7.org/fhir/sid/us-ssn
    then:
      get: value
      plugin:
        name: ssn
        action: format      
    else:
      comment: change nothing
```

**Example: Format output for ssn plugin**

```json
{
  ...
  "entry": [
    {
      "resource": {
        "resourceType": "Patient",
        "identifier": [
          {
            "value": "999-67-9966",
            "system": "http://hl7.org/fhir/sid/us-ssn"
          },
          {
            "value": "3Y67hJYUopQywm8frKLGBf",
            "assigner": {
              "display": "tissuehealth.restore_first_health_1959743"
            }
          }
        ],
        ...
      }
      ...
    }
  ]
}
```

</details>

<details>
<summary>Plugin: Phone numbers </summary>

Bundles functionality for handling phone number values. This is referenced as `name: phone-number`.

#### `format`

Parses a string into a valid phone number format. This action returns undefined if unable to parse the input.

##### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `renderFormat: string` | Specifies the output to render. If not specified, the default is `e164`. [Learn about accepted formats](https://docs.redoxengine.com/permalink/4r50wuxhs82bzn2BU9l03H/#accepted-formats). |

##### Example

You want to take the input phone number  at every `PATIENT_RESULT[0].PATIENT.PID.13[*].1` and render it in `international` format (i.e., `+1 800-123-4567`) using the `phone-number` plugin. Once it’s converted to `international` format, you only want the 10 digits, not country code.

**Example: Format input for phone-number plugin**

```json
{
  ...
  "PATIENT_RESULT": [
    {
      ...
      "PATIENT": {
        "PID": {
          ...,
          "13": [
            {
              "1": "+16097811857",
              "2": "PRN",
              "3": "PH"
            },
            {
              "1": "+16094102648",
              "2": "PRS",
              "3": "CP"
            }
          ],
          ...
      }
    }
  ]
}
```

**Example: Format selector for phone-number plugin**

```json
$.PATIENT_RESULT[0].PATIENT.PID.13[*].1
```

**Example: Format in config modifier for phone-number plugin**

```yaml
pipe:
  - plugin:
      name: phone-number
      action: format
      parameters:
        renderFormat: international
  - plugin:
      name: text
      action: split
      parameters:
        separator: ' '
        getIndex: 1
```

**Example: Format output for phone-number plugin**

```json
{
  ...,
  "PATIENT_RESULT": [
    {
      ...,
      "PATIENT": {
        "PID": {
          ...,
          "13": [
            {
              "1": "609-781-1857",
              "2": "PRN",
              "3": "PH"
            },
            {
              "1": "609-410-2648",
              "2": "PRS",
              "3": "CP"
            }
          ],
          ...
        }
      }
    }
  ]
}
```

</details>

<details>
<summary>Plugin: Text formatting</summary>

Bundles functionality for manipulating text values. This is referenced as `name: text`.

The `text` options are:

- `lower-case`
- `replace`
- `split`
- `trim`
- `upper-case`

#### `lower-case`

Converts an input string to lower case.

There aren’t any required or optional parameters for `lower-case`.

##### Example

**Example: Lower-case input for text plugin**

```json
  "Extensions": {
    "gender-identity": {
      "string": "Male",
      "url": "https://api.redoxengine.com/extensions/gender-identity"
    }
  }
```

**Example: Lower-case selector for text plugin**

```json
$.Patient.Demographics.Extensions.gender-identity.string
```

**Example: Lower-case in config modifier for text plugin**

```yaml
plugin:
  name: text
  action: lower-case
```

**Example: Lower-case output for text plugin**

```json
  "Extensions": {
    "gender-identity": {
      "string": "male",
      "url": "https://api.redoxengine.com/extensions/gender-identity"
    },
```

#### `replace`

Identifies an input string value and replaces occurrences of a given search value with a new value.

> **Global replace**
>
> This is a global replace operation. All occurrences of the search value are replaced with the new value. 
>
> There's no attempt to trim or normalize whitespace. If you require that functionality, you'll first need to sanitize your input value with the `trim` operator. 

##### Required parameters

| **Parameter** | **Notes** |
| --- | --- |
| `newValue: string` | A string value that serves as the replacement value. If not specified, the plugin returns an `undefined` value. |

##### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `searchValue: string` | The value that `newValue` replaces. If not specified, this defaults to a single whitespace. |

##### Example

**Example: Replace input for text plugin**

```json
"identifier": [
  {
    "system": "urn:redox:1a359110-47eb-40f6-924c-1e67079574a4:wshmrn",
    "type": {
      "text": "WSHMRN"
    },
    "value": "050050184"
  },
  ...
],
```

**Example: Text plugin selector**

```json
$.entry[?(@.resource.resourceType=="Patient")].resource.identifier[*]
```

**Example: Replace in config modifier for text plugin**

```yaml
if:
  operator: all
  terms:
    - get: type.text
  then:
    if:
      operator: equals
      terms:
        - get: type.text
        - constant: WSHMRN
      then:
        merge:
          - {}
          - properties:
              type:
                properties:
                  text:
                    constant: MR
              system:
                get: system
                plugin:
                  name: text
                  action: replace
                  parameters:
                    newValue: mr
                    searchValue: wshmrn
      else:
        comment: do nothing
  else:
    comment: type.text does not exist, do nothing
```

**Example: Replace output for text plugin**

```json
"identifier": [
  {
    "system": "urn:redox:1a359110-47eb-40f6-924c-1e67079574a4:mr",
    "type": {
      "text": "MR"
    },
    "value": "050050184"
  },
  ...
],
```

#### `split`

Splits a string value on a supplied `separator` and returns the resulting string array. This optionally allows retrieving a specific value by index, returning only the string.

##### Required parameters

| **Parameter** | **Notes** |
| --- | --- |
| `separator: string` | A string value used to split the input string. |

##### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `getIndex: number` | A number that'll be used to retrieve a specific value using a zero-based index. |
| `fromEnd: boolean` | If `true`, the start index begins from the end of the array and retrieves the last value first. If specified, `getIndex` is required. If not specified, the default is `false`. |

##### Example

A good use case for `split` is if an HL7v2 message includes a string with `->` in the initial payload. For example, component 3 of each note in `ORDER_DETAIL.NTE[x]`. You can map the left value to the `Code` of a ClinicalInfo object and the right value to the `Value` of a ClinicalInfo object.

**Example: Split input for text plugin**

```json
      "ORDER_DETAIL": {
        "OBRRQDRQ1RXOODSODT_SUPPGRP": {
         ...
        },
        "NTE": [
          {
            "1": "1"
          },
          {
            "1": "2"
          },
          {
            "1": "3",
            "3": [
              "------------"
            ]
          },
          {
            "1": "4",
            "3": [
              "Do not delete - Department info for vendor: "
            ]
          },
          {
            "1": "5",
            "3": [
              "MERCY MEDICAL CENTER"
            ]
          },
          {
            "1": "6",
            "3": [
              "MERCY NONINVASIVE CARDIOLOGY"
            ]
          },
          {
            "1": "7",
            "3": [
              "701 10TH ST SE"
            ]
          },
          {
            "1": "8",
            "3": [
              "CEDAR RAPIDS IA 52403-1251"
            ]
          },
          {
            "1": "9",
            "3": [
              "Dept: 319-221-8500"
            ]
          },
          {
            "1": "10",
            "3": [
              "Loc: 319-398-6011"
            ]
          },
          {
            "1": "11",
            "3": [
              "------------"
            ]
          },
          {
            "1": "12",
            "3": [
              "Duration (days):->3"
            ]
          },
          {
            "1": "13",
            "3": [
              "Cardiac implant:->None"
            ]
          },
          {
            "1": "14",
            "3": [
              "Placement:->In Clinic"
            ]
          },
          {
            "1": "15",
            "3": [
              "Reason for exam:->CP"
            ]
          },
          {
            "1": "16",
            "3": [
              "Wear start date:->9/26/25"
            ]
          },
          {
            "1": "17",
            "3": [
              "Device applied by:->COLEMAN, DAVID T"
            ]
          },
          {
            "1": "18",
            "3": [
              "Vendor:->CAM - BardyDX"
            ]
          },
          {
            "1": "19",
            "3": [
              "Device serial number:->123"
            ]
          }
        ],
        "DG1": [
          {
            "1": "1",
            "2": "I10",
            "3": {
              "1": "R94.31",
              "2": "Abnormal electrocardiogram (ECG) (EKG)",
              "3": "I10"
            },
            "4": "Abnormal electrocardiogram (ECG) (EKG)"
          }
        ]
      }
```

**Example: Split in config modifier for text plugin**

```yaml
use: initialPayload
get: ORDER[0].ORDER_DETAIL.NTE
items:
  if:
    operator: includes
    terms:
      - get: 3[0]
      - constant: '->'
    then:
      pipe:
        - get: 3[0]
          plugin:
            name: text
            action: split
            parameters:
              separator: '->'
        - properties:
            Code:
              get: '0'
            Value:
              get: 1
    else:
      omit: true
```

**Example: Split output for text plugin**

```json
    "ClinicalInfo": [
      {
        "Code": "Duration (days):",
        "Value": "3"
      },
      {
        "Code": "Cardiac implant:",
        "Value": "None"
      },
      {
        "Code": "Placement:",
        "Value": "In Clinic"
      },
      {
        "Code": "Reason for exam:",
        "Value": "CP"
      },
      {
        "Code": "Wear start date:",
        "Value": "9/26/25"
      },
      {
        "Code": "Device applied by:",
        "Value": "COLEMAN, DAVID T"
      },
      {
        "Code": "Vendor:",
        "Value": "CAM - BardyDX"
      },
      {
        "Code": "Device serial number:",
        "Value": "123"
      }
    ]
```

#### `trim`

Removes leading and trailing whitespace from the input string.

###### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `normalizeWhitespace: boolean` | Indicates whether whitespace is converted. The default is `true`, which converts any whitespace within the input string to one character whitespace. For example, `Bob   Smith` becomes `Bob   Smith`. The `false` value doesn’t convert whitespace within the input string. For example, `Bob   Smith` stays the same. |

##### Example

In a FHIR message, the `Patient` resource contains `telecom` phone values that include the extension number and the word `ext.`. You only care about the 7-digit phone number, so you can use the `text` plugin with `split` to grab everything before `ext.`. However, you’re left with some whitespaces. Using the `text` plugin again with `trim` eliminates the trailing (and any leading) whitespace.

**Example: Trim input for text plugin**

```json
    {
      "fullUrl": "urn:uuid:3186e100-8de6-448a-b869-ea8ad2d444df",
      "resource": {
        "resourceType": "Patient",
        ...
        "telecom": [
          {
            "value": "(608) 833-1557 ext. 432",
            "use": "home",
            "system": "phone"
          },
          {
            "value": "(608) 630-4354 ext. 123",
            "use": "work",
            "system": "phone"
          }
        ],
        ...
      }
    },
```

**Example: Trim selector**

```json
$.entry[?(@.resource.resourceType=="Patient")].resource.telecom[?(@.system=="phone")].value
```

**Example: Trim in config modifier for text plugin**

```yaml
if:
  operator: includes
  terms:
    - {}
    - constant: ext.
  then:
    pipe:
      - plugin:
          name: text
          action: split
          parameters:
            separator: ext.
      - get: '0'
      - plugin:
          name: text
          action: trim
  else: {}
```

**Example: Trim output for text plugin**

```json
{
  "fullUrl": "urn:uuid:3186e100-8de6-448a-b869-ea8ad2d444df",
  "resource": {
    "resourceType": "Patient",
    ...
    "telecom": [
      {
        "value": "(608) 833-1557",
        "use": "home",
        "system": "phone"
      },
      {
        "value": "(608) 630-4354",
        "use": "work",
        "system": "phone"
      }
    ],
    ...
  }
},
```

#### `upper-case`

Converts an input string to upper case.

There aren’t any required or optional parameters for `upper-case`.

##### Example

**Example: Upper-case input for text plugin**

```json
  "Patient": {
   ...
    "Demographics": {
      ...
      "FirstName": "Apple",
      "IsDeceased": null,
      "IsHispanic": null,
      "Language": "en",
      "LastName": "Johnny",
      "MaritalStatus": null,
      "MiddleName": null,
      ...
    },
```

**Example: Upper-case selector**

```json
$.Patient.Demographics.FirstName
```

**Example: Upper-case in config modifier for text plugin**

```yaml
plugin:
  name: text
  action: upper-case
```

**Example: Upper-case output for text plugin**

```json
  "Patient": {
   ...
    "Demographics": {
      ...
      "FirstName": "APPLE",
      "IsDeceased": null,
      "IsHispanic": null,
      "Language": "en",
      "LastName": "Johnny",
      "MaritalStatus": null,
      "MiddleName": null,
      ...
    },
```

</details>

<details>
<summary>Plugin: Arrays</summary>

Bundles functionality for handling array values. This is referenced as `name: array`. 

The array options are:

- `filter`
- `find`
- `join`
- `last`
- `sort`
- `unique`
- `without`

Review examples for each below. 

#### `filter`

Returns an array of values that match the specified value. 

##### Required parameters

| **Parameter** | **Notes** |
| --- | --- |
| `match: string` | A string value used to compare to other values within an input array. |

##### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `partial: boolean` | The default value is `false`. Indicates that a partial match won’t be performed.  If set to `true`, performs a case-sensitive partial match for the specified value(s).  Some `array` actions accept a boolean `partial` parameter. When this is set to `true` the following rules are enacted: 1) The value of `parameters.match` can be a string value or an object (as makes sense for your input value). Non-string values will use exact matching. 2) If multiple key/value pairs are provided in `parameters.match` _and_ logic is used, each key/value pair must partially match. |

##### Example

**Example: Filter input for array plugin**

```json
    [
      {
        "ID": "2000746",
        "IDType": "EPI"
      },
      {
        "ID": "TEST123",
        "IDType": "MR"
      }
    ]
```

**Example: Filter in config modifier for array plugin**

```yaml
plugin:
  name: array
  action: filter
  parameters:
    match:
      IDType: EPI

```

**Example: Filter output for array plugin**

```json
  [
      {
        "ID": "2000746",
        "IDType": "EPI"
      }
  ],
```

#### `find`

Returns the first value that matches the specified value; otherwise, returns `undefined` if no match is found. 

##### Required parameters

| **Parameter** | **Notes** |
| --- | --- |
| `match: string` | A string value used to compare to other values within an input array.  `match` is only used along with `array/find` (and is required). |

##### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `partial: boolean` | The default value is `false`. Indicates that a partial match won’t be performed.  If set to `true`, performs a case-sensitive partial match for the specified value(s).  Some `array` actions accept a boolean `partial` parameter. When this is set to `true` the following rules are enacted: 1) The value of `parameters.match` can be a string value or an object (as makes sense for your input value). Non-string values will use exact matching. 2) If multiple key/value pairs are provided in `parameters.match` _and_ logic is used, each key/value pair must partially match. |

##### Example 1: Exact match

**Example: Find input for array plugin**

```json
  "Order": {
    ...,
    "ClinicalInfo": [
      ...,
      {
        "Code": "CAMID",
        "Codeset": null,
        "Description": "Serial number",
        "Value": "MTP",
        "Units": null,
        "Abbreviation": null,
        "Notes": []
      }
    ]
  }
```

**Example: Find selector for array plugin**

```json
$.Visit.Location.Facility
```

**Example: Find in config modifier for array plugin**

```yaml
pipe:
  - use: processedPayload
    get: Order.ClinicalInfo
    plugin:
      name: array
      action: find
      parameters:
        match:
          Code: CAMID
          Value: MTP
  - get: Value
```

**Example: Find output for array plugin**

```json
  "Visit": {
    ...,
    "Location": {
      "Type": null,
      "Facility": "MTP",
      "FacilityIdentifiers": [],
      "Department": "SNH CARDIO",
      "DepartmentIdentifiers": [],
      "Room": null,
      "Bed": null
    }
  },
```

##### Example 2: Partial match

You want to map `DocumentReference` resources that are the focus in the `MessageHeader` and are missing the `type`. You need to use `find` in conjunction with a partial match for `DocumentReference/` to find all the `DocumentReference` resources in the entry. You can grab the first `DocumentReference` resource that has `resource.content[0].attachment.title` populated and map it to `TXA.12.1`

**Example: Find / partial input for array plugin **

```json
  "entry": [
    {
      "resource": {
        "eventUri": "https://fhir.redoxengine.com/EventDefinition/DocumentReferenceCreate",
        "resourceType": "MessageHeader",
        "id": "PatientProgressDocumentReferenceMessageHeader",
        "source": {
          "name": "LucidAct Health Inc.",
          "endpoint": "28020876-0c46-435e-87d1-913e72e5dd08"
        },
        "focus": [
          {
            "reference": "DocumentReference/381168-PatientProgress-2025-09-01"
          }
        ]
      }
    },
    {
      "fullUrl": "urn:uuid:3b8c99e1-c84d-4a16-a620-9dd0f91c571c",
      "resource": {
        "resourceType": "Patient",
        ...
      }
    },
    {
      "fullUrl": "urn:uuid:2c4eba76-cfae-4f48-83f8-1c11cf35ba73",
      "resource": {
        "resourceType": "ServiceRequest",
        ...
      }
    },
    {
      "fullUrl": "urn:uuid:a0acbeed-f0db-4e6c-86c9-bcc566765b36",
      "resource": {
        "resourceType": "Practitioner",
        ...
      }
    },
    {
      "fullUrl": "urn:uuid:de56c63b-8e4a-4d47-b088-3883dbefe407",
      "resource": {
        "resourceType": "Practitioner",
        ...
      }
    },
    {
      "fullUrl": "urn:uuid:3ac75f6d-d37d-41ac-bcee-4be4bc30fc30",
      "resource": {
        "resourceType": "Condition",
        ...
      }
    },
    {
      "fullUrl": "urn:uuid:4e4645b2-258e-4f69-9cdc-2dde035e5b83",
      "resource": {
        "resourceType": "Condition",
        ...
      }
    },
    {
      "fullUrl": "https://api.redoxengine.com/fhir/R4/optum-tristate/Production/DocumentReference/381168-PatientProgress-2025-09-01",
      "resource": {
        "id": "381168-PatientProgress-2025-09-01",
        "resourceType": "DocumentReference",
        ...,
        "content": [
          {
            "attachment": {
              "contentType": "application/pdf",
              "title": "381168_CHARLES L_SANTAMARIA_1934-06-04_1205839255_LucidAct",
              "data":
              ...
            }
          }
        ],
        "subject": {
          "reference": "urn:uuid:3b8c99e1-c84d-4a16-a620-9dd0f91c571c"
        }
      }
    }
  ]
```

**Example: Find / partial selector for array plugin**

```json
$.TXA.12.1
```

**Example: Find / partial in config modifier for array plugin**

```yaml
references:
  documentReferenceId:
    comment: >-
      find all DocumentReference resources that are part of the MessageHeader
      focus
    pipe:
      - use: initialPayload
      - get: entry
      - plugin:
          name: array
          action: find
          parameters:
            match:
              resource.resourceType: MessageHeader
      - get: resource.focus
      - plugin:
          name: array
          action: filter
          parameters:
            match:
              reference: DocumentReference/
            partial: true
      - items:
          get: reference
          plugin:
            name: text
            action: split
            parameters:
              separator: DocumentReference/
              getIndex: 1
  documentReferenceEntries:
    pipe:
      - use: initialPayload
      - get: entry
      - items:
          if:
            operator: equals
            terms:
              - constant: DocumentReference
              - get: resource.resourceType
            then: {}
            else:
              omit: true
pipe:
  - use: documentReferenceEntries
  - comment: >-
      filter the DocumentReference array list to just the ones referenced in the
      MessageHeader focus field
    items:
      if:
        operator: includes
        terms:
          - use: documentReferenceId
          - get: resource.id
        then: {}
        else:
          omit: true
  - comment: >-
      only include DocumentReference entries where there is a value in
      resource.content[0].attachment.title
    items:
      if:
        operator: all
        terms:
          - get: resource.content[0].attachment.title
        then: {}
        else:
          omit: true
  - comment: >-
      if there are multiple DocumentReference entries that fit this criteria,
      just grab the first
    get: '0'
  - get: resource.content[0].attachment.title
```

**Example: Find / partial output for array plugin**

```json
  "TXA": {
    "1": 1,
    "12": {
      "1": "381168_CHARLES L_SANTAMARIA_1934-06-04_1205839255_LucidAct"
    },
    ...
  },
```

#### `join`

Creates a string from the contents of the array and the `separator`.

###### Required parameters

| **Parameter** | **Notes** |
| --- | --- |
| `separator: string` | A string value that’ll be inserted immediately after each element in the array, excepting the final value in the array. |

##### Example

A good use case of `join` is if you want to append the facility code to the `ID` when the `IDType` is “PI”.

**Example: Join input for array plugin**

```json
  "Meta": {
    ...,
    "FacilityCode": "2807"
  },
  ...
  "Patient": {
  "Identifiers": [
      ...,
      {
        "ID": "282089_2807",
        "IDType": "PI"
      }
    ]
  ...,
  }
```

**Example: Join selector for array plugin**

```json
$.Patient.Identifiers[?(@.IDType == 'PI')].ID
```

**Example: Join in config modifier for array plugin**

```yaml
pipe:
  - concat:
      - {}
      - use: initialPayload
        get: Meta.FacilityCode
  - plugin:
      name: array
      action: join
      parameters:
        separator: _
```

**Example: Join output for array plugin**

```json
"Patient": {
  "Identifiers": [
      ...,
      {
        "ID": "282089_2807",
        "IDType": "PI"
      }
    ]
  ...,
  }
```

#### `last`

Retrieves the last element in an array. 

There aren’t any required or optional parameters for `last`. 

**Example: Last input for array plugin**

```json
{
  ...,
  "PV1": {
    "2": "O",
    "3": {
      "1": "K.PT",
      "2": null,
      "3": null,
      "4": {
        "1": "SY.K"
      },
      "6": null
    }
    ...
  }
}
```

**Example: Last selector for array plugin**

```json
$.PV1.3.4.1
```

**Example: Last in config modifier for array plugin**

```yaml
references:
  facilityId:
    use: processedPayload
    get: PV1.3.4.1
pipe:
  - comment: >-
      these are the facilities where we just want to return whatever comes
      after the first "."
    constant:
      - CD
      - CR
      - SY
  - items:
      if:
        operator: equals
        terms:
          - use: facilityId
            plugin:
              name: text
              action: split
              parameters:
                separator: .
                getIndex: 0
          - {}
        then: {}
        else:
          omit: true
  - prefer:
      - plugin:
          name: array
          action: last
      - use: facilityId
```

**Example: Last output for array plugin**

```json
{
  ...
  "PV1": {
    "2": "O",
    "3": {
      "1": "K.PT",
      "2": null,
      "3": null,
      "4": {
        "1": "K"
      },
      "6": null
    }
    ...
  }
}
```

#### `sort`

Sorts the array as indicated.

This operator can sort both primitive and object arrays.

##### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `order: Array of Objects` | Directs how to sort the input array. If not specified, a primitive array is sorted in `asc` order. An object array isn’t sorted.  If `direction` isn’t specified, the array is sorted in `asc` order. If multiple directions are specified, they’re evaluated in order. For example, it might sort an array first by age, then by last name. If you specify any direction other than `asc` or `desc`, the order parameter is ignored and not applied. If any other directions are defined, they are also ignored. If `by` isn’t specified, a primitive array is sorted according to `direction`. An object array isn’t sorted. |

##### Example

A query returns a list of patients, but maybe you want the results ordered by the `modifyTimestamp` input field for each patient. To get this value, you should base it off the `initialPayload` and add a new `modifyTimestamp` converted to milliseconds to each `PotentialMatch`, since the response schema doesn’t include a timestamp. The matches can then be sorted.

Since this adds a new `modifyTimestamp` field to a potential match, you might want to create a `delete` config modifier to remove it after sorting the array of potential matches.

**Example: Sort input for array plugin**

```json
[
    {
      "id": "f0b57abb-1df5-408c-8b00-b5386af54e4d",
      "firstName": "John",
      "lastName": "Smith",
      "middleName": "",
      ...,
      "modifyTimestamp": "2023-04-06T05:47:13.18"
    },
    {
      "id": "4d6c0775-1e5b-4991-81a1-461f58954a94",
      "firstName": "John",
      "lastName": "Smith",
      "middleName": "W",
      ...,
      "modifyTimestamp": "2016-08-18T10:29:11.127"
    },
    {
      "id": "2f463e9b-2a37-4803-81f0-792a8553e391",
      "firstName": "John",
      "lastName": "Smith1",
      "middleName": "",
      ...,
      "modifyTimestamp": "2024-02-20T16:11:09.753"
    },
    {
      "id": "218e5def-f320-4229-926c-ec49d6992401",
      "firstName": "John1",
      "lastName": "Smith12",
      "middleName": "",
      ...,
      "modifyTimestamp": "2022-12-21T01:36:20.74"

    },
    {
      "id": "bd128e19-13cd-412a-bb3c-438f1813fbcd",
      "firstName": "John12",
      "lastName": "Smith123",
      "middleName": "",
      ...,
      "modifyTimestamp": "2022-12-21T01:39:20.817"
    },
    {
      "id": "264f1937-bdf8-4adc-b209-d11eac28d41c",
      "firstName": "John",
      "lastName": "Smithson",
      "middleName": "",
      ...,
      "modifyTimestamp": "2024-11-04T14:33:53.023"
    }
  ]
```

**Example: Sort selector for array plugin**

```json
$.PotentialMatches
```

**Example: Sort in config modifier for array plugin**

```yaml
references:
  potentialMatchesWithModify:
    use: initialPayload
    items:
      pipe:
        - references:
            modifyTimestamp:
              get: modifyTimestamp
              comment: convert to milliseconds so we can sort
              plugin:
                name: date-time
                action: render
                parameters:
                  standard: Milliseconds
          merge:
            - {}
            - properties:
                modifyTimestamp:
                  use: modifyTimestamp
pipe:
  - use: potentialMatchesWithModify
    plugin:
      name: array
      action: sort
      parameters:
        order:
          - by: modifyTimestamp
            direction: desc
```

**Example: Sort output for array plugin**

```json
  "PotentialMatches": [
    {
      "Demographics": {
        "DOB": "2000-11-15",
        "Sex": "F",
        "FirstName": "John",
        "LastName": "Smith",
        ...,
      }
    },
    {
      "Demographics": {
        "DOB": "1987-09-03",
        "Sex": "M",
        "FirstName": "John",
        "LastName": "Smith",
        "MiddleName": "W",
        ...,
      }
    },
    {
      "Demographics": {
        "DOB": "1998-03-08",
        "Sex": "M",
        "FirstName": "John",
        "LastName": "Smith1",
        ...
      }
    },
    {
      "Demographics": {
        "DOB": "1998-03-08",
        "Sex": "M",
        "FirstName": "John1",
        "LastName": "Smith12",
        ...,        
      }
    },
    {
      "Demographics": {
        "DOB": "1998-03-08",
        "Sex": "M",
        "FirstName": "John12",
        "LastName": "Smith123",
        ...,
      }
    },
    {
      "Demographics": {
        "DOB": "1988-02-01",
        "Sex": "U",
        "FirstName": "John",
        "LastName": "Smithson",
        ...,
      }
    }
  ],
```

#### `unique`

Returns an array of distinct values.

##### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `match: string` | A string value that’ll be used as the de-duplication key for a non-primitive array. If a primitive array, the value of `match` is ignored. If an object array, the value of `match` uses that object property value as the de-duplication key. |

##### Example

You’re receiving telecom information for a `Patient` resource that has duplicate values. You can use the plugin for `array` and `unique` to deduplicate the same telecom entries.

**Example: Unique input for array plugin**

```json
    {
      "fullUrl": "urn:uuid:2b9d8eb9-168e-4052-bcf4-874614ed9869",
      "resource": {
        ...
        "resourceType": "Patient",
        "telecom": [
          {
            "system": "phone",
            "use": "home",
            "value": "+12164445555"
          },
          {
            "system": "email",
            "value": "noilya.mese+testdelete11122025stagerx01@bighealth.com"
          },
          {
            "system": "phone",
            "use": "mobile",
            "value": "+12139245224"
          },
          {
            "system": "email",
            "use": "work",
            "value": "noilya.mese+testdelete11122025stagerx01@bighealth.com"
          }
        ]
      }
    }
```

**Example: Unique selector for array plugin**

```json
$.entry[?(@.resource.resourceType=="Patient")].resource.telecom
```

You need to use two plugin `array` actions: a) one to `sort` those telecom entries without a `use` to the bottom of the array to save the entry that has more data; and b) one to remove duplicates with the `unique` action.

**Example: Unique in config modifier for array plugin**

```yaml
pipe:
  - comment: sort to move any undefined "use" keys to the end
    plugin:
      name: array
      action: sort
      parameters:
        order:
          - by: use
  - comment: remove any duplicate "value" values
    plugin:
      name: array
      action: unique
      parameters:
        match: value
```

**Example: Unique output for array plugin**

```json
 [
    {
      "system": "phone",
      "use": "home",
      "value": "+12164445555"
    },
    {
      "system": "phone",
      "use": "mobile",
      "value": "+12139245224"
    },
    {
      "system": "email",
      "use": "work",
      "value": "noilya.mese+testdelete11122025stagerx01@bighealth.com"
    }
]
```

#### `without`

Returns an array of values that _don_’_t_ match the specified value. 

##### Required parameters

| **Parameter** | **Notes** |
| --- | --- |
| `match: string` | A string value used to compare to other values within an input array. |

##### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `partial: boolean` | The default value is `false`. Indicates that a partial match won’t be performed.  If set to `true`, performs a case-sensitive partial match for the specified value(s).  Some `array` actions accept a boolean `partial` parameter. When this is set to `true` the following rules are enacted: 1) The value of `parameters.match` can be a string value or an object (as makes sense for your input value). Non-string values will use exact matching. 2) If multiple key/value pairs are provided in `parameters.match` _and_ logic is used, each key/value pair must partially match. |

##### Example

The `Patient.Identifiers` array contains an ID that has an IDType of `TD-MR`. If you don’t want this included, you can filter it out with `without`.

**Example: Without input for array plugin**

```json
{
  ...
  "Patient": {
    ...,
    "Identifiers": [
      {
        "ID": "10605",
        "IDType": "TD-MR"
      }
    ],
    "Notes": [
    ]
  }
}

```

**Example: Without selector for array plugin**

```json
$.Patient.Identifiers
```

**Example: Without in config modifier for array plugin**

```yaml
plugin:
  name: array
  action: without
  parameters:
    match:
      IDType: TD-MR
```

Since there’s only one Identifier in the `Identifiers` array and that identifier has an IDType of `TD-MR`, `Patient.Identifiers` is removed.

**Example: Without output for array plugin**

```json
{
  ...
  "Patient": {
    ...
    "Notes": [
    ]
  }
}

```

</details>

<details>
<summary>Plugin: Uniform Resource Identifiers (URIs)</summary>

Bundles functionality for handling URI values. This is referenced as `name: uri`.

#### `encode`

Encodes a `uri` or `uriComponent`.

##### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `isComponent: boolean` | Indicates whether the underlying value should be interpreted as a full URI or just a URI component. |

##### Example

**Example: Encode input for uri plugin**

```json
"https://example.com/?x=шеллы"
```

**Example: Encode in config modifier for uri plugin**

```yaml
plugin:
  name: uri
  action: encode
```

**Example: Encode output for uri plugin**

```json
"https://example.com/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"
```

#### `decode`

Decodes a `uri` or `uriComponent`.

##### Optional parameters

| **Parameter** | **Notes** |
| --- | --- |
| `isComponent: boolean` | Indicates whether the underlying value should be interpreted as a full URI or just a URI component. |

##### Example

**Example: Decode input in uri plugin**

```json
"https://example.com/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"
```

**Example: Decode in config modifier for uri plugin**

```yaml
plugin:
  name: uri
  action: decode
```

**Example: Decode output for uri plugin**

```json
"https://example.com/?x=шеллы"
```

###### 

</details>

<details>
<summary>Plugin: Universally Unique Identifiers (UUIDs)</summary>

Bundles functionality for handling UUID or GUID values. This is referenced as `name: uuid`.

#### `generate`

Creates a version 4 UUID. [Learn about version 4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)). 

There aren’t any required or optional parameters for `generate`. 

##### Example

No input is needed for the UUID plugin. However, you could check an input payload if the generate action is conditional on whether a certain field or value is present. 

Let’s say you want to create a new FHIR `Organization` resource if `PATIENT[0].PV1.3.4.1` exists. A new FHIR resource should be added to the `entry` array. Typically, a new uuid for a FHIR resource is the `fullUrl` of the associated resource. To make it easy, you can use the `uuid` plugin with the `generate` action to generate a UUID value.

**Example: Generate input for uuid plugin**

```json
  "PATIENT": [
    {
      ...,
      "PV1": {
        "3": {
          "1": "HURHO",
          "2": "",
          "3": "",
          "4": {
            "1": "1084831"
          },
          "5": "",
          "6": "HHP DES MOINES HOSPICE"
        },
        ...
      }
    }
  ],
```

**Example: Generate selector for uuid plugin**

```json
$.entry
```

**Example: Generate in config modifier for uuid plugin**

```yaml
references:
  checkPV1:
    use: initialPayload
    get: PATIENT[0].PV1.3.4.1
if:
  operator: all
  terms:
    - use: checkPV1
  then:
    concat:
      - comment: original entry array
      - properties:
          fullUrl:
            pipe:
              - concat:
                  - constant: 'urn:uuid:'
                  - plugin:
                      name: uuid
                      action: generate
              - plugin:
                  name: array
                  action: join
                  parameters:
                    separator: ''
          resource:
            properties:
              resourceType:
                constant: Organization
              active:
                constant: 'true'
              name:
                use: checkPV1
  else:
    comment: do nothing
```

**Example: Generate output for uuid plugin**

```json
{
  ...
  "entry": [
    ...
    {
      "fullUrl": "urn:uuid:85b228a6-1799-4987-bc94-a56ff08401c1",
      "resource": {
        "active": "true",
        "name": "1084831",
        "resourceType": "Organization"
      }
    }
  ]
}
```

</details>

<details>
<summary>Plugin: Value conversions</summary>

Bundles functionality for converting from one value type to another. This is referenced as `name: convert`.

The array options are:

- `boolean-to-string`
- `number-to-string`
- `string-to-boolean`
- `string-to-number`

Review examples for each below. 

#### `boolean-to-string`

Converts a boolean value to its string equivalent. 

> **Supported conversions**
>
> - `true` to `'true`'
> - `false` to `'false`'
>
> If the input value isn't a boolean, then the response returns `undefined`. 
>
> Also note that either single or double quotes are supported for either of the string values. 

There aren’t any required or optional parameters for `boolean-to-string`. 

##### Example

A FHIR message has the `extension` valueBoolean in the `Patient` Resource. You might need to change this from boolean to a string so that it can be translated properly in your translation set before mapping it to the EHR API.

**Example: Boolean-to-string input**

```json
{
    "fullUrl": "urn:uuid:f70fad8c-2980-4e12-bfbf-23fe7ebc1f9b",
    "resource": {
      "extension": [
        {
          "url": "http://hl7.org/fhir/us/core/StructureDefinition/consent-to-call",
          "valueBoolean": true
        }
      ],
      "resourceType": "Practitioner"
      ...
    }
}
```

**Example: Boolean-to-string selector**

```json
$.entry[?(@.resource.resourceType=="Practitioner")].resource.extension
```

**Example: Boolean-to-string in config modifier**

```yaml
pipe:
  - plugin:
      name: array
      action: find
      parameters:
        match:
          url: "consent-to-call"
          partial: true
  - get: valueBoolean
    plugin:
      name: convert
      action: string-to-boolean
```

**Example: Boolean-to-string output**

```json
{
  "fullUrl": "urn:uuid:f70fad8c-2980-4e12-bfbf-23fe7ebc1f9b",
  "resource": {
    "extension": [
      {
        "url": "http://hl7.org/fhir/us/core/StructureDefinition/consent-to-call",
        "valueBoolean": "true"
      }
    ],
    "resourceType": "Practitioner"
    ...
  }
}
```

#### `number-to-string`

Converts a numeric value to its string equivalent. 

> **Supported conversions**
>
> - `123` to `'123`'
> - `-100` to `'-100`'
> - `123.1` to `'123.1`'
> - `9007199254740992` to `'9007199254740992`'
>
> If the input value isn't numeric, then the response returns `undefined`. 
>
> Also note that either single or double quotes are supported for either of the string values. 

There aren’t any required or optional parameters for `number-to-string`. 

##### Example

You want to map `waitlistid` from an Athena API response into the `additional-identifier` Extension under the `Visits` array of a `Scheduling.Booked` message ([review the Redox `Scheduling` data model](https://docs.redoxengine.com/permalink/scheduling-booked)). Because it’s a number type, you need to convert it into a string since the `additional-identifier` schema requires `value` to be of string type.

**Example: Number-to-string input**

```json
{
  "appointmenttypeid": 641,
  "appointmentid": 12233807,
  "departmentid": 599,
  "providerid": 432,
  "waitlistid": 140178,
  "created": "09/02/2025 18:14:51",
  "patientid": 2928905,
  "priority": "HIGH",
  "note": "NP - HX OF URINARY RETENTION CATH PLACED"
}
```

**Example: Number-to-string selector**

```json
$.Visit.Extensions
```

**Example: Number-to-string in config modifier**

```yaml
references:
  root:
    pipe:
      - use: initialPayload
      - {}
if:
  operator: equals
  terms:
    - use: processedPayload
      get: Meta.EventType
    - constant: Booked
  then:
    properties:
      additional-identifier:
        properties:
          url:
            constant: https://api.redoxengine.com/extensions/additional-identifier
          identifier:
            use: root
            properties:
              value:
                get: waitlistid
                plugin:
                  name: convert
                  action: number-to-string
              type:
                constant: Athena Waitlist ID
              period:
                get: created
                plugin:
                  name: date-time
                  action: parse
                  parameters:
                    custom: MM/dd/yyyy hh:mm:ss
  else:
    omit: true
```

**Example: Number-to-string output**

```json
{
  ...
  "Visits": [
    {
      "Extensions": {
        "additional-identifier": {
          "identifier": {
            "period": "2025-09-02T18:14:51.000Z",
            "type": "Athena Waitlist ID",
            "value": "140178"
          },
          "url": "https://api.redoxengine.com/extensions/additional-identifier"
        }
      },
     ...
  ]
}
```

#### `string-to-boolean`

Converts a set of string values to their boolean equivalent. 

> **Supported conversions**
>
> - `'true`' to `true`
> - `'yes'` to `true`
> - `'no`' to `false`
> - `'false`' to `false`
> - `'null`' to `null`
>
> If the input value isn't a string or any of the values listed above, then the response returns `undefined`. 
>
> Also note that either single or double quotes are supported for any of the string values. 

There aren’t any required or optional parameters for `string-to-boolean`. 

##### Example

Athena’s response to an `Appointments` query returns a property of `appointments[].consenttoCall` with a string value of `true` or `false`. But you need it to be a boolean value of `true` or `false`. You can convert it with the `convert` plugin and `string-to-boolean` action. You can map this to the `extension` of `consent-to-call` in the `Patient` resource. This is already mapped to FHIR using Redox’s base config, but the below is an example showing how it can be appended to the `extension` array in addition to using the `convert` and `string-to-boolean` plugin.

**Example: String-to-boolean input**

```json
{
  "totalcount": 3,
  "appointments": [
    {
      "date": "03/12/2025",
      "copay": 40,
      "patient": {
        ...,
        "consenttocall": "true"
      },
      "duration": 30,
      "patientid": "1890491",
      ...
    },
    {
      "date": "03/12/2025",
      "copay": 0,
      "patient": {
        ...,
        "consenttocall": "false"
      },
      "duration": 30,
      "patientid": "2499392"
      ...,
    },
    {
      "date": "03/12/2025",
      "copay": 30,
      "patient": {
        ...,
        "consenttocall": "true"
      },
      "duration": 30,
      "patientid": "2295340",
      ...
    }
  ]
}
```

**Example: String-to-boolean selector**

```json
$.entry[?(@.resource.resourceType=="Patient")].resource.extension
```

**Example: String-to-boolean in config modifier**

```yaml
references:
   patientId:
    use: '@parent'
    get: identifier[0].value
pipe:
    - references:
        currentPatient:
            use: initialPayload
            get: appointments
            plugin:
                name: array
                action: find
                parametersIsProperty: true
                parameters:
                    properties:
                        match:
                            properties:
                                patientid:
                                    use: patientId
      concat:
        - {}
        - properties:
            url:
                constant: http://hl7.org/fhir/us/core/StructureDefinition/consent-to-call
            valueBoolean:
                use: currentPatient
                get: patient.consenttocall
                plugin:
                    name: convert
                    action: string-to-boolean
```

**Example: String-to-boolean output**

```json
"extension": [
  {
    "url": "http://hl7.org/fhir/us/core/StructureDefinition/consent-to-call",
    "valueBoolean": true
  },
  {
    "url": "http://hl7.org/fhir/us/core/StructureDefinition/consent-to-text",
    "valueBoolean": true
  },
  {
    "url": "http://hl7.org/fhir/us/core/StructureDefinition/consent-to-call",
    "valueBoolean": true
  }
],
```

#### `string-to-number`

Converts a string value to a numeric value. 

> **Supported conversions**
>
> - `'123`' to `123`
> - `'-100`' to `-100`
> - `'123.1`' to `123.1`
> - `'9007199254740992'` to `9007199254740992`
>
> If the input value isn't a string, then the response returns `undefined`. 
>
> Also note that either single or double quotes are supported for either of the string values. 

There aren’t any required or optional parameters for `string-to-number`. 

##### Example

The ADT message has an OBX array that might include information for a copay amount. You want to map this to the `copay` extension under `Insurances[*].Extensions`. However, the schema expects a numeric value, and you're receiving a string. Use the `convert` plugin with the `string-to-number` action to convert it to number type.

**Example: String-to-number input**

```json
  "OBX": [
    {
      "1": "1",
      "3": {
        "1": "Primary Co-Pay Type"
      },
      "5": [
        "Specialist Visit"
      ]
    },
    {
      "1": "2",
      "3": {
        "1": "TEXTS ALLOWABLE"
      },
      "5": [
        "Yes"
      ]
    },
    {
      "1": "3",
      "3": {
        "1": "Financial Responsibility -- Copay"
      },
      "5": [
        "30.00"
      ]
    }
  ],
```

**Example: String-to-number selector**

```json
$.Visit.Insurances[*].Extensions
```

**Example: String-to-number in config modifier**

```yaml
references:
  copayObx:
    use: initialPayload
    get: OBX
    plugin:
      name: array
      action: find
      parameters:
        match:
          '3.1': Financial Responsibility -- Copay
  copayTypeObx:
    use: initialPayload
    get: OBX
    plugin:
      name: array
      action: find
      parameters:
        match:
          '3.1': Primary Co-Pay Type
  visitInsurances:
    use: '@parent'
comment: check if Visit.Insurances exists. If not, do nothing
if:
  operator: all
  terms:
    - use: visitInsurances
    - use: copayObx
  then:
    merge:
      - {}
      - properties:
          copay:
            properties:
              url:
                constant: https://api.redoxengine.com/extensions/copay
              decimal:
                use: copayObx
                get: 5[0]
                plugin:
                  name: convert
                  action: string-to-number
              type:
                use: copayTypeObx
                get: 5[0]
  else:
    omit: true
```

**Example: String-to-number output**

```json
{
  ...
  "Visit": {
    ...
    "Insurances": [
      {
        ...
        "Extensions": {
          "copay": {
            "decimal": 30,
            "type": "Specialist Visit",
            "url": "https://api.redoxengine.com/extensions/copay"
          }
        }
      }
    ]
  }
}
```

</details>

## Accepted formats

Several of our plugins require you to specify a format. These are valid formats for various plugins. 

<details>
<summary>Phone numbers</summary>

##### Valid input formats 

| **Identifier** | **Output as E.164** |
| --- | --- |
| `+18001234567` | `+18001234567` (stays the same) |
| `800.123.4567` | `+18001234567` |
| `800-123-4567` | `+18001234567` |
| `800 123 4567` | `+18001234567` |
| `tel:+1-800-123-4567` | `+18001234567` |
| `8001234567` | `+18001234567` |
| `(800) 123-4567` | `+18001234567` |
| `18001234567` | `+18001234567` |
| `(800) 123-4567ext987` | `+18001234567` |

##### Explicit render formats 

| **Identifier** | **Example** |
| --- | --- |
| `e164` | `+18001234567` |
| `international` | `+1 800-123-4567` |
| `national` | `(800) 123-4567` |
| `rfc3966` | `tel:+1-800-123-4567` |
| `significant` | `8001234567` |

</details>

<details>
<summary>Dates with time</summary>

##### Standard

| **Identifier** | **Example(s)** |
| --- | --- |
| `HL7` | `20220729114900` `20220729114900.123` `20220729114900-0600` |
| `ISO` | `2016-05-25T09:08:34.123` `2016-05-25T09:08:34.123-06:00` |
| `HTTP` | `Sun, 06 Nov 1994 08:49:37 GMT` `Sunday, 06-Nov-94 08:49:37 GMT` `Sun Nov 6 08:49:37 1994` |
| `SQL` _We currently only render with offsets, not timezones_ | `2017-05-15 09:12:34` `2017-05-15 09:12:34.342-06:00` `2017-05-15 09:12:34.342 America/Los_Angeles` |
| `milliseconds` _Number of milliseconds since January 1, 1979 at midnight UTC/GMT_ | `1659095340000` |
| `seconds` _Number of seconds since January 1, 1979 at midnight UTC/GMT_ | `1659095340` |
| `RFC2822` _We currently only render date-times that look like_ `Fri, 29 Jul 2022 11:49:00 +0000` | `25 Nov 2016 13:23:12 GMT` `Fri, 25 Nov 2016 13:23:12 +0600` `25 Nov 2016 13:23 Z` |

##### Custom

> **Custom formats**
>
> A custom format is a build-your-own format. You can use commonly used tokens to build a format that suits your needs. These formats aren't recognized as industry-regulated, but the tokens are well known, all the same.
>
> You can use either a custom or standard format, not both.  

| **Token** | **Description** | **Example output** |
| --- | --- | --- |
| `S` | millisecond, no padding | `54` |
| `SSS` | millisecond, padded to three | `05` |
| `s` | second, no padding | `4` |
| `ss` | second, padded to two padding | `04` |
| `m` | minute, no padding | `7` |
| `mm` | minute, padded to two | `07` |
| `h` | hour in 12-hour time, no padding | `1` |
| `hh` | hour in 12-hour time, padded to two | `01` |
| `H` | hour in 24-hour time, no padding | `13` |
| `HH` | hour in 24-hour time, padded to two | `13` |
| `Z` | narrow offset | `+5` |
| `ZZ` | short offset | `+05:00` |
| `ZZZ` | techie offset | `+0500` |
| `z` | IANA zone | `America/New_York` |
| `a` | meridiem | `AM` |
| `d` | day of the month, no padding | `6` |
| `dd` | day of the month, padded to two | `06` |
| `EEE` | day of the week, as an abbreviated localized string | `Wed` |
| `EEEE` | day of the week, as an unabbreviated localized string | `Wednesday` |
| `M` | month as an unpadded number | `8` |
| `MM` | month as a padded number | `08` |
| `MMM` | month as an abbreviated localized string | `Aug` |
| `MMMM` | month as an unabbreviated localized string | `August` |
| `yy` | two-digit year, interpreted as \>1960 | `14` |
| `yyyy` | four-digit year | `2014` |
| `D` | localized numeric date | `9/6/2014` |
| `DD` | localized date with abbreviated month | `Aug 6, 2014` |
| `DDD` | localized date with full month | `August 6, 2014` |
| `DDDD` | localized date with full month and weekday | `Wednesday, August 6, 2014` |

</details>

<details>
<summary>Dates</summary>

##### Standard

| **Identifier** | **Example(s)** |
| --- | --- |
| `HL7` | `20220729` |
| `ISO` | `2016-05-25` |
| `SQL` | `2017-05-15` |

##### Custom

> **Custom formats**
>
> A custom format is a build-your-own format. You can use commonly used tokens to build a format that suits your needs. These formats aren't recognized as industry-regulated, but the tokens are well known, all the same.
>
> You can use either a custom or standard format, not both.  

| **Token** | **Description** | **Example output** |
| --- | --- | --- |
| `d` | day of the month, no padding | `6` |
| `dd` | day of the month, padded to two | `06` |
| `EEE` | day of the week, as an abbreviated localized string | `Wed` |
| `EEEE` | day of the week, as an unabbreviated localized string | `Wednesday` |
| `M` | month as an unpadded number | `8` |
| `MM` | month as a padded number | `08` |
| `MMM` | month as an abbreviated localized string | `Aug` |
| `MMMM` | month as an unabbreviated localized string | `August` |
| `yy` | two-digit year, interpreted as \>1960 | `14` |
| `yyyy` | four-digit year | `2014` |
| `D` | localized numeric date | `9/6/2014` |
| `DD` | localized date with abbreviated month | `Aug 6, 2014` |
| `DDD` | localized date with full month | `August 6, 2014` |
| `DDDD` | localized date with full month and weekday | `Wednesday, August 6, 2014` |

</details>
