FHIR Resolver: One Call from FHIR Coding to OMOP CDM
New FHIR Resolver endpoints translate FHIR Codings and CodeableConcepts to OMOP standard concepts and CDM target tables in a single composite call. Available in the Python and R SDKs.
The new FHIR Resolver collapses the multi-step OMOPHub call sequence - get_concept_by_code → mappings → validate → semantic search fallback - into a single composite endpoint. Pass a FHIR Coding (or CodeableConcept), get back the source concept, the OMOP standard concept, the relationship type, and the CDM target table the resource belongs in. Optional Phoebe recommendations and mapping-quality signals are one flag away. Built for FHIR-to-OMOP ETL pipelines that don't want to stitch four API calls together for every coded field.
Resolve a Single FHIR Coding
Translate a FHIR Coding (system URI + code) to an OMOP standard concept and CDM target table:
# Python
result = client.fhir.resolve(
system="http://snomed.info/sct",
code="44054006",
resource_type="Condition",
)
res = result["resolution"]
print(res["standard_concept"]["concept_name"]) # "Type 2 diabetes mellitus"
print(res["target_table"]) # "condition_occurrence"
print(res["mapping_type"]) # "direct"
# R
result <- client$fhir$resolve(
system = "http://snomed.info/sct",
code = "44054006",
resource_type = "Condition"
)
res <- result$resolution
cat(res$standard_concept$concept_name) # "Type 2 diabetes mellitus"
cat(res$target_table) # "condition_occurrence"
cat(res$mapping_type) # "direct"
Non-standard codes (ICD-10-CM, ICD-9-CM, and other classifications) are automatically traversed to their standard equivalents - no separate mappings call needed. When no structured code is available, pass display text and the resolver falls back to semantic search.
Batch Resolution
Resolve up to 100 codings in a single call. Failed items are reported inline so one bad code doesn't take down the batch:
# Python
result = client.fhir.resolve_batch([
{"system": "http://snomed.info/sct", "code": "44054006"},
{"system": "http://loinc.org", "code": "2339-0"},
{"system": "http://www.nlm.nih.gov/research/umls/rxnorm", "code": "197696"},
])
print(result["summary"]) # {"total": 3, "resolved": 3, "failed": 0}
for item in result["results"]:
if "resolution" in item:
res = item["resolution"]
print(f"{res['source_concept']['concept_code']} -> {res['standard_concept']['concept_name']} -> {res['target_table']}")
else:
print(f"Failed: {item['error']['code']} - {item['error']['message']}")
# R
result <- client$fhir$resolve_batch(list(
list(system = "http://snomed.info/sct", code = "44054006"),
list(system = "http://loinc.org", code = "2339-0"),
list(system = "http://www.nlm.nih.gov/research/umls/rxnorm", code = "197696")
))
cat(sprintf("Total: %d, Resolved: %d, Failed: %d\n",
result$summary$total, result$summary$resolved, result$summary$failed))
for (item in result$results) {
if (!is.null(item$resolution)) {
res <- item$resolution
cat(sprintf("%s -> %s -> %s\n",
res$source_concept$concept_code,
res$standard_concept$concept_name,
res$target_table))
} else {
cat(sprintf("Failed: %s - %s\n", item$error$code, item$error$message))
}
}
CodeableConcept Resolution
A FHIR CodeableConcept can carry multiple codings for the same concept across different vocabularies. The resolver picks the best match using the OHDSI vocabulary preference order (SNOMED > RxNorm > LOINC > CVX > ICD-10) and returns the alternatives ranked alongside it:
# Python
result = client.fhir.resolve_codeable_concept(
coding=[
{"system": "http://snomed.info/sct", "code": "44054006"},
{"system": "http://hl7.org/fhir/sid/icd-10-cm", "code": "E11.9"},
],
resource_type="Condition",
)
best = result["best_match"]["resolution"]
print(best["source_concept"]["vocabulary_id"]) # "SNOMED" (preferred)
print(best["target_table"]) # "condition_occurrence"
for alt in result["alternatives"]:
print(f" Alt: {alt['resolution']['source_concept']['vocabulary_id']}")
# R
result <- client$fhir$resolve_codeable_concept(
coding = list(
list(system = "http://snomed.info/sct", code = "44054006"),
list(system = "http://hl7.org/fhir/sid/icd-10-cm", code = "E11.9")
),
resource_type = "Condition"
)
best <- result$best_match$resolution
cat(best$source_concept$vocabulary_id) # "SNOMED" (preferred)
cat(best$target_table) # "condition_occurrence"
for (alt in result$alternatives) {
cat(sprintf(" Alt: %s\n", alt$resolution$source_concept$vocabulary_id))
}
When no coding resolves, pass the text field and the resolver falls back to semantic search on the human-readable label.
Install or Upgrade
# Python
pip install --upgrade omophub
# R
install.packages("omophub")