Skip to main content

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_Hl7 Unit 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.
  • notifyHl7VisitEvents Unit 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.
  • managementInformationServicePoints Unit 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.000 vs. 19991231^100000.000 vs. 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 .war file; 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​

  1. Place hl7Connector.war into Orchestra's /custdeploy folder, following the standard Orchestra deployment procedure.
  2. 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.
  3. Configure the Connector's connection to Orchestra (see Authentication).
  4. Restart the Orchestra application server so it picks up the new war.
  5. 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.

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.

FieldPurpose
PortLocal TCP port (or several, separated by ;).
TLSEnable 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​

FieldPurpose
CharsetCharacter set for inbound messages. Typical: UTF-8.
Message typeFilter — only messages matching this pattern are processed. * = all. Example: SIU, ADT.
Trigger eventFilter on the trigger event (MSH-9-2). * = all. Example: S12, A01.
HL7 VersionExpected version (2.1 through 2.6).
ER7 optionIf enabled, parser expects classic pipe/caret encoding; otherwise XML.

Remote Server (HIS) Configuration​

Where the Connector sends outbound messages.

FieldPurpose
Remote Server EnabledMaster toggle for outbound traffic.
IP Address / PortHIS endpoint.
Server Timeout (ms)Connection-open timeout when waiting for the HIS.
TLSEnable for TLS/SSL.
Enable HTTPUse this if the HIS exposes a servlet rather than a TCP listener.
Http ContextPath under which the HIS receives messages — typically /hl7list.
Enable Http CredentialsSend Basic Auth credentials with each request.
User / PasswordCredentials.

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: yyyyMMddHHmmss or yyyyMMddHHmm.
  • 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 messages
  • Hl7Connector_Events_handling.log — outgoing messages
  • Hl7Connector_Unattended_servicepoints.log — service-point activity
  • integrationSummary.log — one-line summary per inbound message
  • transactionErrorLog.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:

  1. 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 literal null to match an absent field. Rules can use conditional paths — find a value within a segment with multiple repetitions and pick the right one.
  2. 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.
  3. 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:

  1. Orchestra event — which event triggers this journey (e.g. visit created, visit called, visit ended).
  2. 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.
  3. Rules — guard conditions that must hold for the journey to run.
  4. Fields — the value-mapping table: which event property goes into which HL7 path.
  5. 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_DATA rule.
  • Place cardNumber into HL7 path /QRD-8-1-1 and identityType into /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​

SymptomLikely causeResolution
All HL7 messages return ACK^AR (reject)Message type / trigger event filter excludes themSet 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 traceMost often a missing mapping (e.g. HIS branch code not mapped to an Orchestra branch).
Visit not found by integrationIdThe Connector only searches branches listed in Configuration → BranchesAdd 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 correctlyUpgrade to 2.1.6 or later.
Outgoing message journey misbehaving (pre-2.1.5)Bug fixed in 2.1.5Upgrade to 2.1.5 or later.
Mappings codes need pattern matching, not exact equalitySupported since 2.1.4 — mapping codes can be regexMark the mapping value as a regex expression.
Connector loses Orchestra credentials on upgradeCredentials embedded in the warMove them to conf/hl7-connector.conf (supported since 2.1.4).
Kiosk-time customer lookup is slowThe DM connector calls service-point synchronouslyUpgrade 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.

  • 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.