Docs · FHIR Mapping
FHIR data mapping: from CSV to FHIR-ready fields
Most healthcare data does not arrive as FHIR. It arrives as a CSV export, an Excel sheet, or a legacy table — in five languages, with free-text headers and inconsistent code systems. FHIR mapping is the work of turning those columns into the resources, fields, and terminology that a FHIR-aware system expects.
Concepts
What FHIR mapping is
FHIR (Fast Healthcare Interoperability Resources, an HL7 standard) models healthcare data as resources — for example a Patient, an Observation, a Medication, or a Claim. Each resource has defined fields (elements) with types and cardinality, and many fields carry terminology bindings — they expect a coded value drawn from a specific code system rather than free text.
FHIR mapping, then, is a three-part problem: figure out which FHIR resource a row of your data represents, line up each of your columns with the right field on that resource, and make sure coded fields carry values from the right terminology — LOINC for lab observations, ICD-10 for diagnoses, CPT for procedures, and so on. The standard spells out the resources and their fields in detail at hl7.org/fhir.
The hard part
Why CSV → FHIR is hard
The gap between a spreadsheet and a FHIR resource is wider than it looks. Three things make it hard:
- Free-text headers. A column called
DOB,birth_dt, orPatient Birthdayall meanPatient.birthDate, but no two source systems agree on the spelling. - Locale variance. Headers, date formats, and gender values differ across German, French, Italian, English, and Spanish source systems — common in multi-region healthcare data.
- Code systems. FHIR’s coded fields expect values from specific terminologies — LOINC, ICD-10, CPT, ATC, NPI — and a raw export rarely arrives validated against them.
Get any of these wrong and the resulting resource is either rejected by the receiving system or — worse, for your-money-or-your-life healthcare data — silently incorrect.
The approach
How AdaptivMapr maps to FHIR
AdaptivMapr maps your inbound columns to a template’s canonical fields, and each healthcare template carries a fhir_resource mapping so you always know which FHIR resource and path a field corresponds to. It resolves and validates the mapping layer; your pipeline serialises the FHIR-ready fields into resources.
The 5-layer cascade
Header resolution runs through five layers, cheapest first. When a layer accepts a column, the layers below it never run — and the metered LLM is the last resort, not the first move.
- 1 · Statistics — no AI cost, deterministic; auto-accepts headers seen mapped the same way before.
- 2 · Heuristic — no AI cost; compares the normalised header against the column name, label, and every multilingual hint (DE / FR / IT / EN / ES).
- 3 · Fuzzy — no AI cost, pure compute; tolerates typos and reordered tokens.
- 4 · Semantic — cheap, cached embeddings for the long tail of paraphrases.
- 5 · LLM — metered; fires only on genuinely ambiguous columns, constrained to the template’s allowed field set so it cannot invent a field.
Validators & HITL gating
Healthcare templates attach field-level validators — LOINC, ICD-10, CPT, ATC, NPI, GTIN, IBAN and more — that run on every committed row. Each template also carries a risk level. Medium- and high-risk templates — patient_demographics, lab_results, claims_line_items, and drug_formulary — return requires_hitl: true with hitl_status: "pending_review" so you can gate your own commit workflow with a human review step.
On data handling: schema-only mapping is the default data-minimization mode — only headers and up to three sample rows (≤80 characters each) leave your environment. Full-data mapping requires a PHI subscription, where the layer-5 LLM call is routed through a PHI-eligible provider with X-PHI and X-Region headers to force a PHI-eligible, in-region model. A BAA is available; AdaptivMapr is HIPAA-aware.
Worked examples
Three columns, mapped
Each example links to the live template page, where you can see the full canonical schema, validators, and FHIR resource mapping.
"Geburtsdatum" → date_of_birth
template : patient_demographics_v1
fhir : Patient.birthDate
caught by : Layer 2 · HeuristicThe German header matches a registered hint after the normalising pass, so the column resolves without AI. The date_range validator (1900-01-01 to today) fires on commit.
Patient demographics template →"code loinc" → loinc_code
template : lab_result_catalog_v1
fhir : Observation.code
caught by : Layer 2 · HeuristicThe French label resolves against the loinc hint, and the loinc_code validator checks the value against LOINC’s code format on commit.
Lab result catalog template →"Diagnose (ICD)" → icd10_code
template : claims_line_items_v1
fhir : Claim.item
caught by : Layer 3 · FuzzyA messy header with extra tokens still resolves via the fuzzy layer. Because this template is risk medium, the mapping is returned with requires_hitl:true so your team can gate the commit.
Claims line items template →Questions
FHIR mapping FAQ
Get started
Map your first file — without shipping raw records.
Schema-only mapping keeps raw records on your side — start there. The documentation covers the API, the MCP server, and the template catalogue.