# 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](https://zato.io/docs/dev/healthcare/hl7/to-fhir/index.html) preserves each one as a Basic resource whose extensions hold every populated field.

## What a Z-segment becomes {#what-a-z-segment-becomes}

```python
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:

```json
{
  "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.

## Standard segments that become Basic too {#standard-segments-that-become-basic-too}

Two kinds of standard segments take the same route as a Z-segment. One is a segment [without a mapping](https://zato.io/docs/dev/healthcare/hl7/to-fhir/resources/index.html) of its own, e.g. a UAC or a DSC, which maps to no other resource. The other is a segment that only enriches another resource and arrives without it - a PV2 in a message with no PV1, an RXR with no pharmacy segment before it, an AIS with no SCH. Rather than dropping the data, the conversion preserves the segment whole, with `code` naming the segment and one extension per field, in the same way as above.

Two Z-segments have mappings of their own and do not become Basic resources when their parent is present - ZBE, the IHE PAM movement segment, enriches the Encounter, and ZDS, the quasi-standard imaging segment, adds the study instance UID to the ServiceRequest.

## Setting the extension base URL {#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](https://zato.io/docs/dev/healthcare/hl7/to-fhir/config/index.html):

```ini
[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 {#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:

```json
{
  "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](https://zato.io/docs/dev/healthcare/hl7/to-fhir/codes/index.html) are also preserved as extensions.

## See also {#see-also}

- [Customizing code mappings](https://zato.io/docs/dev/healthcare/hl7/to-fhir/codes/index.html) - Unknown code values, also preserved as extensions
- [Configuration](https://zato.io/docs/dev/healthcare/hl7/to-fhir/config/index.html) - The extensions section that changes the base URL
- [What you get per message](https://zato.io/docs/dev/healthcare/hl7/to-fhir/resources/index.html) - Every segment-to-resource mapping, standard and custom alike

## Learn more {#learn-more}

- [Healthcare interface engine](https://zato.io/docs/dev/healthcare/) - Clinical messages, FHIR, conversion and operations
- [HL7 v2 parsing](https://zato.io/docs/dev/healthcare/hl7/v2/parsing/) - Messages as typed objects, with field access and validation
- [MLLP channels](https://zato.io/docs/dev/healthcare/hl7v2/mllp/) - Receiving and sending HL7 v2 over MLLP sockets
- [FHIR integrations](https://zato.io/docs/dev/healthcare/hl7/fhir/) - Read and write FHIR resources, with paths, bundles and extensions
- [HL7 v2 to FHIR](https://zato.io/docs/dev/healthcare/hl7/to-fhir/) - Converting v2 messages into FHIR bundles, codes and references included
- [EDIFACT](https://zato.io/docs/dev/healthcare/edifact/) - Parsing interchanges, dialects and the transports they arrive on
- [Transformation](https://zato.io/docs/dev/healthcare/transformation/) - One message in, another standard out, in ordinary Python
- [Audit log](https://zato.io/docs/dev/healthcare/audit-log.html) - Every message with its acknowledgment, searchable by patient identifier
- [AI in clinical interfaces](https://zato.io/docs/dev/healthcare/ai/) - Services calling LLMs and AI agents calling clinical services as tools
