by Rahul Bhagat
Let’s take the example of registering a new patient. When the staff at the front desk completes the patient registration and hits enter, it triggers an event: A04 (Register patient). This causes the system to generate a new ADT^A04 HL7 message, which looks something like this.
MSH|^~&|SENDER_APP|SENT_BY|RECEIVER_APP|RCVD_BY|201310201500||ADT^A04|MSG_ID001|P|2.5|||AL
EVN|A04|201310201500|||ID221^Dude@Terminal
PID|1||PAT416^^^HEALTH_ID||SEBELUS^KANSAS||194801150600|M|||123 SESAME ST^^TORONTO^ON^A1A2B2^CANADA||(416)888-8088||ENGLISH |M||PAT_AC_721914
NK1|1|SEBELUS^MARY|SPOUSE|||(416)888-9999|(647)123-1234|C|20131020
PV1|1|O|ROOM10^BED12^OUTPATIENT|ELECTIVE|||S21195^DRIKOFF^FRANCIS^^^DR^MD||C90023^PAYNE^TRACY^^^DR^MD|SUR||||1|||S21195^DRIKOFF^FRANCIS^^^DR^MD||37323| SELF||||||||||||||||||||||||201310201500
PV2|||DAY SURGERY
AL1|1|FA^PEANUT||PRODUCES MILD RASH
See what I mean? Makes no sense. But soon it will.
Segment
The primary building block of a message is a segment. A segment is simply a row of data in the message. So, for the message above, the first segment starts with MSH and ends on line two with AL. It is actually just one row of data, which was wrapped over to the second line. There is a line break after AL and that means end of the segment. The second segment starts with EVN on line three and ends at “Terminal” on the same line, followed by a line break and so on. A new segment always starts on a new line.
The first three characters of each segment is the segment ID. The segment ID is an acronym or the nametag of the segment.
Once we know the segment name, we know the information in that segment. This is because the main purpose of a segment is to group related information together.
In our example here, there are seven segments (IDs bolded). MSH is the Message Header segment, EVN is the Event segment, PID is the Patient Identification segment and so on. Without even looking at the content of the PID segment, I can tell you it contains the name of the patient, his health ID, date of birth, phone number, address - basically all the information that can be used to identify the patient. Hence the name of the segment - Patient Identification.
MSH|^~&|SENDER_APP|SENT_BY|RECEIVER_APP|RCVD_BY|201310201500||ADT^A04|MSG_ID001|P|2.5|||AL
EVN|A04|201310201500|||ID221^Dude@Terminal
PID|1||PAT416^^^HEALTH_ID||SEBELUS^KANSAS||194801150600|M|||123 SESAME ST^^TORONTO^ON^A1A 2B2^CANADA||(416)888-8088||ENGLISH |M||PAT_AC_721914
NK1|1|SEBELUS^MARY|SPOUSE||(416)888-9999|(647)123-1234|C|20131020
PV1|1|O|ROOM10^BED12^OUTPATIENT|ELECTIVE|||S21195^DRIKOFF^FRANCIS^^^DR^MD||C90023^PAYNE^TRACY^^^DR^MD|SUR||||1|||S21195^DRIKOFF^FRANCIS^^^DR^MD||37323| SELF||||||||||||||||||||||||201310201500
PV2|||DAY SURGERY
AL1|1|FA^PEANUT||PRODUCES MILD RASH
Message Structure
Segments in a message are always organized in a specific order. This order is called the message structure. Different message types have different message structures but some things are always the same. For example, every message starts with an MSH segment.
If the order of segments in a message is not exactly like its message structure, then that message will become invalid. It will be rejected by the receiving system.
You can get the abstract message structure of any message in the HL7 specification document. The abstract message structure of an ADT^A04 message is in Chapter 3 of the HL7 specification document where event A04 is discussed.
Here is a partial abstract message structure of an ADT^A04 message. It is just a table with three columns: segment ID, segment name and the chapter where that segment is explained.
If you compare the example message to its abstract message structure, the segment order does not match between the two. In the example message, the SFT segment is missing after MSH; PD1 & ROL are missing too.
Does that mean the example message is invalid? No, it’s not because the [ ] and {} brackets around those segments make them either optional or repeatable.
Optional/Repeatable/Mandatory
There are two kinds of brackets: square [ ] and curly {}. If a segment ID is enclosed within [square brackets], it means the segment is optional. We can choose whether to include that segment in the message or not. These segments are generally for optional information, such as PD1 (additional patient information).
If the segment ID is enclosed within {curly brackets}, then that segment is repeatable. We can have more than one instance of that segment in a real message. Curly brackets are for segments like NK1 (Next of Kin). If a patient has given contact information for two next of kin (spouse and sister), then the information for each next of kin will need a separate NK1 segment in the message.
If a segment ID is enclosed in both [{square and curly}] brackets then that means the segment is both optional and repeatable. If a segment ID is not surrounded by any bracket then that means it is a mandatory segment. That segment has to be present in the message. So segments like MSH, EVN, PID, PV1, with no brackets, have to be present in a real message.
Based on this knowledge we can see why the example is a valid message. All the missing segments, SFT, PD1 and ROL are surrounded by square brackets. And that means those segments are optional. We can choose to leave them out.
Pipe Delimited
So far so good. Now we know that a message is nothing but a collection of segments. Let’s dig deeper. Let’s take a single segment, for example PID (Patient Identification), and follow the sequence of characters in this segment. You cannot help but notice the | symbol scattered all over the place. This symbol is called a pipe.
PID|1||PAT416^^^HEALTH_ID||SEBELUS^KANSAS||194801150600|M|||123 SESAME ST^^TORONTO^ON^A1A 2B2^CANADA||(416)888-8088||ENGLISH|M||PAT_AC_721914
A pipe is a field separator in HL7. Or, if I were to use the jargon, HL7 messages are pipe delimited.
When you hear delimiter, think separator. Have you ever come across a csv file? Often we convert an excel file into a csv (comma-separated-value) format, to export data. It is a very commonly used file format for updating databases.
When the data in an excel file is converted to csv format, it goes from looking like a table to simple rows of data, like below.
Notice how the data has been stripped down to the basics. It is just field values separated by commas. In csv format, a comma is the symbol that separates field values or to use the correct jargon – it is the field delimiter. So now you know what I mean, when I say, a pipe is the field delimiter in HL7. It is the symbol that is used to separate fields in an HL7 message.
Does that mean a segment is just a collection of fields? That’s right, a segment is nothing but a collection of related fields. But in HL7, unlike the csv file, there is no top row with the name of individual fields. Then how do we know what those fields represent?
Positional
Fields in a segment are positional. This is another way of saying that the position of a field in the segment is fixed. Patient name is always the fifth field in the PID segment. Date of birth is seventh. You cannot have DOB in the seventh field in one message and in the tenth field in another message. The position of a field is fixed.
The HL7 specification document defines an attribute table for each segment. This attribute table contains the list of fields for each segment and other related information like length of field, data type, etc. Both sending and receiving systems refer to the attribute table to figure out where a particular field is. This eliminates the need to send a header row with field names for each message.
Component (^)
Let’s put this newfound knowledge about attribute tables to the test. If you refer to the attribute table for PID segment in Chapter 3 of the HL7 specification document, you will notice that the fifth field is for the name of the patient. Now, we will check the same field in our example message. The best way to get to a field is by counting the pipes.
PID|1||PAT416^^^HEALTH_ID||SEBELUS^KANSAS||194801150600|M|||12
3 SESAME ST^^TORONTO^ON^A1A 2B2^CANADA||(416)888-8088||ENGLISH|M||PAT_AC_721914
The value after the fifth pipe is SEBELUS^KANSAS, which does look like a real person’s name. You can now claim that you are capable of reading an HL7 message!
However, there is a ^ symbol embedded in the name which needs a little explaining. The ^ symbol is called a caret. A caret is the component separator (delimiter) in HL7 messages.
Just like a segment is made up of fields separated by pipes, a field is made up of parts called components, which are separated by carets. If a field has two or more components then those components have to be separated by carets in the message. For example, the name field can have a first name, a middle name, and a last name. So a caret will have to be placed between the first name and the middle name as well as between the middle name and the last name.
Sub-component (&)
Yes, some components are made up of even smaller pieces. Sometimes, I wonder if there were physicists involved in creating HL7. You know, molecules (such as water) are made up of atoms (oxygen and hydrogen). The atoms are made up of sub-atomic particles (electrons, protons & neutrons) and the sub-atomic particles are made up of quarks (up, down, strange, charm etc.).
Similarly, there are components, which are composite in nature and they are made up of smaller pieces called sub-components. Sub-components are separated by the & (ampersand) symbol.
Going back to the example of patient name, its first component, family name, is actually defined as a composite component with five sub-components: surname, own surname prefix, own surname, surname prefix from partner/spouse, and surname from partner/spouse.
If the surname of the patient was St. Pierre Jr. with the first name of Kansas, then the name field would have been something like PIERRE&JR&ST^KANSAS, with subcomponents of the last name separated by & (ampersand).
So there you have it, the building blocks of an HL7 message.
A message is made up of segments
A segment is made up of fields separated by pipes (|)
A field is made up of components separated by a caret (^)
A component is made up of sub-components separated by an ampersand (&)
7. Working with a Message
Now that we have some idea what HL7 is, it’s time to start working with complete messages.
What are some of the situations where you are going to be running into an HL7 message?
1. During system integration: If a new clinical system is purchased, it will need to exchange HL7 messages with existing systems.
2. During troubleshooting: If your system is rejecting an incoming message, you will need to look at the error description and the HL7 message.
3. While creating a message profile. If you are a software company then you will need to define what HL7 messages coming out of your system look like.
There could be other situations but these three make it clear that working with HL7 messages involves reading, writing and creating messages.
To read a message, you will need the Interface Specification document (interface spec). It tells you what each field in the message is for. If an interface spec is not available, you can look up the segment attribute table in the HL7 spec to get an idea about the field. However, the source of truth is always the interface spec.
To write a message, you will definitely need an interface spec. This is because an HL7 spec only gives you the abstract framework. Organizations further tweak the rules (for example, only allow numbers in an alphanumeric field) and these rules are documented in the interface spec. To create a valid message, you will need to comply with all the rules.
Creating a message also involves figuring out the information to be included in the message and how it will be mapped. This information is then documented in the interface spec. It takes a while to get all this work done and you will need to know your way around the HL7 spec in order to do so.
But before we get down to reading, writing and creating messages, let’s learn a bit more about the HL7 spec and the interface spec so that we are able to navigate them easily.
Anatomy of a Message
I tend to look at an HL7 message as made up of a head and a body. The head is the first two or three segments at the top of the message and the rest is the body. Head segments are Control segments and the body segments are Data segments.
Control segments only carry meta-data information about a message. Remember Edward Snowden and the NSA spying scandal? At one point, the NSA came back with the excuse that they were only collecting meta-data of phone conversations. In other words, they were not listening to actual conversation, only recording call related information. Things like the duration of the call, the phone number dialed, local time of the call etc.
Similarly, in HL7, control segments carry only meta-data information about a message. Data segments, as the name suggests, are the real carriers of the data.
HL7 Specification Document
There is no escaping it. If you want to know HL7, you will have to know your way around the eminently dry HL7 specification document (HL7 spec). That’s where all the information is.
The HL7 spec is the owner’s manual for HL7 messaging. It is a bulky manual that has fifteen chapters and over sixteen hundred pages of content.
Until recently, you had to pay a considerable amount to get hold of a copy. However, in September 2012, the organization announced that HL7 standards and all of its intellectual properties would be made publicly available to reduce barriers to adoption and to broaden its usage. You can download the spec for free from their website.
Go to the HL7.org homepage and click on “Standards” in the menu. Within standards, click on “Section 1: Primary Standards” and on the following page (which was a table for me), click on “HL7 Version 2 Product Suite”. This will take you to a page that lists all the versions of the standard. I had to register but it was pretty simple (name, email, address). After that, I was able to download a compressed copy of the specification document. The organization still requires that you acquire a license (for free) before using the standard.
Once you unzip the downloaded file, it expands into over twenty different files. This can be a bit overwhelming, like driving in a new city where you don’t have a mental layout of the place. To avoid frustration while looking for specific information, it will serve you well to have a good sense of the lay of the land.
So, lets unclutter this collection of over twenty files. There are fifteen chapters, four appendices and some other stuff. The chapters are important. You can typically ignore the rest. Even with the chapters, there are only a few that are really important. Remember the 80-20 rule?
Chapter 2 (CH02.pdf) is the most important chapter in the collection. This chapter is called “Control” and that is where you will find information on all the important concepts, control segments, fields, data types etc.
HL7 also defines a lot of data types, which are in CH02A.pdf. You can ignore this chapter unless you need details of a particular data type.
Then there are Chapters 3–15. Each chapter handles a different message type, its trigger events, its data types and other related details.
Each chapter has more or less the same layout. First, trigger events and message types are discussed. Then some data segments are introduced, followed by examples and finally special scenarios.
Interface Specification Document
I mentioned earlier that the HL7 spec is like the owner’s manual. This statement needs a correction. The real owners’ manual is the Interface Specification Document (interface spec). HL7 spec is more like a rulebook with multiple options. The interface spec is a customized version of that rulebook.
Interface specs vary depending on the type of interfaces we are talking about. If it is only for sending and receiving messages, then the spec will detail what the message will look like going out and what it should look like coming in, before the system will process it.
For integration engines (hubs), the spec loo
ks different. They receive a message, change the type/content of the message and send out a different message. So in addition to sending and receiving messages, the interface spec will also have to provide details on transforming the message.
There is no set structure for an interface spec. People do their own thing. But there are some common pieces of information they all have.
The spec will define one or more trigger events. It could even define an entire message type with all of its trigger events. Generally, you will have a number of different specs for different trigger events and message types.
Within the spec, for each trigger event, you will have a message structure that defines the segments and their order in the message. And for each segment, there will be an attribute table, which defines the length, optionality, data type, and other details for each field of that segment. Message structure and segment details give you pretty much all the information you will need to read and write messages.
Reading/Writing a Message
Here is the example message from the previous chapter. Let’s take a stab at reading it.
MSH|^~&|SENDER_APP|SENT_BY|RECEIVER_APP|RCVD_BY|201310201500||ADT^A04|MSG_ID001|P|2.5|||AL
EVN|A04|201310201500|||ID221^Dude@Terminal
PID|1||PAT416^^^HEALTH_ID||SEBELUS^KANSAS||194801150600|M|||123 SESAME ST^^TORONTO^ON^A1A 2B2^CANADA||(416)888-8088||ENGLISH|M||PAT_AC_721914
NK1|1|SEBELUS^MARY|SPOUSE|||(416)888-9999|(647) 123 12 34|C|20131020
PV1|1|O|ROOM10^BED12^OUTPATIENT|ELECTIVE|||S21195^DRIKOFF^FRANCIS^^^DR^MD||C90023^PAYNE^TRACY^^^DR^MD|SUR||||1|||S21195^DRIKOFF^FRANCIS^^^DR^MD||37323| SELF||||||||||||||||||||||||201310201500
PV2|||DAY SURGERY
AL1|1|FA^PEANUT||PRODUCES MILD RASH
First thing you look for in a message is its message type and trigger event. Message type is the ninth field in the MSH segment (MSH-9). In our case, its value is ADT^A04 (bolded in the message). Remember, this is a field with two components joined together by a component delimiter (^). The first component is the general message type, which is ADT. This means the message has something to do with patient administration. The second component is the event type code. This is the trigger event that generated the message. In our example it is A04, which means a patient registration triggered this message.