HL7v2 to FHIR - configuration
Supply what messages do not carry - identifier systems, timezone, local code values and the extension base URL.
A FHIR server expects a few facts that an HL7v2 message never carries. Where the message names an assigning authority as MYHOSP, FHIR wants a globally unique URI for that system of identifiers. Where a timestamp arrives without a UTC offset, FHIR wants to know what timezone it was recorded in. And where a hospital uses its own local code values, FHIR wants the standard ones.
These are facts about your site rather than about any single message, which is why the conversion reads them from an .ini file - written once and shared by every message that names it. Every section and every key is optional, and msg.to_fhir() with no configuration at all works with the defaults described below.
Naming the file in code
The config argument is a string - either the name of an .ini file in the server's user-conf directory or a full path to a file:
# A file from the server's user-conf directory, without the extension
bundle = msg.to_fhir(config='hl7-fhir-demo')
# A full path, e.g. outside a server
bundle = msg.to_fhir(config='/path/to/my-mappings.ini')
to_fhir_dict and to_fhir_json accept the same argument. A parsed file is cached, so naming the same config with every message does not read the file again.
Where the files live
Every Zato server has a user-conf directory for your own configuration files - drop a file into <server>/pickup/incoming/user-conf/ and refer to it by its base name. A new server already contains a fully commented demo file, hl7-fhir-demo.ini, ready to copy and adjust:
# Settings for msg.to_fhir(config='hl7-fhir-demo') - each section and key is optional
# and msg.to_fhir() with no config at all uses the defaults described below.
# What kind of bundle to produce - transaction, batch or collection.
# The default is transaction.
[bundle]
type=transaction
# The timezone offset applied to HL7 date/time values that do not carry their own.
# The default is +00:00.
[datetime]
default_timezone=+00:00
# Maps assigning authorities from your HL7 messages to FHIR identifier system URIs.
# The authority is what your messages carry, e.g. in PID-3.4, and the system
# is the URI the resulting FHIR identifiers should use.
[identifiers]
[[patient_mrn]]
authority=MYHOSP
system=http://example.org/mrn
[[visit_number]]
authority=MYHOSP
system=http://example.org/visit
# Overrides or additions to the standard code mappings, one subsection per map.
# For instance, patient_class maps PV1-2 codes to FHIR encounter classes.
[codes]
[[patient_class]]
P=AMB
# Where extensions built from Z-segments and other unmapped data are published.
# The default is urn:zato:hl7v2:extension.
[extensions]
base_url=http://example.org/fhir/ext
Section reference
[bundle]
| Key | Default | Allowed values |
|---|---|---|
| type | transaction | transaction, batch, collection |
What each type means for the output is described in references and deduplication.
[datetime]
| Key | Default |
|---|---|
| default_timezone | +00:00 |
HL7 timestamps may state their own offset, e.g. 20260315101112+0100, and when they do, that offset wins. When a timestamp has a time part but no offset, default_timezone is appended to produce a valid FHIR dateTime. Date-only values, e.g. a birth date of 19800115, get no offset at all.
[identifiers]
Each [[subsection]] maps one assigning authority to an identifier system URI. The subsection name is a label of your choosing, the matching happens on the authority value:
With this in place, an identifier such as 12345^^^MYHOSP^MR in PID-3 produces:
{
"value": "12345",
"system": "http://example.org/mrn",
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "MR"
}
]
}
}
Both keys, authority and system, are required in every subsection. An authority the file does not mention falls back to urn:zato:hl7v2:authority:<name>, so identifiers are never lost - a configured URI replaces the placeholder. Authorities that have a universal ID of type ISO or UUID need no configuration - they become urn:oid:... and urn:uuid:... automatically.
[codes]
Each [[subsection]] overrides or extends one code mapping - the subsection name is the map's name and each line maps an HL7 code to the FHIR target code. See customizing code mappings for the map names and details.
[extensions]
| Key | Default |
|---|---|
| base_url | urn:zato:hl7v2:extension |
The base URL under which Z-segment extensions are published.
Strict validation
Configuration mistakes surface immediately, not as silently ignored settings. An unknown section, an unknown key, a missing required key or an invalid bundle type all raise an exception naming the file and the offending setting:
Unknown section `[bundles]` in `/path/to/my-mappings.ini`,
allowed: ['bundle', 'codes', 'datetime', 'extensions', 'identifiers']
See also
| Page | What it covers |
|---|---|
| Customizing code mappings | The map names behind the codes section and what unknown codes become |
| References and deduplication | What the transaction, batch and collection bundle types mean |
| Z-segments | The extensions published under the base URL set here |
Learn more
Schedule a meaningful demo
Book a demo with an expert who will help you build meaningful systems that match your ambitions
"We evaluated 12 integration platforms and Zato was the only one to score 100%."
Philip Zuñiga, Assistant Professor, University of the Philippines