HL7v2 to FHIR - Z-segments and extensions

Preserve custom Z-segment data instead of dropping it - each segment becomes a Basic resource with extensions holding every populated field.

Z-segments are the custom, site-defined segments of HL7v2 - ZPD, ZIN, ZBE and the other segments vendors define for data the standard does not cover. FHIR has no resource for them, so the conversion preserves each one as a Basic resource whose extensions hold every populated field.

What a Z-segment becomes

from zato.hl7v2 import parse_hl7

raw = (
    'MSH|^~\\&|SENDER|FACILITY|RECEIVER|FAC|20260315101112||ADT^A01^ADT_A01|CTL001|P|2.9\r'
    'PID|||12345^^^HOSP^MR||SMITH^JOHN^A||19800115|M\r'

    # A custom segment with a membership level and a renewal year
    'ZPD|GOLD|2026\r'
)

msg = parse_hl7(raw, validate=False)
bundle = msg.to_fhir()

print(msg.to_fhir_json(indent=2))

The ZPD segment produces this entry in the bundle:

{
  "resourceType": "Basic",
  "code": {
    "coding": [
      {
        "system": "urn:zato:hl7v2:extension/segment",
        "code": "ZPD"
      }
    ]
  },
  "extension": [
    {
      "url": "urn:zato:hl7v2:extension/ZPD/1",
      "valueString": "GOLD"
    },
    {
      "url": "urn:zato:hl7v2:extension/ZPD/2",
      "valueString": "2026"
    }
  ],
  "subject": {
    "reference": "urn:uuid:98e4f8aa-a5ad-5791-add1-66fd3afb4f83"
  }
}

In this entry:

  • The resource's code names the segment the data comes from - ZPD
  • Each populated field becomes one extension whose URL ends with the segment name and the field's position - .../ZPD/1 is ZPD-1, .../ZPD/2 is ZPD-2
  • Field values keep their HL7 wire form, so components stay separated with ^, repetitions with ~ and subcomponents with &
  • subject points at the Patient from the same bundle, so the custom data stays attached to the person it describes

A message may include any number of Z-segments and each becomes its own Basic resource, while a Z-segment with no populated fields produces nothing.

Setting the extension base URL

The default URLs are built under urn:zato:hl7v2:extension. To publish extensions under your own namespace, set base_url in the [extensions] section of the configuration file:

[extensions]
base_url=http://example.org/fhir/ext

With this file, the ZPD-1 extension URL becomes http://example.org/fhir/ext/ZPD/1 and the segment code system http://example.org/fhir/ext/segment.

Unmapped fields of standard segments

A populated field of a standard segment that has no FHIR equivalent is preserved too - not as its own Basic resource, but as an extension on the resource built from its segment. A county code in PID-12 appears on the Patient as:

{
  "url": "urn:zato:hl7v2:extension/unmapped/PID-12",
  "valueString": "MIDDLESEX"
}

The unmapped URLs are built under the same base URL, so the [extensions] setting above changes them as well. Unknown code values are preserved the same way.

See also

PageWhat it covers
Customizing code mappingsUnknown code values, preserved as extensions the same way
ConfigurationThe extensions section that changes the base URL
What you get per messageEvery segment-to-resource mapping, standard and custom alike

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