HL7 for ADT and patient administration
ADT is the patient-administration family of HL7 messages. It is how a patient administration system, PAS, EHR, registration desk, bed board, or MPI tells the rest of the hospital that a patient was registered, admitted, moved, discharged, updated, linked, merged, or corrected. The base HL7 patient-administration chapter describes this as demographic and visit information, but in real interfaces it becomes the backbone that orders, results, billing, document filing, pharmacy, dietary, bed management, and clinical repositories all lean on.
The dangerous myth is that ADT is just "patient demographics." A good ADT feed has at least three stories running at the same time: the person in PID, the encounter or account in PV1, and the event in EVN plus MSH-9. If those stories are mixed up, the message can still parse cleanly while downstream systems attach orders, results, documents, or charges to the wrong record.
This is why ADT is usually the safest place to start the HL7 vertical series. The message family is old, widely implemented, well covered by the HL7 v2 standard, and already represented in this guide by individual pages for ADT_A01, ADT_A02, ADT_A03, ADT_A04, ADT_A08, and ADT_A40. The interesting part is not whether ADT exists. The interesting part is how carefully you treat it.
This is a deliberately ordinary synthetic ADT_A01. Open it in HL7 Soup Web and compare PID-3 with PV1-19. That one comparison teaches a lot: the patient identifier says who the person is, while the visit number says which encounter this event is about.
What ADT Is For
ADT messages are event notifications. They do not normally carry a complete clinical record. They tell receivers that something changed in patient administration and provide enough patient, visit, account, location, provider, contact, diagnosis, insurance, or merge context for that receiver to keep its own state aligned.
The HL7 v2.4 patient-administration chapter lists a long family of trigger events: admit, transfer, discharge, register, pre-admit, update, cancel, pending movement, leave of absence, add/update person, merge, move, change identifiers, and more. That broad list is the first lesson. "ADT" is not one behavior. ADT^A01, ADT^A08, and ADT^A40 all look related, but they should not be handled as interchangeable patient updates.
My practical rule is: treat MSH-9 as the event name, EVN as the event detail, PID as person identity, and PV1 as visit or account context. If a receiver needs to make operational decisions, it should do so from those roles, not from one vague "current patient record" object.
The ADT Events To Learn First
| Event | Usual meaning | Receiver behavior to agree |
|---|---|---|
| A01 | Admit or open a visit. | Create or activate the encounter. Do not treat later location corrections as fresh admissions. |
| A02 | Transfer the patient. | Update the current assigned location in PV1-3 and preserve the prior-location story when provided. |
| A03 | Discharge or end the visit. | Close the encounter, set discharge date/time, and keep the record available for late results, charges, and documents. |
| A04 | Register an outpatient or emergency-style visit. | Create the registration without assuming an inpatient bed admission. |
| A05 | Pre-admit a patient. | Store planned or preadmission identifiers without pretending the patient is already admitted. |
| A08 | Update patient or visit information. | Update demographics or visit context without accidentally reopening, moving, or discharging the encounter. |
| A11, A12, A13 | Cancel an admit, transfer, or discharge. | Reverse the corresponding event deliberately. Do not process a cancellation as just another A08. |
| A15, A16 | Pending transfer or pending discharge. | Model pending state separately from completed state, or ignore safely if the receiver cannot model it. |
| A28, A31 | Add or update person-level information. | Use for MPI or person demographics when there may not be a visit to update. |
| A40 | Merge patient identifier list. | Treat PID-3 as the surviving/correct identifier and MRG-1 as the prior identifier, subject to the local profile. |
The Core Segments
MSH is the envelope: sender, receiver, timestamp, message type, control ID, processing mode, and version. In an ADT feed, MSH-9 is one of the first routing fields. MSH-10 gives the message control ID that an interface engine can log, acknowledge, and use in output filenames.
EVN is the event segment. It is easy to ignore because MSH-9 already names the event, but EVN carries the recorded date/time, planned event time, event reason, operator, occurred time, and event facility depending on version and profile. When support staff ask "when did the transfer actually happen?", EVN may be more useful than the message transmission time.
PID is the person. The field to respect is PID-3 Patient Identifier List, which uses the CX datatype. PID-3 repeats because one patient can have a local MRN, enterprise ID, national identifier, temporary emergency ID, and other identifiers at the same time. Keep the assigning authority and identifier type with the identifier. A bare number is not a patient matching strategy.
PV1 is the visit, encounter, or account layer. PV1-2 Patient Class, PV1-3 Assigned Patient Location, PV1-7 Attending Doctor, PV1-19 Visit Number, PV1-44 Admit Date/Time, and PV1-45 Discharge Date/Time are the fields I would inspect first. The PL datatype behind PV1-3 matters because point of care, room, bed, and facility are not the same value.
After those core segments, the optional segments are not ornamental. NK1 can carry emergency contacts, guardians, or next of kin. AL1 carries allergies that may affect medication, surgery, or diagnostic workflows. DG1 can provide diagnosis context for the encounter. GT1 and IN1 often matter to billing and registration receivers. The local implementation guide decides which optional groups are required for your workflow.
Patient, Visit, And Account Are Not The Same Thing
Most ADT pain comes from flattening patient, visit, and account into one identifier. PID-3 says who the person is. PV1-19 says which visit or encounter this message is about. PID-18 can carry a patient account number in some versions and profiles. PV1 has its own financial and account-context fields. They are related, but they are not synonyms.
Here is the bug pattern: a receiver keys records by patient ID only, then the same patient has two emergency visits, one outpatient appointment, and a later inpatient admission. Results, documents, allergies, and charges can all be technically valid while landing in the wrong visit bucket. The feed did not fail. The receiver's identity model was too small.
The safer receiver stores the patient identifier, visit number, account number where present, patient class, facility, location, and trigger event separately. In Integration Soup, make those values visible in routing, logs, and transformations. If the interface routes inpatient and outpatient events differently, route on explicit fields such as MSH-9, PV1-2, facility, and sender rather than a display label.
Merges Are The Serious Part
ADT merge events deserve their own testing pack. An ADT_A40 does not mean "here are some new demographics." It means one patient identifier has been merged into another. The refactored HL7 v2 material describes A40 as a merge at the patient identifier list level: the prior identifier in MRG-1 is merged into the correct target identifier in PID-3.
That direction matters. If you reverse it, you can retire the good record and keep the duplicate. If you drop assigning authority, you can merge two unrelated patients who happen to share a local-looking number. If you treat A40 as A08, the patient search screen may update while documents, orders, results, images, claims, and audit trails still point to the prior identifier.
Good merge handling keeps both identifiers, the source message, the event time, the operator/source when provided, and the affected downstream references. Some systems physically retain the prior identifier for audit even after it should no longer be used in future transactions. That is not a contradiction; it is a reminder that ADT merge handling is as much governance as parsing.
How ADT Affects Other Medical Verticals
Radiology and imaging receivers use ADT to keep patient demographics, current location, visit number, and sometimes merge information aligned before orders and results arrive. A radiology order can be perfect, but if the patient merge never reaches the RIS or PACS, images can be filed under the wrong identity.
Lab and pathology receivers often rely on ADT for patient identity, location, provider, visit context, and billing context before a specimen order or result appears. Public health, infection control, and clinical repositories may use the same ADT stream to understand where the patient was and which encounter a report belongs to.
Pharmacy, dietary, bed management, nursing, and transport systems care about different pieces of the same event. A transfer affects medication delivery, meal delivery, bed occupancy, patient tracking, and worklists. That is why an A02 should not be swallowed as "just an update." It is a movement event.
Billing and patient accounting often care about guarantor, insurance, financial class, account status, discharge disposition, and admit/discharge dates. If your ADT feed is only for clinical display, you may not need every financial segment. If it feeds billing or charge capture, those fields stop being optional in practice.
A Practical Integration Soup Workflow
For a first ADT workflow in Integration Soup, start small and make the operational contract visible. Receive ADT messages over TCP/MLLP or with a Directory Scanner. Add a representative ADT sample as the message template so the binding tree exposes MSH, EVN, PID, PV1, and the optional groups you care about. Log the message control ID, trigger event, patient identifier, visit number, patient class, location, and sender.
The Integration Host getting started tutorial shows the basic pattern: choose the receiving activity, add a message template, map fields, write output, and inspect logs. For an ADT feed, I would extend that by routing on MSH-9, keeping A01/A02/A03/A08/A40 behavior separate, and making identity values visible in the workflow instead of hiding them inside one transformer.
If the workflow writes files, borrow the production habits from the Processing Files best-practices tutorial: archive important source files, move failed files into an error folder, use a unique value such as workflow instance ID or message control ID in output filenames, and write to a temporary location before another system is allowed to pick up the completed file.
If a team needs a spreadsheet view of ADT activity, the Send HL7 messages to Excel / CSV tutorial is a good fit. Map PID-3, PID-5, PV1-2, PV1-3, PV1-19, MSH-9, and the message date into columns. Keep the first extract boring and verifiable. Once the rows are trustworthy, add filtering by trigger event, facility, or patient class.
The Test Pack I Would Ask For
Do not accept one A01 and call the ADT interface tested. Ask for a set that represents the events the receiver will actually handle:
- A01 admit or visit notification with PID, PV1, and any required optional groups.
- A04 outpatient or emergency registration if the sender uses outpatient visits.
- A02 transfer with old and new location behavior clearly documented.
- A03 discharge or end visit with discharge time and disposition when required.
- A08 demographic or visit update that should not create a new encounter.
- A11, A12, and A13 cancellation cases if the sender supports them.
- A40 merge with clear PID/MRG direction and assigning authority.
- A patient with multiple PID-3 repetitions.
- A patient with multiple active or recent encounters.
- An ACK error or rejection case so retries and support alerts can be tested.
Run those through HL7 Soup Web first. It is much easier to spot a wrong PID/PV1 assumption while the message is still visible than after it has been flattened into a database table.
Implementation Traps
The first trap is using A08 for everything. It is tempting because A08 feels safe: update the patient, move on. But cancel events, transfers, discharges, pending events, merges, and person-level updates have different meanings. Treating them all as A08 slowly erases the event history that made the feed useful.
The second trap is trusting location as text. A location like WARD1^101^1^CITYHOSP is not just a display string. It has point of care, room, bed, and facility components. If the receiving system needs bed board behavior, those components need to stay structured.
The third trap is stripping identifiers down to the number. In ADT, assigning authority and identifier type are safety equipment. Keep them. Patient matching, provider matching, visit matching, merge handling, and multi-site routing all become less risky when identifier authority survives the transformation.
The fourth trap is assuming the feed is a full snapshot. Some senders include every useful optional segment on every event. Others send only the fields relevant to the event. Decide whether blank fields mean "clear this value" or "not supplied on this event" before go-live. That one rule can prevent a lot of mysterious disappearing data.
The fifth trap is validating only the field shell. In ADT-heavy public-health or syndromic-surveillance feeds, a field such as PID-5 may be present while the required component is empty or malformed. Validation should know the segment, field, component, and value set required by the implementation guide, not just whether there is text between two pipe characters.
Related Reading
- HL7 v2.4 Chapter 3: Patient Administration
- HL7 v2+ ADT_A40 merge patient identifier list notes
- ADT_A01 Admit/Visit Notification
- ADT_A02 Transfer a Patient
- ADT_A03 Discharge/End Visit
- ADT_A08 Update Patient Information
- ADT_A40 Merge Patient Identifier List
- PID Patient Identification, PV1 Patient Visit, and MRG Merge Identity
- Integration Host Getting Started
- Processing Files with Integration Host Best Practices
- Send HL7 Messages to Excel / CSV
- Integration Soup HL7 tutorial directory