Pure Elixir HL7 v2.x toolkit.
Schema-driven parsing, typed segment structs, programmatic message building, validation, and integrated MLLP transport.
Parsing
# Raw mode — canonical round-trip, delimiter-based
{:ok, raw} = HL7v2.parse(text)
# Typed mode — segments become structs
{:ok, msg} = HL7v2.parse(text, mode: :typed)Building
msg =
HL7v2.new("ADT", "A01", sending_application: "PHAOS")
|> HL7v2.Message.add_segment(%HL7v2.Segment.PID{...})
text = HL7v2.encode(msg)Acknowledgments
{:ok, typed} = HL7v2.parse(wire, mode: :typed)
msh = hd(typed.segments)
{ack_msh, msa} = HL7v2.ack(msh)MLLP Transport
{:ok, _} = HL7v2.MLLP.Listener.start_link(port: 2575, handler: MyHandler)
Summary
Functions
Builds an ACK (Application Accept) for the given MSH segment.
Encodes an HL7v2 message to wire format.
Fetches a value, returning {:ok, value} or {:error, reason}.
Gets a value from a typed message using a path string like "PID-5" or a %HL7v2.Path{} struct.
Gets a value from a typed message with a default.
Builds a new HL7v2 message. Shortcut for HL7v2.Message.new/3.
Parses an HL7v2 message from a binary string.
Converts a %HL7v2.RawMessage{} to a %HL7v2.TypedMessage{}.
Validates an HL7v2 typed message.
Functions
@spec ack( HL7v2.Segment.MSH.t(), keyword() ) :: {HL7v2.Segment.MSH.t(), HL7v2.Segment.MSA.t()}
Builds an ACK (Application Accept) for the given MSH segment.
Shortcut for HL7v2.Ack.accept/2.
Options
:text— optional text message for MSA-3:message_control_id— override the generated ACK message control ID
Examples
{ack_msh, msa} = HL7v2.ack(original_msh)
@spec encode(HL7v2.RawMessage.t() | HL7v2.Message.t() | HL7v2.TypedMessage.t()) :: binary()
Encodes an HL7v2 message to wire format.
Accepts:
%HL7v2.RawMessage{}— encodes directly%HL7v2.Message{}— converts to raw viaMessage.encode/1%HL7v2.TypedMessage{}— converts to raw viaTypedParser.to_raw/1, then encodes
Examples
wire = HL7v2.encode(raw_message)
wire = HL7v2.encode(builder_message)
wire = HL7v2.encode(typed_message)
@spec fetch(HL7v2.TypedMessage.t(), binary() | HL7v2.Path.t()) :: {:ok, term()} | {:error, atom()}
Fetches a value, returning {:ok, value} or {:error, reason}.
@spec get(HL7v2.TypedMessage.t(), binary() | HL7v2.Path.t()) :: term()
Gets a value from a typed message using a path string like "PID-5" or a %HL7v2.Path{} struct.
@spec get(HL7v2.TypedMessage.t(), binary() | HL7v2.Path.t(), term()) :: term()
Gets a value from a typed message with a default.
@spec new(binary(), binary(), keyword()) :: HL7v2.Message.t()
Builds a new HL7v2 message. Shortcut for HL7v2.Message.new/3.
Options
:sending_application— string or%HD{}:sending_facility— string or%HD{}:receiving_application— string or%HD{}:receiving_facility— string or%HD{}:message_control_id— string (default: auto-generated):processing_id— string (default:"P"):version_id— string (default:"2.5.1")
Examples
msg = HL7v2.new("ADT", "A01", sending_application: "PHAOS")
Parses an HL7v2 message from a binary string.
Options
:mode—:raw(default) or:typed:validate—trueto validate after parsing (defaultfalse). Requiresmode: :typed; silently ignored in:rawmode.:copy—trueto copy all parsed binaries (prevents GC reference to original message binary). Use when storing parsed messages long-term. Defaultfalse.
Examples
{:ok, msg} = HL7v2.parse("MSH|^~\\&|...")
{:ok, msg} = HL7v2.parse(text, mode: :typed, validate: true)
{:ok, msg} = HL7v2.parse(text, copy: true)
@spec type(HL7v2.RawMessage.t()) :: {:ok, HL7v2.TypedMessage.t()} | {:error, term()}
Converts a %HL7v2.RawMessage{} to a %HL7v2.TypedMessage{}.
Shortcut for HL7v2.TypedParser.convert/1.
Examples
{:ok, raw} = HL7v2.parse(wire)
{:ok, typed} = HL7v2.type(raw)
@spec validate( term(), keyword() ) :: :ok | {:ok, [map()]} | {:error, [map()] | :not_a_typed_message}
Validates an HL7v2 typed message.
Returns :ok when all validation rules pass, or {:error, errors} with
a list of error/warning maps. Requires a HL7v2.TypedMessage -- raw messages
return {:error, :not_a_typed_message}.
Version-aware rules (v2.7+ B-field exemptions, etc.) are driven by MSH-12
(version_id) by default. Pass :version to override this — useful for
validating messages that mis-declare their version or when cross-checking
a v2.5.1 payload against v2.7 conformance rules.
Options
:mode--:lenient(default) or:strict:validate_tables--trueto check coded fields against HL7 tables (defaultfalse):version-- explicit HL7 version override (e.g."2.7"). When provided, version-specific rules use this value instead of the one extracted from MSH-12. Invalid or unrecognized versions fall back to the MSH-12 value.:profile-- aHL7v2.Profilestruct (or list of profiles) to validate against in addition to the base schema. Profiles express organization- specific constraints: required segments, required fields beyond the base spec, table bindings, cardinality, value predicates, and custom rules. Profile errors include a:rule(which rule type fired) and:profile(profile name) for traceability.
Examples
{:ok, msg} = HL7v2.parse(text, mode: :typed)
:ok = HL7v2.validate(msg)
# With table validation
{:error, errors} = HL7v2.validate(msg, validate_tables: true)
# Override the version read from MSH-12 and apply v2.7 rules instead
:ok = HL7v2.validate(msg, version: "2.7")
# Validate against a conformance profile
profile =
HL7v2.Profile.new("Hospital_ADT_A01", message_type: {"ADT", "A01"})
|> HL7v2.Profile.require_field("PID", 18)
|> HL7v2.Profile.require_cardinality("OBX", min: 1, max: 10)
HL7v2.validate(msg, profile: profile)