This guide walks through the complete path from FHIR-coded clinical data to populated OMOP CDM tables using OMOPHub. It covers vocabulary resolution, domain assignment, standard concept mapping, and CDM table placement - the four steps that every FHIR-to-OMOP transformation pipeline has to solve. If you’re looking for a resource-by-resource cookbook (Condition →Documentation Index
Fetch the complete documentation index at: https://docs.omophub.com/llms.txt
Use this file to discover all available pages before exploring further.
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.
OMOPHub’s FHIR-to-OMOP resolution follows the HL7 FHIR-to-OMOP Implementation
Guide (Informative 1, v1.0.0):
vocabulary-driven domain assignment,
Maps to standardization, the
source/standard concept separation, and the IG’s administrative ConceptMaps
(gender, encounter class, condition status, and more).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. Caller Responsibilities (Outside the Resolver)
The resolver operates on coded values. Two FHIR-to-OMOP IG concerns are resource-level and must be handled by your ETL — OMOPHub does not infer them from a bare code:- Modifier extensions & negation (IG: Understanding FHIR Modifier Extensions). A
modifierExtensioncan negate or repurpose a resource — “no known allergy”, a refuted condition, an anti-prescription, a family-historyCondition, an unreliable measurement. The IG requires checkingmodifierExtensionat the resource root and on backbone elements, and not mapping negated/uncertain content into clinical domain tables. Resolve these before calling the resolver: a code like SNOMED “Allergy to penicillin” resolves identically whether or not it was negated, so negation handling is yours to apply. - Type concepts (
*_type_concept_id). Provenance — “EHR encounter diagnosis”, “patient self-reported”, and so on — derives from FHIRcategory/source context, not from the clinical code. Populate*_type_concept_idin your ETL from the resource’s category.
These are caller responsibilities by design — the resolver is a terminology
service, not a resource-level transformer. See Known
Limitations.
8. The Complete Pipeline Architecture
9. 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.