condition_occurrence, Observation → measurement, MedicationStatement → drug_exposure, and so on), see the FHIR Integration guide. This page focuses on the vocabulary standardization layer that sits at the heart of any FHIR-to-OMOP pipeline.
1. Why Vocabulary Resolution Is the Hard Part
Converting FHIR resources to OMOP CDM tables is not primarily a schema transformation problem. The structural mapping - which FHIR fields go into which OMOP columns - is well-documented in the HL7 FHIR-to-OMOP IG. The hard part is vocabulary standardization: taking the coded clinical concepts in your FHIR data and resolving them to the correct OMOP standard concepts. This is hard because:- FHIR
CodeableConceptfields can contain codes from any vocabulary system - SNOMED CT, ICD-10-CM, LOINC, RxNorm, local hospital codes, or several simultaneously - OMOP requires a specific
*_concept_idcolumn in each clinical table to point at a standard concept, and the vocabulary domain determines which CDM table the record belongs to - The same clinical idea can appear as different codes in different systems, and a single ICD-10 code can map to multiple SNOMED concepts
- Some FHIR codes are already standard OMOP concepts (most SNOMED codes), while others need mapping via
Maps torelationships (ICD-10, NDC, local codes)
2. The Four-Step Flow
Every FHIR-to-OMOP vocabulary resolution follows the same pattern.Extract the coded concept from the FHIR resource
A FHIR resource contains one or more This Condition has two codings for the same clinical idea: one in SNOMED CT, one in ICD-10-CM.
CodeableConcept or Coding elements. For example, a FHIR Condition resource might contain:Resolve to the OMOP standard concept
Send the codings to OMOPHub’s Concept Resolver. It handles vocabulary identification, concept lookup, The Resolver returns a Key things to notice:
Maps to traversal, and OHDSI vocabulary preference ranking in a single call:best_match based on OHDSI vocabulary preference (SNOMED > RxNorm > LOINC > CVX > ICD-10 for conditions), plus alternatives and unresolved arrays. The important payload is nested under best_match.resolution:- Both the SNOMED code (already standard) and the ICD-10 code (mapped via
Maps to) resolve to the same standard concept:201826 - The SNOMED coding wins as
best_matchbecause SNOMED is the preferred vocabulary for the Condition domain in OHDSI conventions mapping_typetells you what happened:direct(source was already standard),mapped(followedMaps to),semantic_match(fell back to text-based search), orunmappedtarget_tabletells you which CDM table the record belongs to - computed from the standard concept’s domain, not from the FHIR resource typedomain_resource_alignmentisalignedwhen the FHIRresource_typeyou declared matches the concept’s OMOP domain - useful as a sanity signal for mis-coded data
Read the domain assignment
The
domain_id in the standard concept determines which OMOP CDM table the record belongs to. This is critical, and it’s vocabulary-driven, not FHIR-resource-driven.| domain_id | Target OMOP CDM table |
|---|---|
Condition | condition_occurrence |
Drug | drug_exposure |
Measurement | measurement |
Observation | observation |
Procedure | procedure_occurrence |
Device | device_exposure |
Specimen | specimen |
Visit | visit_occurrence |
3. Working with the Python SDK
The same four-step flow, in Python:4. Batch Processing: The ETL Pattern
In a real ETL pipeline you’re processing thousands of FHIR resources. Don’t resolve one at a time - use the batch endpoint. Deduplicate first, then batch-resolve the unique codings in chunks of 100:5. Using the FHIR R4 Terminology Service
If your pipeline already speaks FHIR (you’re integrating with HAPI FHIR or EHRbase, or you’re building a spec-conformant client), you can use OMOPHub’s FHIR R4 terminology operations instead of the REST resolver:$lookup - get concept details for a code:
$translate - map between vocabularies:
$validate-code - check if a code exists:
Parameters responses and can be consumed directly by FHIR-aware clients. See the FHIR Terminology Service overview for the full operation reference.
Concept Resolver vs FHIR Terminology Service - when to use which:Use the Concept Resolver (
/v1/fhir/resolve*) when you want the complete OMOP mapping chain in one call - source concept, standard concept, domain, target CDM table, mapping type. This is purpose-built for ETL pipelines and returns OMOPHub’s native JSON envelope.Use the FHIR R4 Terminology Service (/fhir/r4/*) when you’re integrating with FHIR infrastructure (HAPI FHIR, EHRbase, Firely) that expects spec-conformant FHIR operations and OperationOutcome error responses.Both use the same underlying vocabulary data. The difference is response format and how much resolution logic the server hands you in a single call.6. Handling Edge Cases
One-to-many mappings
A single ICD-10 code can map to multiple SNOMED standard concepts (e.g. a combination diagnosis that splits into separate Condition and Observation concepts). The single-coding resolver returnsalternative_standard_concepts alongside the primary standard_concept. For ETL pipelines, inspect that array and decide whether to write one row per alternative or pick the highest-quality match.
Unmapped codes
If a code doesn’t map to any standard concept, the Resolver returnsmapping_type: "unmapped" with no standard_concept. Your pipeline should:
- Store the source code in the
*_source_valuefield - Set
*_concept_idto0(OMOP convention for unmapped) - Log the unmapped code for manual review - don’t silently drop records
Local / proprietary codes
Hospital-specific codes with custom FHIR system URIs (e.g.http://hospital.local/codes) won’t be in the OMOP vocabulary tables. Two options:
- Pass a
displayvalue with nosystem/code. The Resolver falls back to semantic search over the display text, scoped to theresource_typedomain, and returnsmapping_type: "semantic_match"with asimilarity_score. - Pre-map your local codes to standard vocabularies as part of your site configuration, then send standard codes to the Resolver. See Collaborative Mapping for the shared-mapping-file pattern.
7. The Complete Pipeline Architecture
8. What to Read Next
FHIR Integration Cookbook
Resource-by-resource mappings: Condition, Observation, MedicationRequest, Procedure, and more, with the exact Coding extraction logic for each.
FHIR Terminology Service
Full operation reference for the FHIR R4 Terminology Service:
$lookup, $translate, $validate-code, $expand, $subsumes, $find-matches, $closure, $diff.Lean ETL Mapping Cache
Build validated mapping caches during development and apply them locally at production speed.
Collaborative Mapping
Share mappings across teams via
source_to_concept_map files.Batch & Performance
Deduplication, batch endpoints, cache patterns for ETL at scale.
Known Limitations
What OMOPHub does not do. FHIR-specific caveats, vocabulary exclusions, and what’s on the roadmap.