HL7 Integration
Overview
The Orchestra HL7 Connector is a middleware bridge between Qmatic Orchestra and a Hospital Information System (HIS) — for example a Patient Administration System, EMR, or scheduling platform that already speaks HL7 v2. Rather than building a custom integration per hospital, the Connector translates incoming HL7 messages into Orchestra actions (create visit, check in appointment, identify customer, transfer visit, etc.) and translates Orchestra events back into outgoing HL7 messages for the HIS.
It runs as a separate web application (hl7Connector.war) deployed alongside Orchestra Central, plus three unit type templates that integrate it with Orchestra branches and service points.
Sector — healthcare. The Connector is designed around HL7 v2 message conventions and isn't intended for non-healthcare integrations.
Use cases
The Connector covers four phases of the customer flow:
Pre-arrival — keep Orchestra appointments in sync with HIS appointments. The HIS pushes appointment events (created, updated, deleted) and customer demographic changes into Orchestra; or Orchestra fetches appointments from the HIS in a daily import.
At arrival — when a patient identifies themselves at a kiosk or reception, three patterns are supported:
- Fetch the patient's appointments from Orchestra (assuming pre-arrival sync ran), create a visit, and report the check-in back to the HIS.
- Fetch the patient's appointments from the HIS in real time (via an outgoing/incoming HL7 round trip), then create the visit.
- Receive an inbound check-in HL7 message from a HIS reception module and create the visit on receipt.
Reporting check-in to HIS — when a visit is created in Orchestra, an outbound HL7 message (typically ADT^A04 Patient Admit) is sent to the HIS so its records track that the patient has arrived.
At serving — the HIS can drive Orchestra workstation actions over HL7: call a visit, end a visit, recycle a visit, transfer a visit, add a service to a visit, attach a custom parameter — all addressed by integrationId (a unique appointment ID from the HIS).
When not to use this integration
Internal service-to-service communication inside your stack — Orchestra has REST APIs that are far more ergonomic than HL7. The Connector earns its keep when one or both sides of the integration are non-Qmatic systems that already speak HL7.
Architecture
Hospital Information System Qmatic
┌────────────────────────┐ ┌─────────────────────────────────┐
│ PAS / EMR / RIS │ HL7 v2 │ HL7 Connector (war) │
│ │ ◄───────► │ • TCP listener (HL7 stream) │
│ │ over TCP │ • HTTP listener (servlet) │
│ │ or HTTP │ • Incoming-journey engine │
│ │ │ • Outgoing-journey engine │
└────────────────────────┘ │ • Mapping tables │
│ • Configuration UI │
└────────────┬────────────────────┘
│ REST
▼
┌─────────────────────────────────┐
│ Orchestra Central + Agent │
│ (visits, appointments, │
│ customers, calendar) │
└─────────────────────────────────┘
Components
The deployed solution consists of four artefacts:
hl7Connector.war— the middleware itself. Listens for HL7 traffic, runs the journey engine, exposes a configuration UI and a small REST API for triggering outbound messages.ServicePoint_WebServicePoint_Hl7Unit Type — service-point unit type that handles HL7-driven workstation actions without requiring a logged-in user. Useful in large installations where managing per-user workstations is impractical.notifyHl7VisitEventsUnit Type — catches Orchestra visit events (called, ended, recycled, transferred) and POSTs them to the Connector's outbound endpoint so an HL7 message can be emitted to the HIS.managementInformationServicePointsUnit Type — surfaces service-point visit status to the HL7 service-point unit types. Required for good response time when the Connector handles visit operations.
HL7 message structure (refresher)
HL7 v2 messages are pipe-delimited ASCII. Each message starts with an MSH (Message Header) segment whose MSH-9 field carries the message type (e.g. ADT^A01, SIU^S12, SQR^S25). Subsequent segments — EVN, PID, PV1, OBX, etc. — carry domain data. The default delimiters are | (field), ^ (component), & (subcomponent), ~ (repetition).
MSH|^~\&|MegaReg|XYZHospC|SuperOE|XYZImgCtr|20060529090131-0500||ADT^A01^ADT_A01|01052901|P|2.5|
EVN||200605290901||||200605290900|
PID|||56782445^^^UAReg^PI||KLEINSAMPLE^BARRY^Q^JR||19620910|M|...
PV1||I|W^389^1^UABH^^^^3||||12345^MORGAN^REX^J^^^MD^0010^UAMC^L|...
Every transaction completes with an ACK (acknowledgement) message. MSA-1 = AA means accepted; AE is application error; AR is reject.
The Connector targets the v2.x family — supported versions are 2.1, 2.2, 2.3, 2.3.1, 2.4, 2.5, 2.5.1, 2.6. Messages can be encoded in classic ER7 (pipe + caret) or XML — the listener handles both.
Real-world HL7 caveats
A few realities worth setting expectations around (the Connector handles all of these via configurable journeys and mappings, but the team integrating needs to be aware):
- Missing fields — vendors often omit fields rather than leaving them empty. This shifts every subsequent field number.
- Same data in different fields — the same logical data lives in different fields (or even different segments) across HIS implementations.
- Same data in different formats — timestamps, in particular, vary:
19991231100000.000vs.19991231^100000.000vs. ISO 8601. - Version drift — HL7 v2.x is broadly backward compatible, but quirks accumulate.
- Optional values that the spec says are optional — sometimes vendors omit fields the spec considers mandatory.
- Invalid segment grammar — extra segments, missing segments, wrong order — all happen in the wild.
Prerequisites
- Orchestra version: 7.0 (build 4.0.0.697) or later.
- Application server: the Connector ships as a
.warfile; deploy it to Orchestra's application server alongside the other Orchestra apps. - Hospital Information System that can either accept inbound HL7 messages over TCP or HTTP, send outbound HL7 messages to a configured endpoint, or both.
- Network access: open the TCP port the Connector listens on (configurable; multiple ports are allowed, separated by
;) inbound from the HIS, and the Orchestra ports outbound from the Connector. If TLS is in use, both sides need certificate exchange. - Java 8 (bundled JRE in the Orchestra installation is sufficient).
Installation
- Place
hl7Connector.warinto Orchestra's/custdeployfolder, following the standard Orchestra deployment procedure. - Add the three unit-type templates (
ServicePoint_WebServicePoint_Hl7,notifyHl7VisitEvents,managementInformationServicePoints) via Orchestra's Unit Types administration. Refer to the Orchestra Reference Manual for the unit-type install procedure. - Configure the Connector's connection to Orchestra (see Authentication).
- Restart the Orchestra application server so it picks up the new war.
- Open the Connector UI at
http://<orchestra-host>:<port>/hl7Connector/and complete the Configuration steps.
Authentication
The Connector authenticates to Orchestra using a normal Orchestra user account. There are two ways to provide the credentials.
Option A — embedded in the war
Edit WEB-INF/CONFIG/applicationContext.xml inside the war and set username/password on the Orchestra REST connector bean. Replace the placeholder yourUser / yourPassword with a real Orchestra account that has access to the Central branch.
Option B — external config file (recommended)
Create a file named hl7-connector.conf in Orchestra's conf/ folder:
username=user
password=password
server=localhost:8080
protocol=http
If this file is present, it overrides anything in applicationContext.xml. This makes upgrades cleaner — drop in a new war and the credentials persist.
Connector → HIS authentication
When the HIS accepts inbound HTTP traffic with credentials, configure the username and password in the Connector UI under Configuration → Remote Server (H.I.S) Configuration → Enable Http Credentials. For TCP listeners, mutual TLS is the typical option (also configured in the UI).
HIS → Connector authentication
If the HIS calls the Connector's REST endpoints, secure them at the network layer (TLS, IP allow-listing) — the Connector's REST surface is intentionally small and intended for trusted callers.
Configuration
All configuration is done through the Connector UI at /hl7Connector/. The settings are persisted, and you can export/import them as JSON for environment promotion (DEV → STAGING → PROD).
HL7 Listener
Defines the TCP socket the Connector listens on for inbound HL7 messages.
| Field | Purpose |
|---|---|
| Port | Local TCP port (or several, separated by ;). |
| TLS | Enable for TLS/SSL — usually requires importing the HIS certificate. |
Listener Performance
The Connector uses HAPI's java.util.concurrent.ExecutorService internally to process inbound messages. Defaults: corePoolSize=10, maximumPoolSize=100, keepAliveTime=30s. Tune these only if traffic volume requires it.
HL7 Settings
| Field | Purpose |
|---|---|
| Charset | Character set for inbound messages. Typical: UTF-8. |
| Message type | Filter — only messages matching this pattern are processed. * = all. Example: SIU, ADT. |
| Trigger event | Filter on the trigger event (MSH-9-2). * = all. Example: S12, A01. |
| HL7 Version | Expected version (2.1 through 2.6). |
| ER7 option | If enabled, parser expects classic pipe/caret encoding; otherwise XML. |
Remote Server (HIS) Configuration
Where the Connector sends outbound messages.
| Field | Purpose |
|---|---|
| Remote Server Enabled | Master toggle for outbound traffic. |
| IP Address / Port | HIS endpoint. |
| Server Timeout (ms) | Connection-open timeout when waiting for the HIS. |
| TLS | Enable for TLS/SSL. |
| Enable HTTP | Use this if the HIS exposes a servlet rather than a TCP listener. |
| Http Context | Path under which the HIS receives messages — typically /hl7list. |
| Enable Http Credentials | Send Basic Auth credentials with each request. |
| User / Password | Credentials. |
Orchestra Central / Agent settings
Two parallel blocks under Configuration: the Central settings drive appointment and customer operations; the Agent settings drive entry-point and service-point operations. Each block has Username, Password, Protocol (http/https), and host:port.
Date settings
Two formats need to match the systems on each end:
HL7 Date Format— what the HIS emits and accepts. Example:yyyyMMddHHmmssoryyyyMMddHHmm.Orchestra Date Format— what the Orchestra REST API expects. Default:yyyy-MM-dd'T'HH:mm:ss.000+0000.
Customer template
Defines how the Connector builds the customer external ID when looking up or creating customers. Default templates:
- Calendar customer:
{customer.externalId} - Central customer:
{customer.cardNumber}
Available placeholders: customer.phone, customer.identificationNumber, customer.externalId, customer.firstName, customer.lastName, customer.publicId, customer.email, customer.name.
Branches
A multi-select dropdown listing which branches the Connector should search when locating visits by HL7 custom parameter. Limit it to the branches that actually integrate over HL7.
Logging
Inbound and outbound traffic each get a dedicated log file via conf/logback.xml configuration. Recommended additional appenders:
hl7Connector.log— incoming messagesHl7Connector_Events_handling.log— outgoing messagesHl7Connector_Unattended_servicepoints.log— service-point activityintegrationSummary.log— one-line summary per inbound messagetransactionErrorLog.log— inbound messages that ended in an error
In production set the level to INFO. Detailed DEBUG is acceptable during integration testing.
A per-transaction logging mode is also available, configured in Configuration → Logging & Monitoring. It writes one file per transaction into a date-stamped folder. Useful while bedding in a new integration, expensive in production volume.
Journeys
The Connector's behaviour is defined by journeys — a journey is a triggered pipeline of rules and actions.
Incoming journeys
Trigger: an inbound HL7 message arrives that matches the configured Message Code (e.g. ADTA04, SIUS12, SQRS25).
A journey consists of:
- Rules — every rule must be fulfilled to execute the actions. A rule reads one or more HL7 paths (e.g.
/PID-3-1,/MSH-9) and matches the value against an accepted-values list. Accepted values can be plain strings, regex expressions, or the literalnullto match an absent field. Rules can use conditional paths — find a value within a segment with multiple repetitions and pick the right one. - Parameters — extracted values from the HL7 message that subsequent actions can reference. Parameter types: HL7 path selection, HL7 path concatenation, integration ID, entry point, service, ticket parameter name, appointment public ID, service point, calendar resource/service/appointment, central appointment, calendar/central customer, transfer parameters.
- Actions — what to do once rules pass and parameters are extracted. The action library covers the full Orchestra surface: identify customer, identify appointment, create/call/recycle/end/merge/transfer/remove visit, add parameter or service to visit, create/update/delete appointment (calendar or central), create/update/delete customer (calendar or central), fetch data, multi-appointment check-out, send visit data by HL7, no action, and a custom local action hook.
Outgoing journeys
Trigger: an Orchestra event (caught by the notifyHl7VisitEvents unit type) or a direct REST call to the Connector's outbound endpoint.
An outgoing journey consists of:
- Orchestra event — which event triggers this journey (e.g. visit created, visit called, visit ended).
- Message template — an HL7 message skeleton with placeholders that get filled from event data and configured fields. Customer and appointment templates can be reused across journeys.
- Rules — guard conditions that must hold for the journey to run.
- Fields — the value-mapping table: which event property goes into which HL7 path.
- Send — the message is dispatched to the configured HIS remote server.
Mappings
Because the same business concept often has different codes between HIS and Orchestra, the Connector includes a mapping module (Mappings menu) for: services, standard services, calendar services, queues, entry points, service points, calendar resources. Mapping values can be evaluated as regex, useful for many-to-one matches.
Mappings can be exported and imported as JSON for environment promotion.
Public API
The Connector exposes a small REST surface that lets your own applications (kiosks, custom service-point pages, widgets) trigger journeys without needing to send raw HL7. Both endpoints expect a JSON payload and return a JSON response.
Send data to the HIS
Trigger an outgoing journey — the Connector renders an HL7 message and sends it to the configured HIS. Use this when an Orchestra-side event needs to notify the hospital.
POST /hl7Connector/service/outgoingMessageEngine.groovy
Content-Type: application/json
Required field: eventName — picks the outgoing journey to execute. Any other fields you include become available to the journey's rules and to the message template's field bindings.
Example — notifying the HIS that a visit has been checked in:
const payload = {
eventName: "VISIT_CREATE",
customerId: "1234",
integrationId: "APPT-9988",
branchId: "1",
ticket: "A042",
visitId: "987",
};
await fetch("/hl7Connector/service/outgoingMessageEngine.groovy", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
Fetch data from the HIS
Trigger an outgoing journey AND route the HIS's HL7 response into an incoming journey for processing — a request/response round trip in a single call. Use this for kiosk-time lookups (fetch a patient's appointments, demographics, lab services).
POST /hl7Connector/service/outgoingIncomingMessageEngine.groovy
Content-Type: application/json
Required fields: eventName (the outgoing journey) and optionally eventType (used as input for the incoming journey's rule evaluation — written into the response message's MSH-6-1 field so an incoming journey rule can match on it).
Response envelope:
{
"status": "OK",
"description": "Customer fetched successfully",
"data": "{ ...JSON-encoded payload from the incoming journey... }"
}
status is OK on success, KO on failure. data is a JSON-encoded string with whatever the incoming journey produced.
Example — fetch a patient's lab appointments by card number from a kiosk:
const payload = {
eventName: "CUSTOM",
eventType: "FETCH_DATA",
cardNumber: "121112",
identityType: "PI",
};
const res = await fetch("/hl7Connector/service/outgoingIncomingMessageEngine.groovy", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
const result = await res.json();
if (result.status === "OK") {
const labAppointments = JSON.parse(result.data);
// render the labs in the kiosk UI
}
The corresponding outgoing journey would be configured to:
- Match on the
eventType=FETCH_DATArule. - Place
cardNumberinto HL7 path/QRD-8-1-1andidentityTypeinto/QRD-8-13-1. - Send to the HIS endpoint configured in Remote Server.
The HIS responds with an SQR^S25 message; the Connector replaces MSH-6-1 with eventType so an incoming journey with Message Code = SQRS25 and a rule on MSH-6-1=FETCH_DATA fires next, parses the response, and returns its payload to the original caller.
Connector tester
Built into the UI: send a raw HL7 message at the listener and watch the resulting journey execution. Use it during integration to sanity-check rules and actions before the HIS is actually wired up.
Troubleshooting
| Symptom | Likely cause | Resolution |
|---|---|---|
All HL7 messages return ACK^AR (reject) | Message type / trigger event filter excludes them | Set Message type and Trigger event to * while debugging, or expand the filter list. |
ACK^AE with "Application internal error" | Action failed mid-journey — check Hl7Connector.log and transactionErrorLog.log for the stack trace | Most often a missing mapping (e.g. HIS branch code not mapped to an Orchestra branch). |
Visit not found by integrationId | The Connector only searches branches listed in Configuration → Branches | Add the missing branch to the multi-select. |
| Multi-line HL7 paths return wrong value (pre-2.1.6) | Bug fixed in 2.1.6 — conditional path now handles multi-line segments correctly | Upgrade to 2.1.6 or later. |
| Outgoing message journey misbehaving (pre-2.1.5) | Bug fixed in 2.1.5 | Upgrade to 2.1.5 or later. |
| Mappings codes need pattern matching, not exact equality | Supported since 2.1.4 — mapping codes can be regex | Mark the mapping value as a regex expression. |
| Connector loses Orchestra credentials on upgrade | Credentials embedded in the war | Move them to conf/hl7-connector.conf (supported since 2.1.4). |
| Kiosk-time customer lookup is slow | The DM connector calls service-point synchronously | Upgrade to 2.1.4 or later — service-point calls are synchronised since then. |
FAQ
Which HL7 versions does the Connector support? HL7 v2.1, 2.2, 2.3, 2.3.1, 2.4, 2.5, 2.5.1, 2.6. The version is set in Configuration → HL7 settings → HL7 Version.
Can the Connector send and receive XML-encoded HL7? Yes. Toggle the ER7 option in HL7 Settings. Off = XML, on = classic pipe/caret encoding.
Where do the per-transaction log files go? Into the folder configured at Configuration → Logging & Monitoring → Logging Folder Path, with one subfolder per day. Set Number of days to keep logs files to control retention.
How do I move journeys/mappings between environments? Use the JSON export/import buttons in the journeys and mappings views. Imported journeys are disabled by default — enable them after verifying.
Can multiple HL7 listener ports run at once?
Yes — list them separated by ; in the Listener configuration. Each port shares the same engine.
Related resources
- API Gateway — front the Connector behind the gateway if you're exposing its REST endpoints to external callers.
- Mobile App Integration — kiosk and self-service patterns that pair well with
outgoingIncomingMessageEngine.groovy. - Orchestra API 7.4 reference — the underlying REST endpoints the Connector calls into Orchestra Central and Agent.
- Personal Data API — for retention policies that apply to HIS-sourced patient data.