Skip to content

Sending a CDA Document to an HIE

This recipe configures a channel to submit a CDA document to a Health Information Exchange (HIE) using IHE ITI-41 Provide and Register Document Set-b. The same configuration works for XDS.b (Affinity Domain) and XDR (point-to-point). Only the endpoint URL changes.

It assumes you already have a channel that produces or receives the CDA; the focus here is the submission destination.

What QIE supports

IHE transactions. QIE has built-in operations for the most common IHE transactions, with auto-generated SOAP envelopes:

Profile Built-in transactions
XDS.b ITI-41 (Provide and Register), ITI-42 (Register), ITI-18 (Adhoc Query), ITI-43 (Retrieve Document Set)
PIX / PIXv3 ITI-44 (Patient Identity Feed), ITI-45 (PIXv3 Query)
PDQ ITI-47 (Patient Demographics Query)
XCA ITI-38 (Cross-Community Query), ITI-39 (Cross-Community Retrieve)
XCPD ITI-55 (Cross-Community Patient Discovery)
HPD ITI-58 (Provider Information Query)

Any other SOAP-based IHE transaction can be configured with a standard SOAP Web Service connection. Load the actor's WSDL and the operations become available in the SOAP Sender. In practice, QIE can implement any IHE transaction QIE can be given a WSDL for.

CDA documents. ITI-41 carries the document as a binary attachment, so QIE can submit any CDA R2 / C-CDA document type: Continuity of Care Document (CCD), Discharge Summary, Progress Note, Referral Note, Care Plan, etc. The document type is communicated to the recipient through the Class Code (typically LOINC) and Format Code (an IHE/HITSP template OID) metadata fields. The HIE supplies the specific values to use.

XDS.b vs. XDR. ITI-41 is the same SOAP call in both. XDS.b targets a Document Repository actor in an Affinity Domain; XDR delivers point-to-point to a Document Recipient actor. The QIE configuration is identical; only the endpoint URL changes.

What you need from the HIE before you start

QIE cannot invent the connection details. These come from the HIE's onboarding packet:

  • The ITI-41 endpoint URL (UAT and production).
  • TLS requirements, server-only TLS or mutual TLS, and any cipher restrictions.
  • For mutual TLS: which client certificate to present. The HIE only needs your public certificate.
  • The required metadata values for the XDS.b submission: Class Code, Format Code, Confidentiality Code, Practice Setting Code, Facility Type Code, Type Code, and any expected schemes.
  • Your Document Source ID, the OID identifying your organization as a Document Source. The HIE assigns or accepts this value.
  • The patient identifier domain the HIE expects (often the affinity-domain OID).
  • Whether the HIE expects MTOM/XOP framing or plain SOAP attachments.
  • Test patient/document requirements for onboarding.

Step 1: Import any required certificates

If the HIE requires TLS or mutual TLS, import the HIE's server certificate (and your client key, if mTLS is required) on the Certificate Management page. Skip this step for plain-HTTP test endpoints.

Step 2: Create the IHE Web Service Connection

On the Web Service Connections page, create one connection per HIE actor endpoint URL. Many HIEs split actors across different URLs (Document Repository, Registry, PIX Manager, etc.); use one connection per actor and check only the transactions that actor serves.

Field Value
Type IHE Web Service Profiles
Endpoint URL The HIE-supplied ITI-41 endpoint
Operations Check Provide and Register Document Set-b (ITI-41)
TLS Version Match the HIE's requirement (commonly TLSv1.2 or Allow All Supported Versions)
Trust Policy Trust Selected Certificates. Pick the HIE's server cert
Client Auth Required if the HIE mandates mTLS, then pick your client key in Client Cert
Cached Conn. A non-zero value (e.g. 4) if you expect sustained throughput; the default 0 is fine for low volume

Step 3: Add a SOAP Sender destination

On the channel that produces the CDA, add a destination node. Selecting an IHE Web Service Connection makes the destination a SOAP Sender automatically; the configuration fields are:

Field Value
Connection The IHE connection from Step 2
Binding XDS_soap12_binding (SOAP 1.2, because ITI-41 is bound to SOAP 1.2)
Operation ProvideAndRegisterDocumentSetRequest
Use MTOM Leave unchecked unless the HIE requires MTOM/XOP framing
Request Timeout / Ack Timeout 15000 (ms) is a sensible starting point; raise for slow HIEs
Retry Limit 5
Use Ack Checked

When you select the operation, QIE auto-generates the SOAP envelope template, starting <xdsb:ProvideAndRegisterDocumentSetRequest> with the IHE-standard <wsa:Action> header urn:ihe:iti:2007:ProvideAndRegisterDocumentSet-b and the registry-object skeleton populated with node-tag placeholders.

Step 4: Attach the CDA document

Open the Attachments dialog on the SOAP Sender. Add one attachment per CDA document being submitted.

Field Value
Source Message Cache or Message Node, depending on where the CDA bytes live in your channel
Value The cache key or node path holding the CDA
MIME Type text/xml for a CDA R2 document
Content ID A unique ID such as Document01. Reference this same value from the envelope

The auto-generated envelope already includes the reference to the attachment via XOP:

<xdsb:Document id="Document01">
   <xop:Include href="cid:Document01" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
</xdsb:Document>

If you change the Content ID, change the href value in the envelope to match.

Step 5: Fill in the XDS.b metadata

On the destination node toolbar, click Meta Data to open the XDS.b Provide and Register Meta Data dialog. The dialog edits the metadata embedded in the SOAP envelope. Every field supports node-tag lookups ({PID-3}, {m:patientId}, etc.) so values can be pulled from the message at runtime.

Group Fields
Document descriptors Name, Description
Author Author, Author Institution, Author Role, Author Specialty
Identifiers Patient ID (in the HIE's patient identifier domain), Document Source ID
Content Type Value, Display Name, Scheme
Class Code Value, Display Name, Scheme, high-level document class (typically LOINC)
Confidentiality Code Value, Display Name, Scheme (commonly HL7 v3 Confidentiality)
Format Code Value, Display Name, Scheme, the IHE/HITSP template OID identifying the document format
Facility Type Code Value, Display Name, Scheme
Practice Setting Code Value, Display Name, Scheme
Document Type Code Value, Display Name, Scheme, specific document type (typically LOINC)

The HIE dictates the exact coded values for each set. Most rejections during onboarding come from a code in the wrong scheme or a value the HIE's registry does not recognize.

Document Source ID across multiple facilities

If you operate multiple facilities and each must submit with its own Document Source ID, use a channel-cache or a published mapping table to look up the right OID per source location, then drop a node tag (e.g. {m:documentSourceId}) into the Document Source ID field.

Step 6: Write the ack script

The HIE returns HTTP 200 OK whether the submission is accepted or rejected. The actual outcome is in the SOAP body, a successful response contains <rs:RegistryResponse status="…:Success">, and a failure contains <rs:RegistryResponse status="…:Failure"> with a <rs:RegistryErrorList> carrying one or more <rs:RegistryError> entries. The destination's ack script must inspect the body to decide whether the message completes or goes to the error queue.

What the HIE sends back

The two response shapes look like this. The <rs:RegistryResponse> body is the same across ITI-41, ITI-42, and the ITI-18 query response, so the same ack-script pattern works for all three.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"
                  xmlns:wsa="http://www.w3.org/2005/08/addressing">
   <soapenv:Header>
      <wsa:Action>urn:ihe:iti:2007:ProvideAndRegisterDocumentSet-bResponse</wsa:Action>
      <wsa:RelatesTo>urn:uuid:...</wsa:RelatesTo>
   </soapenv:Header>
   <soapenv:Body>
      <rs:RegistryResponse
         xmlns:rs="urn:oasis:names:tc:ebxml-regrep:xsd:rs:3.0"
         status="urn:oasis:names:tc:ebxml-regrep:ResponseStatusType:Success"/>
   </soapenv:Body>
</soapenv:Envelope>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"
                  xmlns:wsa="http://www.w3.org/2005/08/addressing">
   <soapenv:Header>
      <wsa:Action>urn:ihe:iti:2007:ProvideAndRegisterDocumentSet-bResponse</wsa:Action>
      <wsa:RelatesTo>urn:uuid:...</wsa:RelatesTo>
   </soapenv:Header>
   <soapenv:Body>
      <rs:RegistryResponse
         xmlns:rs="urn:oasis:names:tc:ebxml-regrep:xsd:rs:3.0"
         status="urn:oasis:names:tc:ebxml-regrep:ResponseStatusType:Failure">
         <rs:RegistryErrorList>
            <rs:RegistryError
               codeContext="Patient Id is not known"
               errorCode="XDSUnknownPatientId"
               location=""
               severity="urn:oasis:names:tc:ebxml-regrep:ErrorSeverityType:Error"/>
         </rs:RegistryErrorList>
      </rs:RegistryResponse>
   </soapenv:Body>
</soapenv:Envelope>

Ack script

The script below maps these two shapes to QIE's success / error-queue outcomes. On the destination node, set the ack script to:

// Empty/missing response = transient failure; let QIE retry the send.
if (response == null || response.length === 0) {
   qie.simulateSendError('No response received from HIE.');
}

// Any <rs:RegistryError> means the submission was rejected.
// Surface the HIE's error code and context into the error message.
if (response.indexOf('RegistryErrorList') >= 0) {
   var responseXml = qie.createXMLMessage(response);
   var code        = responseXml.getNode('//RegistryError/@errorCode');
   var context     = responseXml.getNode('//RegistryError/@codeContext');
   message.error('HIE rejected submission: ' + code + ' — ' + context);
   return false;
}

return true;

The three behaviors:

Outcome Script action Effect
No response qie.simulateSendError(...) Treats it as if the send never happened; QIE retries per the channel's resend rules.
Registry rejection message.error(...) + return false Message goes to the error queue with the HIE's errorCode / codeContext as the error text.
Success return true Message marked complete; the SOAP response is stored as the response received.

See Ack Scripts for the full ack-script return-value contract and the qie.simulateSendError / qie.throwAckError / message.error helpers.

Step 7: Test against the HIE's UAT endpoint

  1. Enter debug mode on the channel and run a test message.
  2. The status log records [path=N-N] – SOAP Request: and [path=N-N] – SOAP Response: entries. Open the response to verify what the HIE sent back.
  3. Submit the test patient/document the HIE specified for onboarding.
  4. Iterate on metadata values until the HIE returns a …:Success response.

Typical rejection causes:

  • HTTP 401 or TLS handshake failure: wrong client certificate, the HIE's trust store does not include your CA, or a TLS-version mismatch.
  • XDSUnknownPatientId: the patient ID is not in the HIE's patient identifier domain; run a PIX query first (ITI-9 or ITI-45) to get the HIE-side ID.
  • XDSRegistryMetadataError: a Class Code, Format Code, or other coded value does not match what the HIE's registry expects.
  • XDSRepositoryError: usually MTOM/XOP framing or a Content ID mismatch between the envelope and the attachment.

Companion transactions

ITI-41 is rarely standalone. Production HIE channels usually need one or more of these transactions, configured on the same IHE Web Service Profiles connection type:

Step Transaction(s) Direction
Look up the HIE's patient ID ITI-9 (PIX) or ITI-45 (PIXv3 Query) QIE → HIE Patient ID Manager
Send patient demographics ITI-8 or ITI-44 (Patient Identity Feed) QIE → HIE PIX Manager
Submit the CDA ITI-41 (Provide and Register) QIE → HIE Repository
Find existing documents ITI-18 (Adhoc Query) + ITI-43 (Retrieve) QIE ↔ HIE Registry / Repository

Create one IHE Web Service Connection per actor endpoint URL and check only the transactions that endpoint serves.

Replacing a previously-submitted document

To resubmit an updated CDA that supersedes a prior submission, the envelope must include an <rim:Association> element with associationType="urn:ihe:iti:2010:AssociationType:APND" (for an addendum) or RPLC (for a replacement), referencing the prior document's UUID. This is configured by editing the SOAP envelope directly on the SOAP Sender, typically on a second destination node alongside the first-submit destination, with the channel routing to one or the other based on a flag set in mapping. The XDS.b specification defines the full set of association semantics.