HL7 v2 acknowledgments
What AA, AE and AR mean, what an ACK contains and who sees the error details.
Every HL7 v2 message is answered with an acknowledgment - an ACK. The sender does not consider a message delivered until the ACK arrives, and retransmits when none does. This page covers what each code means, what the ACK message contains and who sees the error details, in both directions - messages you receive and messages you send.
The codes
| Code | Meaning | When you see it |
|---|---|---|
| AA | Application Accept | The message was processed successfully |
| AE | Application Error | The receiving side failed to process the message - the message reached it, but processing raised an error or validation rejected the content |
| AR | Application Reject | The receiving side refused the message without processing it - for instance, nothing was configured to handle a message like this one |
The enhanced processing mode uses commit-level counterparts - CA counts as accepted the same way AA does, CE as an error the same way AE does, and CR requests a retry the same way AR does.
What an ACK contains
An ACK is itself a small HL7 v2 message:
- MSH - the sender and receiver of the original message, swapped, with a fresh timestamp and
ACKas the message type - MSA - the acknowledgment code and the control ID of the original message, echoed from its MSH-10 - this is how the sender matches the ACK to the message it acknowledges
- ERR - present when there are error details to report, with the details and a condition code from HL7 table 0357
When you receive messages
MLLP channels generate acknowledgments automatically:
- AA - your service processed the message and returned nothing, so the channel answered with the standard accept
- AE - your service raised an exception, or the channel's Validate each message toggle was on and the message failed validation
- AR - no channel's match criteria matched the message and no default channel exists
A duplicate message - one whose MSH-10 control ID was already seen within the deduplication window, when one is set - receives an AA immediately and your service is not invoked again.
If your service returns a string starting with MSH, that message is sent as the response instead of a generated ACK - this is how custom acknowledgments, including query responses, are produced.
Who sees the error details
The channel's Return error details in NAK responses toggle decides what an AE contains. It is off by default:
- Off - the ERR segment holds a generic error message. Off is the production default - the error details stay in your own logs.
- On - the ERR segment contains the actual exception text. Turn this on during development and integration testing, when the people reading the ACKs are the ones fixing the errors.
Either way, the full error is recorded on your side - in the server logs and in the audit log, where the message and its acknowledgment are stored together.
When you send messages
Sending through outgoing connections returns an AckResult that has the remote system's answer already interpreted:
| Field | Type | Meaning |
|---|---|---|
ack_code | str | The MSA-1 code from the remote system, e.g. AA |
is_accepted | bool | True when the message was accepted (AA or CA) |
should_retry | bool | True when the remote system asked for a retry (AR or CR) |
error_text | str | Error details when the message was not accepted |
ack_text | str | The acknowledgment exactly as it arrived, ER7 and all |
# Send 'data', the ER7 message, through the outgoing connection ..
conn = self.mllp['EHR Main']
result = conn.send(data)
# .. and the result carries the remote system's answer.
if result.is_accepted:
self.logger.info(f'Message accepted: {result.ack_code}')
else:
self.logger.warning(f'Message rejected: {result.ack_code} ({result.error_text})')
An acknowledgment is only trusted when its MSA-2 echoes the control ID of the message it answers - a reply naming another message lands in error_text instead.
The connection's Wait for the acknowledgment setting - 250 ms by default - controls how long the reply is waited for. When no reply arrives within it, the connection raises an exception that describes what went wrong, rather than returning a result.
Finding an acknowledgment
The audit log stores each message and its acknowledgment, in either direction, as one exchange, found by the MSH-10 control ID or by a patient identifier from the message itself.
See also
| Page | What it covers |
|---|---|
| Receiving over MLLP | The channels that answer with the codes above |
| Sending over MLLP | Outgoing connections, self.mllp and delivery retries |
| The audit log | Every message and its acknowledgment stored as one exchange |
Learn more
Schedule a meaningful demo
Book a demo with an expert who will help you build meaningful systems that match your ambitions
"We evaluated 12 integration platforms and Zato was the only one to score 100%."
Philip Zuñiga, Assistant Professor, University of the Philippines