FHIR-Converter turns HL7v2 and C-CDA into FHIR with Liquid templates
Conversion utility to translate legacy data formats into FHIR
At a glance
- What is it?
- microsoft/FHIR-Converter is a .NET service that maps legacy health data formats onto FHIR using templates written in the Liquid templating language, and it ships as a container you can run on Azure Container Apps. The mapping logic is editable, which is the point, and also the cost.
- Who is it for?
- Adopt FHIR-Converter when you have to convert HL7v2, C-CDA or JSON into FHIR and your organisation already runs on Azure, since the documented deployment path is a container on Azure Container Apps and customer templates are stored in Azure Storage. Do not adopt it as a general HL7 to FHIR library inside a long-running application, because the shipped architecture is a REST service reached over the network, and the newest conversion, FHIR to HL7v2, is still marked preview.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 30 days ago.
- What is it written in?
- Mainly Liquid, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Conversions that start and end at the same REST boundary
The problem FHIR-Converter addresses is narrow and real: hospitals and health software vendors hold clinical data in HL7v2 messages, C-CDA documents or bespoke JSON, and they need that data expressed as FHIR resources. Writing that mapping by hand in code means every profile variant, every segment and every edge case becomes a code change and a release.
This project moves the mapping into templates. The listed conversion pairs are HL7v2 to FHIR, C-CDA to FHIR, JSON to FHIR, FHIR STU3 to R4, and FHIR to HL7v2, where the last one is labelled preview in the project description. The engine is the Liquid template language running on the .NET runtime, and the templates are what define the mapping between the formats. Editing a template changes the behaviour of the conversion, and creating a new template lets you express a mapping the shipped ones do not cover.
The service is REST based. A request carries the input data in the specified legacy format, names the template to use, and the response is the converted result produced by the transformations in that template. That is a different shape from a library call, and the difference matters for how you would deploy it.
Liquid templates, custom filters and the concept list a template author has to learn
The templates are written in Liquid and make use of custom filters and tags, documented separately in the repository under docs/Filters-and-Tags.md. The engine is the Liquid implementation from Shopify, and the .NET side is a converter assembly referenced in the troubleshooting notes as Microsoft.Health.Fhir.Liquid.Converter.
Writing a template is not quite writing a Liquid page, because the domain vocabulary is specific. The documentation calls out several concepts that a template author has to review before writing anything: the filters and tags summary, the snippet concept, resource id generation, and validation and post processing. Snippets are the reusable fragments, resource id generation is a domain problem rather than a templating one, and post processing is a step that runs on the output.
A ready-made set of templates ships with the project, one per conversion, with notes attached. The HL7v2 to FHIR template comes with a page of important points and a page listing common FHIR Validator errors and warnings that the conversion might produce, which tells you the project expects you to be validating output with the FHIR Validator. The STU3 to R4 template links to a document describing the differences between the two resource versions.
One caveat is stated outright: the provided templates are based on HL7 v2.8, and other HL7 versions may require you to modify them yourself. That is a maintenance commitment, not a detail.
Running it as a container on Azure Container Apps
The current architecture of the project is container based. The APIs are offered as a container artifact in the Microsoft Container Registry, and the documentation states the image can be downloaded and run as a web service on a container hosting platform in your Azure tenant, which clients then target for conversion requests.
The documented default deployment puts the FHIR Converter API container on Azure Container Apps, with the deployment options described in the how-to-guides folder of the documentation. The how-to-guides folder also holds the API usage details and examples, and a troubleshooting guide for a deployed instance.
Two deployment details deserve attention. First, the system is not self-hosted in the sense of a binary you copy onto a server: the shipping form is a container image, and the supported path runs it on Azure. A team that must run everything in its own data centre has to work out that itself, and the documentation given here does not describe a bare-metal deployment. Second, changing access modes is a service operation with a cost, which is one reason the project supports storing and retrieving custom templates in Azure Storage.
On custom templates, the project states that it offers support for storing and retrieving them from Azure storage, and points to a template store integration guide. The list of what changed in the preview iteration also mentions support for Azure Storage for customer templates and the removal of the Azure Container repository dependency for custom templates, so the storage path is a deliberate part of the current design rather than an add-on.
Where the output actually comes from: post processing and the JSON expectation
The troubleshooting notes are where the project is most honest about its own behaviour, and they explain several failure modes you would otherwise hit blind.
The first is timing. Processing time is related to input message size, the template, and the logic inside the template, and the guidance for a slow template is to check for unnecessary loops. There is no batch or streaming guidance, so a template that iterates badly over a large message will show it as latency on that request.
The second is the shape of the result. The output of a template is expected to be JSON when the target is FHIR, which is a contract you can check in a test rather than discover in a client.
The third is post processing. When converting data to FHIR, post processing is performed after the template runs, and the project tells you that unexpected results should be traced to the post processing logic first, pointing at PostProcessor.cs in the converter output processors. This matters because it means a template that looks right can still produce output that surprises you, and the fault is not always in the template.
The fourth is how to learn the real behaviour. For a deeper understanding of how data is converted, the project directs you to the functional tests in the converter's functional tests directory, ConvertDataTemplateCollectionProviderFunctionalTests.cs. That is a better starting point than guessing, because the tests show the inputs and the resulting resources for the shipped templates.
The older 5.x engine and the retired 3.x Handlebars version
The repository keeps a table of previous versions, and reading it explains a lot about the current shape of the code. The 5.x Liquid release covered HL7v2, C-CDA and JSON to FHIR transformations, a command line utility, a VS Code authoring extension, integration with the FHIR Service $convert operation, and ACR template storage. The 3.x Handlebars solution is marked as a previous base solution and no longer supported.
Two things follow. The 5.x line was a tool as well as a library, and the preview API is a service; a command line utility and a VS Code authoring extension are features of a different era of the project, and the current architecture description does not mention them. If you are migrating from 5.x, the local authoring and CLI workflow in particular may not carry over in the same form.
The second is the historical reason for Liquid. The project moved off Handlebars, and the earlier template engine and its documentation are still reachable at the pinned commits in the repository. Anyone who finds an old blog post describing Handlebars filters is reading about a version that is explicitly no longer supported.
Release tags tell their own story. The listed releases are v7.0 on 2024-06-03, v6.0-preview on 2024-05-13 and v5.1.0 on 2022-11-29. The repository is not archived and the last push was on 2026-09-23, so work continues on the default branch, but the most recent tagged release named here is more than two years old, and the newest conversion direction, FHIR to HL7v2, is still flagged as preview.
MIT for the code, a separate agreement for contributions
The code is MIT licensed, which is the permissive end of the range for software you deploy as a service inside a hospital network. The repository also carries a NOTICE file, a SECURITY.md, a stylecop.json, a custom analysis ruleset and a Directory.Build.props, the kind of static analysis and build configuration a .NET project of this size accumulates.
Contributions run on different terms. The project states that most contributions require you to agree to a Contributor License Agreement, a CLA declaring that you have the right to grant the rights to your contribution, and that a bot decides whether a pull request needs one and decorates it accordingly. In practice you only need to sign once across the repositories covered by that agreement. The project also has adopted the Microsoft Open Source Code of Conduct and publishes its own code of conduct document in the repository.
None of this changes the MIT terms for using the converter. It changes who can contribute upstream, which matters if you intend to fix a template rather than maintain a private fork of one.
Editorial conclusion
Adopt FHIR-Converter when you have to convert HL7v2, C-CDA or JSON into FHIR and your organisation already runs on Azure, since the documented deployment path is a container on Azure Container Apps and customer templates are stored in Azure Storage. Do not adopt it as a general HL7 to FHIR library inside a long-running application, because the shipped architecture is a REST service reached over the network, and the newest conversion, FHIR to HL7v2, is still marked preview. Before you start, read the supplied HL7v2 templates against your own HL7 v2.x version, because they are based on v2.8 and other versions need edits, and plan for the licensing sign-off that the MIT licence covers while the contributor agreement does not.
Frequently asked questions
Which data formats can FHIR-Converter convert?
The documented conversions are HL7v2 to FHIR, C-CDA to FHIR, JSON to FHIR, FHIR STU3 to R4, and FHIR to HL7v2, where the last is marked as preview. The mapping for each pair is defined in a template.
What technology does FHIR-Converter use to define conversions?
Templates written in the Liquid templating language, running on the .NET runtime, with custom filters and tags documented in the repository. You can create a new template or modify the shipped ones to match your own requirements.
How do I deploy the FHIR Converter API?
The APIs are published as a container artifact in the Microsoft Container Registry, and the default deployment places the container on Azure Container Apps. The deployment options are described in the how-to-guides folder of the documentation.
Do the shipped HL7v2 templates work with any HL7 version?
The provided templates are based on HL7 v2.8, and other versions may require you to modify the templates yourself. The HL7v2 to FHIR template also comes with a page on common FHIR Validator errors and warnings.
Why is my FHIR conversion output different from what the template seems to produce?
When converting to FHIR, post processing runs after the template, so the project advises checking the post processing logic in the converter output processors when results look wrong. The output of a template is expected to be JSON when the target is FHIR.
Can I store my own conversion templates somewhere other than the container?
Yes. The project documents support for storing and retrieving custom templates from Azure Storage, with a template store integration guide in the how-to-guides folder, and the preview iteration added Azure Storage support for customer templates.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/microsoft-fhir-converter)Was this useful?