Azure Health Data Services(HDS)/Azure API for FHIR for converting HL7 Messages to FHIR

256

Healthcare Data is one of the most sensitive and sophisticated forms of data. Having dealt with it, I have experienced it first hand. It has been challenging and exciting at the same time for me. With a myriad of standards and regulations to deal with, healthcare data management requires solid technology to back it up.

Also read: Data Integration: Definition, Process, Tools, Use Cases

Let’s take an example. In a recent project, I had to deal with data in HL7 and FHIR formats. Each of them have different set of challenges. While HL7 is a legacy healthcare data interchange format, FHIR is its modern variant, to make it compliant to HTTP/REST protocol . Hence, legacy HL7 systems need to be moved to FHIR standard.

Both these standards are vastly different in their representation. HL7 is a pipe separated text data, while FHIR is in the standard JSON format. Here is a dummy example of Hl7 ADT message:

MSH|^~\&|||||20220621134830||ADT^A01^ADT_A01|1|P|2.5.1||||AL
SCH|202206211348301
PID||15927|||Moudy^Aubrie^NA^^NA||19811210|female|||1427 WHITE PLNS RD^^Lincoln^PA^^NA||nan|nan|||||NA
PV1||R||||||||nan
NK1|1

Please note that this is not real patient data. Any resemblance is mere co-incidence.

MSH is the beginning of the message header section, SCH for scheduling section, PID for Personal Identification, PV1 for patient visits, NK1 and Next of Kin. While this is not very intuitive, parsers are available. However, for integrating clinical data with modern REST based systems, this first needs to be parsed and then converted to JSON format. Moreover, with strict guidelines in healthcare industry, standards like FHIR needs to be used. Thus, for legacy systems, services for converting standards like HL7 directly to FHIR would be desirable.  Azure Health Data  services’ FHIR service/Azure API for FHIR serves this purpose.  And don’t even think of using LLMs for this, since these standards deal with highly sensitive data.

Also read: Explore your structured data using Natural Language with Azure Open AI

Azure Health Data Services/Azure API for FHIR

As per official documentation, Azure API for FHIR enables rapid exchange of data through Fast Healthcare Interoperability Resources (FHIR®) APIs, backed by a managed Platform-as-a Service (PaaS) offering in the cloud. It makes it easier for anyone working with health data to ingest, manage, and persist Protected Health Information PHI in the cloud. Nevertheless, to perform this conversion, the first step is to provision an Azure Health Data services’ FHIR service or an Azure API for FHIR resource and provision a client application for service principal access. Here is detailed tutorial to create a service client application. Please note the application id and the client secret.

The next step would be to generate an authentication token. Here is a code to generate the token:

def get_access_token():

    app_id = '<your-service-client-id>'
    token_url = 'https://login.microsoftonline.com/<authority-id>/oauth2/v2.0/token' #authority-id is your AD tenant id
    token_data = {
    'grant_type': 'client_credentials',
    'client_id': app_id,
    'client_secret': '<your-client-secret>',
    'scope':'https://<my-az-api-for-fhir>.azurehealthcareapis.com/.default',
    }

    token_r = requests.post(token_url, data=token_data)
    print("Retrieving Access Token")

    if token_r.status_code == 200:
        print("Access Token Retrieved Successfully")
    else:
        raise Exception("Error retrieving access token")

    return token_r.json()["access_token"]

access_token = get_access_token()

Also, here are the API url and auth headers:

#api-endpoint
URL = "https://<my-az-api-for-fhir>.azurehealthcareapis.com/$convert-data"

headers = {
    'Authorization': 'Bearer {}'.format(access_token),
    'Content-type':'application/json',
    'Accept':'application/json'
}

The next step is to create a request body. Here is a sample request body:

hl7Body ={

    "resourceType": "Parameters",
    "parameter": [
        {
            "name": "inputData",
            "valueString": "MSH|^~\&#|||||20200705110909||ADT^A01^ADT_A01|1|P|2.7||||AL\nSCH|202007051109091\nPID||15927|||Moudy^Aubrie^NA^^NA||19811210|female|||1427 WHITE PLNS RD^^Lincoln^PA^^NA||nan|nan|||||NA\nPV1||C||||||||nan\nNK1|1\n"
        },
        {
            "name": "inputDataType",
            "valueString": "Hl7v2"
        },
        {
            "name": "templateCollectionReference",
            "valueString": "microsofthealth/fhirconverter:default"
        },
        {
            "name": "rootTemplate",
            "valueString": "ADT_A01"
        }
    ]
}

It can be seen that the HL7 message goes into the inputData segment of the request body. This Hl7 message can be converted to FHIR with a simple HTTP POST request:

resp = requests.post(URL, json=hl7Body,headers=headers)
print(resp.text)

Here is the screenshot of the response. We won’t paste the full response here since, it is prohibitive and quite complicated. Note that it is not a well formatted JSON.

{
"fullUrl": "urn:uuid:364bf61f-d0ac-3b9a-d91c-dbc2d9d9f46f",
"resource": {
"resourceType": "Patient",
"id": "364bf61f-d0ac-3b9a-d91c-dbc2d9d9f46f",
"identifier": [
{
"value": "15927"
},
{
"value": "NA",
"type": {
"coding": [
{
"code": "SB",
"system": "http://terminology.hl7.org/CodeSystem/v2-0203"
}
]
},
"system": "http://hl7.org/fhir/sid/us-ssn"
}
],
"name": [
{
"family": "Moudy",
"given": [
"Aubrie",
"NA"
],
"prefix": [
"NA"
]
}
],
"birthDate": "1981-12-10",
"gender": "female",
"address": [
{
"line": [
"1427 WHITE PLNS RD"
],
"city": "Lincoln",
"state": "PA",
"country": "NA"
}
],
"telecom": [
{
"value": "nan",
"use": "home"
},
{
"value": "nan",
"use": "work"
}
]
},
"request": {
"method": "PUT",
"url": "Patient/364bf61f-d0ac-3b9a-d91c-dbc2d9d9f46f"
}
}

Conclusion

Hope this article has been useful. While Azure Health Data Services and Azure API for FHIR are two different services for now, from 2026 onwards, FHIR API will exclusively be a part of Azure Health Data Services. The above code will work for both and has been duly tested by the author. Try it yourself by changing the endpoint (do not forget the service client, though). Lastly, this is for informational purposes only. The authors do not claim guarantees regarding the code/examples provided.

 



I am a Data Scientist with 6+ years of experience.


Leave a Reply