HL7 Configuration
The HL7 configuration is a standard configuration object managed via the Configuration API. Within this framework, it is identified by its configuration type and consumed by the HL7 worker.
This document describes the structure and behavior of HL7 configurations and how they are used to transform incoming HL7 messages into FHIR resources at runtime.
Configuration Model Overview
An HL7 configuration is identified by a combination of tenant, and metadata. The transformation logic is defined declaratively in the content field.
Type
Identifies the configuration domain. HL7 configurations use: hl7
Scope
Identifies the configurations scope. Can be one of: global, organization, ward, role or user.
Name
Identifies the configurations name. This name is not needed for finding configurations.
TenantId
Identifies the tenant (e.g. hospital or system) this configuration belongs to. This field is mandatory and ensures proper routing and isolation of configurations. The fallback tenantId in the hl7 worker is mona-default
Meta
A flexible JSON object used for message-level matching. The HL7 worker reads the event type from the incoming message and selects the appropriate configuration based on these metadata filters.
Example:
{
"hl7_event": "ADT^A01"
}
content
Contains the ordered list of operations executed by the HL7 worker. Operations define how HL7 data is transformed into FHIR resources. See next section or click here.
Operation Model
HL7 transformations are defined as a sequence of operations. Operations are executed sequentially from top to bottom.
Each operation performs a specific task such as:
- creating a resource
- updating a resource
- loading an existing resource
- performing an upsert operation
export interface Operation {
type: OperationType;
options: OperationOptions;
storeAs?: string;
isCritical?: boolean;
hl7Segment?: {
hl7Type?: string;
iterate?: boolean;
};
}
Type
Defines the action executed by the HL7 worker. Current supported values:
createResource
updateResource
loadResource
upsertResource
Each operation type has specific option requirements. See operation-handlers for more information for each handler and examples.
Options
Operations define their configuration using the options object.
export interface OperationOptions {
fhirType: string;
mapping: MappingConfig;
createMapping: MappingConfig;
updateMapping: MappingConfig;
search: string;
}
Not every option is required for every operation. See details in the operation-handlers section.
FhirType
Specifies the FHIR resource type. Examples: Patient, Encounter, Observation.
Mapping/CreateMapping/UpdateMapping
Defines the transformation from HL7 fields to FHIR fields.
{
"gender": "{{PID-8|hl7Gender}}",
"birthDate": "{{PID-7|hl7Date}}"
}
Search
FHIR search query used to locate existing resources. Example:
identifier={{PID-3-1}}
StoreAs (optional)
Stores the resulting resource in the execution context so it can be reused by later operations.
storeAs: "patient"
Later usage:
Patient/%patient.id%
This behaves like a runtime variable shared between operations.
IsCritical (optional)
Controls error handling behavior.
| Value | Behavior |
|---|---|
| true | Processing stops if the operation fails |
| false | Processing continues |
This allows distinguishing between mandatory and optional operations. If not set, processing will continue after errors.
hl7Segment (optional)
Defines the HL7 segment or group that should trigger the operation.
{
"hl7Segment": {
"hl7Type": "OBX",
"iterate": true
}
}
| Field | Description |
|---|---|
| hl7Type | HL7 segment type (e.g. PID, PV1, OBX) |
| iterate | Execute the operation for every occurrence |
If iterate is true, the worker processes all matching segments.
Operation Handler
loadResource
Loads an existing resource using a FHIR search query. Required options:
- fhirType
- search
{
"type": "loadResource",
"storeAs": "patient",
"options": {
"fhirType": "Patient",
"search": "identifier={{PID-3-1}}"
}
}
createResource
Creates a new FHIR resource. Required options:
- fhirType
- mapping
Example:
{
"type": "createResource",
"storeAs": "patient",
"options": {
"fhirType": "Patient",
"mapping": {
"identifier[0].value": "{{PID-3-1}}",
"gender": "{{PID-8|hl7Gender}}",
"birthDate": "{{PID-7|hl7Date}}"
}
}
}
updateResource
Updates an existing FHIR resource. Typically used after a loadResource operation because it uses a context id. If you want to search and update for a resource in one step use the upsert resource handler.
- fhirType
- mapping
Example:
{
"type": "updateResource",
"storeAs": "patient"
"options": {
"fhirType": "Patient",
"mapping": {
"address[0].city": "{{PID-11-3}}"
}
}
}
UpsertResource
Performs a conditional create or update.
Execution logic:
- Execute search
- If resource exists → update using updateMapping
- If no resource exists → create using createMapping
Required options:
- fhirType
- search
- createMapping
- updateMapping
Example:
{
"type": "upsertResource",
"storeAs": "patient",
"options": {
"fhirType": "Patient",
"search": "identifier={{PID-3-1}}",
"createMapping": {
"identifier[0].value": "{{PID-3-1}}",
"gender": "{{PID-8|hl7Gender}}"
},
"updateMapping": {
"gender": "{{PID-8|hl7Gender}}"
}
}
}
Execution Semantics
Operations are processed sequentially.
Important rules:
- Later operations may reference previously stored resources
- Template expressions are resolved at runtime
- Failures respect the isCritical setting
Mapping Expressions
Mappings define how HL7 data is transformed into FHIR fields.
{
"gender": "{{PID-8|hl7Gender}}",
"status": "in-progress",
"subject.reference": "Patient/%patient.id%"
}
| Expression Type | Example |
|---|---|
| HL7 field | {{PID-3-1}} |
| transformer | {{PID-8}} |
| static value | "status": "final" |
| stored variable | "Patient/%patient.id%" |
Custom HL7 Transformers
Transformers convert HL7 values into valid FHIR values.
Usage
{{PID-8|hl7Gender}}
| Transformer | Description |
|---|---|
hl7Gender | HL7 gender FHIR gender |
hl7Date | HL7 date FHIR date |
hl7DateTime | HL7 timestamp ISO datetime |
hl7PatientClass | HL7 patient class FHIR encounter class |
toBoolean | Converts Y/N or 1/0 to boolean |
toNumber | Converts string (including , to . correction) to number. |
uppercase | Converts string to uppercase. |
lowercase | Converts string to lowercase. |
trim | Removes spaces at the beginning and end. |
Examples
Example with multiple operations
{
"content": {
"operations": [
{
"type": "createResource",
"options": {
"mapping": {
"gender": "{{PID-8|hl7Gender}}",
"name[0].family": "{{PID-5-1}}",
"name[0].given[0]": "{{PID-5-2}}",
"identifier[0].value": "{{PID-3-1}}",
"identifier[0].system": "{{PID-3-5}}"
},
"fhirType": "Patient"
},
"storeAs": "%patient%",
"isCritical": true
},
{
"type": "createResource",
"options": {
"mapping": {
"status": "in-progress",
"class.code": "{{PV1-2|hl7PatientClass}}",
"class.system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
"period.start": "{{PV1-44|hl7DateTime}}",
"subject.reference": "Patient/%patient.id%",
"identifier[0].value": "{{PV1-19-1}}",
"identifier[0].system": "{{PV1-19-4}}"
},
"fhirType": "Encounter"
},
"storeAs": "%encounter%",
"isCritical": false
}
]
},
"meta": {
"hl7_event": "ADT^A01"
},
"id": "85e50210-c27c-4eb0-94fc-267ecc557350",
"name": "ADT^A01^Default",
"scope": "global",
"scopeId": null,
"tenantId": "mona-default",
"type": "hl7",
"createdAt": "2026-03-10T10:53:12.458Z",
"createdBy": null,
"updatedAt": "2026-03-10T10:53:12.458Z",
"updatedBy": null,
"deletedAt": null,
"deletedBy": null,
"version": 1
},
In this example:
- First a
Patientresource is created - HL7 fields are mapped declaratively to FHIR elements
- The resulting resource is stored as
%patient% - Processing stops if this operation fails
- Second an
Encounterresource is created with the reference to the new created patient in the first step
Example with iterate
{
"content": {
"operations": [
{
"type": "loadResource",
"options": {
"search": "identifier={{PID-3-1}}",
"fhirType": "Patient"
},
"storeAs": "patient"
"isCritical": true
},
{
"type": "loadResource",
"options": {
"search": "identifier={{PV1-19}}",
"fhirType": "Encounter"
},
"storeAs": "encounter"
"isCritical": true
},
{
"type": "createResource",
"options": {
"hl7Type": "OBX",
"mapping": {
"status": "final",
"effectiveDateTime": "{{now}}",
"subject.reference": "Patient/%patient%.id",
"valueQuantity.code": "{{OBX-6-1}}",
"valueQuantity.unit": "{{OBX-6-2}}",
"code.coding[0].code": "{{OBX-3-1}}",
"encounter.reference": "Encounter/%encounter%.id",
"valueQuantity.value": "{{OBX-5|toNumber}}",
"valueQuantity.system": "http://unitsofmeasure.org",
"code.coding[0].system": "http://loinc.org",
"code.coding[0].display": "{{OBX-3-2}}"
},
"fhirType": "Observation",
"createEach": true
},
"segment": {
"hl7Type": "OBX",
"iterate": true
},
"isCritical": false
}
]
},
"meta": {
"hl7_event": "ORU^R01"
},
"id": "fd081de3-c151-49c5-98aa-09856ce379d1",
"name": "ORU^R01^Default",
"scope": "global",
"scopeId": null,
"tenantId": "mona-default",
"type": "hl7",
"createdAt": "2026-03-10T10:54:35.176Z",
"createdBy": null,
"updatedAt": "2026-03-10T10:56:54.144Z",
"updatedBy": null,
"deletedAt": null,
"deletedBy": null,
"version": 2
}
In this example:
- The patient must be loaded
- The encounter must be loaded
- For every OBX Segment an observation will stored. With the loaded patientId and the encounterId