OMOP Concept Hierarchy API: The Authoritative OMOPHub Guide

You're probably dealing with one of two situations right now. Either you already run OMOP and vocabulary work keeps slowing the delivery of ETL, analytics, and terminology integration, or you're evaluating OMOP and have realized the hard part isn't the Common Data Model itself. It's the vocabulary operations around it.
The friction usually shows up in the same places. Teams need to search concepts, resolve source codes to standard concepts, walk hierarchies for phenotype definitions, and keep everything aligned with ATHENA releases. What sounds like “just terminology lookup” turns into local database setup, repeated reloads, custom scripts, and brittle logic around hierarchy traversal.
That's where an API-first pattern changes the shape of the work. Instead of treating OMOP vocabularies as a quarterly infrastructure project, you treat them as an operational service your pipelines, applications, and research tooling can call directly. The practical value isn't just convenience. It's getting repeatable, auditable vocabulary behavior into production systems without rebuilding the same plumbing in every team.
Why You Need a Better OMOP Vocabulary Strategy
A common failure pattern shows up late in delivery. The ETL is nearly done, the phenotype logic looks settled, and then the team discovers that concept expansion, source-to-standard mapping, and hierarchy traversal all behave differently across scripts, local databases, and release snapshots. Work stops while engineers sort out vocabulary mechanics instead of finishing the data product.

That problem gets expensive in production. A local vocabulary install can answer simple lookups, but production workflows usually need more than lookups. They need repeatable hierarchy expansion for cohort definitions, stable mappings for ETL pipelines, and predictable behavior across ATHENA-aligned releases. Teams that treat OMOP vocabularies as static files usually end up rebuilding the same service layer in every project.
The hard part is hierarchy.
SNOMED CT is large and highly nested, with hundreds of thousands of active concepts documented in the SNOMED CT Starter Guide. In practice, phenotype authors rarely mean a single code. They mean a parent concept plus the right descendants, with exclusions applied deliberately. ETL teams hit the same issue from the other side. A source code must map to a standard concept, and that standard concept must still behave correctly in downstream rollups, quality checks, and analytics.
Manual vocabulary operations usually fail in three predictable ways:
- Access is an afterthought. Files are present, but application code still lacks a clean way to query ancestors, descendants, relationships, and standard mappings.
- Release handling is brittle. Logic that worked on one vocabulary snapshot often breaks after a refresh.
- Vocabulary logic leaks into delivery work. Data engineers spend time maintaining terminology infrastructure instead of improving normalization rules and data quality.
A better pattern is to treat vocabulary functions as an operational service. Search, mapping, hierarchy traversal, and version-aware resolution should be callable from ETL jobs, phenotype tooling, and interoperability services without custom database plumbing in each team. That is the practical shift behind an API-first OMOP vocabulary strategy.
Performance matters here as well. Low-latency terminology APIs are achievable with caching and edge delivery, a pattern described in the Cloudflare guidance on cache performance and latency. For production systems, that changes the user experience from batch-era vocabulary processing to interactive concept resolution inside authoring tools, validation pipelines, and clinical data services.
The result is simpler operations and cleaner governance. Vocabulary behavior becomes auditable, reusable, and consistent across ETL mapping, phenotype authoring, and FHIR-based workflows.
Understanding the OMOPHub Vocabulary Universe
Before writing calls against any vocabulary service, you need a mental model of what you're querying. In OMOP terms, the basic units are concepts, vocabularies, domains, and relationships. If you get those right, your API usage stays clean. If you don't, even simple mapping workflows start producing ambiguous results.
The terminology layer exposed through OMOPHub mirrors the official ATHENA release stream rather than a private fork, which is the right starting point for teams that need predictable standardization behavior across research and operational use cases. The All of Us overview of OMOP basics notes that OMOP vocabularies synchronized with ATHENA support over 15 major terminologies including LOINC, RxNorm, and HCPCS, with version management that tracks updates over time.

The objects that matter in daily work
A useful way to think about the vocabulary universe is this:
- Concepts are the atomic records you search, resolve, map, and traverse.
- Vocabularies tell you where a code originated, such as SNOMED CT, ICD-10-CM, LOINC, or RxNorm.
- Domains tell you where the concept belongs in OMOP semantics, which matters when you're routing data into the right CDM table.
- Relationships define graph behavior. Two of the most important are
Maps tofor source-to-standard translation and hierarchical relationships used for ancestor and descendant expansion.
In practice, developers also need to distinguish standard concepts from source concepts. Standard concepts are what you want in the target model for consistent analytics. Source concepts are often what your inbound systems send. The mapping process bridges the two.
How to inspect concepts before you automate them
Before embedding logic in ETL or research code, inspect a few concepts interactively. The OMOPHub Concept Lookup tool is useful for that because it lets you sanity-check names, vocabulary origin, domains, and relationship context without writing code first.
For a broader walkthrough of how the vocabulary API fits together, the OMOP vocabulary API guide is a good companion read.
When teams skip concept inspection and jump straight to code, they usually end up debugging assumptions about standardness, domain assignment, or mapping direction instead of debugging the API.
One more practical point. “Search” and “mapping” aren't interchangeable. Search helps humans find candidate concepts. Mapping needs deterministic rules, version awareness, and explicit relationship handling. Treat those as separate jobs in your architecture.
Your First API Call in 5 Minutes
The fastest way to validate your setup is to make a single authenticated request that returns a standard OMOP concept and a CDM destination. That proves four things at once. Your key works, your client can reach the API, your request shape is correct, and you're getting terminology decisions back in structured JSON.

The minimum setup
You need an API key from the OMOPHub dashboard. Requests use a Bearer token over HTTPS, and the same key works across the REST API and FHIR terminology surface.
Use the REST base at OMOPHub REST API and send your key like this:
- Authorization header set to
Bearer oh_your_api_key - Content-Type set to
application/json
First call to resolve a clinical code
A strong first test is FHIR code resolution because it's a common production problem. You have a coding system URI, a code, and a FHIR resource context. You want the standard concept and target table without manually chaining terminology logic yourself.
This example resolves a SNOMED condition code:
curl -X POST "https://api.omophub.com/v1/fhir/resolve"
-H "Authorization: Bearer oh_your_api_key"
-H "Content-Type: application/json"
-d '{"system": "http://snomed.info/sct", "code": "44054006", "resource_type": "Condition"}'
If you prefer to browse the platform entry points first, the default FHIR terminology endpoint is available at OMOPHub FHIR Terminology Service.
What to check in the response
Look for these fields first:
- Standard concept identity
- Domain
- Mapping type
- CDM target table
If those are present and semantically correct, your environment is ready for the more interesting work: hierarchy traversal, batch ETL mapping, and phenotype expansion. If the response isn't what you expect, test with a known code from the same coding system before changing your application logic.
Core API Endpoint Reference
The easiest way to misuse a terminology API is to treat every problem like a search problem. Production systems usually need three distinct behaviors. Search to find candidate concepts. Resolve to normalize a coding into an OMOP target. Map when you need cross-vocabulary translation at scale.
Search endpoints for discovery
Use search when a user knows a phrase, not a concept ID. This is the right fit for concept-set authoring tools, analyst workflows, and UI autocomplete.
Common search patterns include:
- Full-text search for exact or near-exact labels
- Fuzzy search when source phrasing is messy
- Autocomplete for interactive UIs
- Semantic search when the wording doesn't match the canonical terminology string
A typical request shape is a query term plus optional filters such as vocabulary or domain. The response should be treated as a ranked candidate list, not a final mapping decision.
Example request:
GET /v1/search?q=type%202%20diabetes
Example response shape:
- candidate concept ID
- concept name
- vocabulary
- domain
- standardness indicators
Resolve endpoints for deterministic normalization
Use resolve when the input already contains a code and coding system. Application integration gets simpler because the service can handle Maps to traversal and return a standard concept plus the target CDM context.
Typical request:
POST /v1/fhir/resolve
Example JSON request:
{ "system": "http://snomed.info/sct", "code": "44054006", "resource_type": "Condition" }
Example response shape:
{ "standard_concept": { "concept_id": "...", "concept_name": "..." }, "domain": "...", "mapping_type": "...", "cdm_target_table": "..." }
This pattern is especially useful in FHIR ingestion pipelines because you don't want every downstream service implementing its own code-system parsing and OMOP mapping rules.
Mapping endpoints for cross-vocabulary translation
Mapping is different from resolve because the question is often “what is the preferred OMOP-aligned target across vocabularies” rather than “what does this one coding mean in FHIR context.” Batch support matters more here.
Practical use cases include:
- transforming claims or lab source codes during ETL
- validating terminology coverage before a study
- translating between source coding systems used by different institutions
Example request shape:
POST /v1/map
Example JSON request:
{ "source_vocabulary": "ICD10CM", "code": "E11.9" }
Expected response fields usually include the mapped concept, target vocabulary information, and relationship metadata.
FHIR terminology operations when standards compliance matters
Some environments don't want a custom REST abstraction. They want native FHIR terminology operations such as $lookup, $validate-code, $translate, $expand, $subsumes, $find-matches, $closure, and $diff. That's where a dedicated terminology service endpoint fits better than a hand-rolled adapter.
For implementation details and request shapes, Our developer documentation is worth keeping open alongside the platform docs because it helps compare integration styles and payload conventions in real projects.
Don't let UI search responses leak into ETL mapping logic. Human-assisted discovery and machine-grade normalization should stay separate, even if they use the same vocabulary backend.
Programmatic Hierarchy Traversal
A common failure shows up after the first successful code mapping. The ETL team maps source codes correctly, then builds a phenotype or quality measure that misses half the intended population because the concept set stopped at the seed concept. In OMOP, hierarchy traversal is how you turn a correct concept into a usable cohort definition, rollup, or classification rule.
The practical question is rarely “what does this code mean?” It is usually “which descendants belong in scope for this use case?” or “which ancestors explain why this concept landed in this domain or category?” Those are production questions. They affect cohort size, feature engineering, auditability, and downstream reproducibility.
Use hierarchy endpoints as part of a recipe, not a one-off lookup
The pattern that works in production is straightforward. Resolve or identify the right seed concept first. Expand descendants for inclusion logic. Pull ancestors when reviewers, analysts, or ETL owners need to understand the rollup path. Store both the seed and the expansion criteria so the result can be reproduced later.
OMOPHub simplifies this because teams do not have to write recursive SQL against concept_ancestor for every application. The API gives the hierarchy directly, which is useful when the same vocabulary logic must serve ETL pipelines, phenotype authoring tools, and validation jobs.
For a broader implementation view, the OMOP vocabulary SDK guide for application developers covers client patterns outside raw HTTP.
Python example for descendant expansion
Python teams usually want one thing here. Get a stable concept set artifact that can feed cohort logic or mapping review.
from omophub import OMOPHub
client = OMOPHub(api_key="oh_your_api_key")
seed_concept_id = 201826 # example seed concept
descendants = client.descendants(concept_id=seed_concept_id)
concept_ids = [seed_concept_id]
for item in descendants["items"]:
concept_ids.append(item["concept_id"])
print(concept_ids)
That snippet is enough for a first pass, but production pipelines usually add two controls. Filter by hierarchy distance when broad parents bring in concepts that are clinically too far from the original intent. Persist the expansion timestamp and API parameters so a later vocabulary refresh does not change study logic without notice.
R example for hierarchy navigation
R workflows often use hierarchy traversal during concept set curation, exploratory analysis, or cohort package preparation.
library(omophub)
client <- OMOPHub$new(api_key = "oh_your_api_key")
seed_concept_id <- 201826
desc <- client$descendants(concept_id = seed_concept_id)
concept_ids <- c(seed_concept_id, vapply(desc$items, function(x) x$concept_id, numeric(1)))
print(concept_ids)
The trade-off is the same as in Python. Fast expansion saves time, but every broad seed concept increases review burden. Good phenotype authors start narrow, inspect returned descendants, then widen only when the clinical intent supports it.
Where hierarchy traversal pays off
Two use cases show up repeatedly.
For ETL, hierarchy traversal helps convert a small number of reviewed standard concepts into reusable inclusion groups. That is useful when different source systems code the same clinical idea at different levels of specificity.
For phenotype authoring, descendants give you candidate members of a concept set, while ancestors provide the audit trail reviewers ask for when they want to know why a concept was included under a broader condition, procedure, or drug class.
What breaks in real systems
Three mistakes account for a lot of avoidable rework:
- Using an overly broad seed concept. A high-level parent can pull in descendants that are valid in the vocabulary but wrong for the analytic question.
- Treating every descendant as phenotype-ready. Hierarchy membership is a starting point for review, not automatic clinical approval.
- Skipping provenance. If you do not store the seed concept, traversal direction, filters, and vocabulary version, you cannot explain later why a concept set changed.
A simple review loop prevents most of this. Inspect the first expansion, remove obvious false positives, rerun with tighter constraints, then promote the result into your shared concept-set asset. For one-off verification before you automate anything, use the interactive lookup tool and inspect the tree visually before the logic reaches ETL or study code.
Leveraging Advanced FHIR and AI Services
Some teams only need a REST vocabulary API. Others need terminology behavior that plugs directly into standards-based clinical systems or AI-assisted workflows. That's where two capabilities become especially valuable: a FHIR terminology service and an MCP server for grounded AI access.
FHIR terminology operations for real interoperability
A standards-compliant FHIR terminology service lets FHIR-aware clients use terminology operations directly instead of going through a custom translation layer. In practice, that means systems such as HAPI FHIR or EHRbase can call operations like $lookup, $validate-code, $translate, $expand, $subsumes, $find-matches, $closure, and $diff against OMOP-backed vocabularies.
That matters when terminology resolution sits close to clinical workflows. A FHIR app can validate incoming codes, expand value sets, or translate codings into OMOP-compatible semantics without inventing a proprietary terminology stack first.
One implementation option is OMOPHub, which exposes a REST plus FHIR API over the ATHENA-aligned vocabulary set, supports R4, R4B, R5, and R6 on the same endpoint, and adds a FHIR resolver that can return the standard concept, domain, mapping type, and CDM target table in one call.
AI workflows need grounded terminology tools
LLMs are good at language. They aren't reliable code systems. If you let a model invent SNOMED, LOINC, or RxNorm codes, your pipeline becomes unsafe fast. An MCP server closes that gap by giving the model tool access to the source-of-truth vocabulary service instead of letting it guess.
The OMOP MCP guide explains the pattern well. The practical value is straightforward. The agent can search, resolve, map, and inspect hierarchy through tools instead of free-form generation.
Relevant SDKs and repositories:
Tips for using these services well
- Use FHIR operations when your client already speaks FHIR. Don't force a REST wrapper into a HAPI FHIR integration if the standard operation already fits.
- Keep AI on a short leash. Let the model propose search terms or workflow steps, but require tool-backed code resolution before accepting terminology output.
- Log the terminology decisions. For auditability, store the input coding, returned concept, and version context used by your workflow.
Practical Recipes for Common Use Cases
The API becomes useful when it removes friction from workflows you already have. Three patterns show up constantly in delivery work: ETL mapping, phenotype authoring, and point-of-care FHIR resolution.

Recipe one for ETL source-to-standard mapping
A typical ETL feed arrives with source codes from claims, labs, medications, or local clinical systems. The pipeline needs to normalize those codes into standard OMOP concepts before loading target tables.
A clean production sequence looks like this:
- Separate deterministic inputs from ambiguous ones. If the source already provides code plus vocabulary, send those through direct resolution or mapping first.
- Apply
Maps tologic server-side. This reduces custom ETL branching and keeps mapping behavior centralized. - Route by returned domain and target table. Don't infer target CDM placement from source file names or local assumptions.
- Send unresolved cases to a review queue. Keep them out of the main load until a terminology decision exists.
This recipe works best when the ETL job stores both the original source code and the returned standard concept details. That preserves traceability without complicating the transform layer.
Recipe two for phenotype concept-set authoring
A researcher often starts with a short list of seed concepts, usually chosen from a literature definition or prior concept set. The next step is to expand descendants and inspect the resulting tree.
A practical workflow:
- Pick a seed concept carefully. Broad parent concepts can over-include.
- Fetch descendants programmatically. Build the first draft of the concept set from the returned tree.
- Review exclusions explicitly. Some descendants are clinically related but wrong for the study.
- Freeze the final set with version context. Your results need to be reproducible.
The OMOP concept hierarchy API proves its value here. The hard part isn't writing a recursive loop. It's making hierarchy expansion auditable and repeatable so the same concept set can be rebuilt later.
A concept set is never “correct” in the abstract. It's correct for a use case, a clinical definition, and a vocabulary version.
Recipe three for FHIR-aware applications
FHIR applications often receive codings at the point of care and need to make an OMOP-aware decision immediately. A Condition, Observation, or medication-related resource arrives with a coding system and code. The app needs to know what that coding means in OMOP terms and where it belongs downstream.
The practical recipe is:
- accept the incoming coding or
CodeableConcept - resolve it through the terminology service
- use the returned standard concept and domain for business rules
- send the CDM-targeted output into downstream analytics or persistence logic
This keeps your application logic thin. The app doesn't need to understand every coding system relationship itself.
Small habits that save time
- Cache stable terminology responses in your app or pipeline when repeated lookups are common.
- Keep an exception list for local review rather than embedding ad hoc manual overrides in code.
- Test hierarchy-based logic with known edge cases before applying it to a full cohort build.
Teams that do these three things usually move faster because they stop mixing one-off terminology fixes into operational code paths.
Best Practices for Production Systems
A prototype usually fails in production for boring reasons. An ETL job starts timing out on hierarchy expansion, a vocabulary refresh changes a mapping result, or five parallel workers hammer the same lookup endpoint and create avoidable retry storms. Production terminology design is mostly about making those failures predictable and controllable.
Follow a strict decision order
Use a deterministic mapping path first. For ETL and phenotype pipelines, start with direct lookup when the source code system is known, then resolve non-standard concepts through Maps to, then fall back to constrained search only for records that still need review, as outlined in the OMOP concept mapping guidance.
That order reduces drift over time. Search is useful, but it also creates the most review work and the highest chance of inconsistent analyst choices across runs. In production, reserve it for exception handling and queue the unresolved cases for review instead of letting fuzzy matches enter the main pipeline unreviewed.
Use the right hierarchy authority
Hierarchy logic should read from CONCEPT_ANCESTOR. That table is the graph you can build against for descendant expansion, rollups, and cohort logic.
Do not treat the CONCEPT table's is_hierarchical flag as the source of truth for traversal. It is descriptive metadata, not the hierarchy itself. If your client expands descendants programmatically, support pagination, retries, and rate control. Some source terminologies are deep enough that recursive testing against small examples will not expose the production behavior. SNOMED International documents that SNOMED CT is organized as a polyhierarchy, which is exactly why descendant retrieval needs disciplined client handling rather than ad hoc recursion (SNOMED CT Starter Guide).
Production checklist
- Cache repeated lookups. Common code resolutions and approved hierarchy expansions should come from cache when possible.
- Handle pagination explicitly. Broad descendant queries and search results can span multiple pages.
- Control request rate in the client. SDK support helps, but batch jobs and orchestrators still need concurrency limits and backoff.
- Persist vocabulary version context. A concept set without version context is hard to reproduce and hard to defend in audit.
- Protect API keys. Use scoped, revocable credentials. Keep them out of notebooks, screenshots, and shared scripts.
- Keep PHI out of terminology calls. Send codes, concept IDs, and vocabulary identifiers only.
OMOPHub vs. Self-hosted ATHENA
| Capability | Self-hosted ATHENA | OMOPHub |
|---|---|---|
| Setup time | 1–2 days | 5 minutes (get an API key) |
| Vocabulary updates | Manual re-download & re-load every ~6 months | Automatic, synced with ATHENA |
| Full-text / semantic / autocomplete search | Build your own | Built-in |
| REST API, Python SDK, R SDK, MCP server | Build your own | Included |
| FHIR Terminology Service | Build your own / deploy Snowstorm | Built-in |
| FHIR Concept Resolver (Coding → OMOP + CDM table) | Not a standard OHDSI tool | Built-in (POST /v1/fhir/resolve) |
| Infrastructure cost | $150–400/month (DB + compute) | Free tier; paid tiers for volume |
| Maintenance burden | Ongoing | Zero |
Self-hosting still fits some environments. Air-gapped networks, local terminology extensions, and strict data egress policies are common reasons to keep the stack in-house.
For many teams, the practical pattern is hybrid. Use OMOPHub to speed up mapping, validation, search, and hierarchy work during development. Then persist approved outputs, cache stable responses, and run controlled local processes where policy requires it. For implementation details, the OMOPHub documentation covers SDK behavior and operational setup.
Frequently Asked Questions
Does the API handle PHI
No. The vocabulary service is for terminology lookup and concept operations. Requests should contain codes, concept IDs, vocabulary identifiers, and search terms. They shouldn't contain patient identifiers, clinical notes, or full medical records.
Which vocabularies are included
The platform surface described here includes SNOMED CT, ICD-10, LOINC, RxNorm, and many other OMOP vocabularies across a broad standardized set. For day-to-day work, the key question isn't usually whether a major vocabulary is present. It's whether your workflow is using the right concept relationships and version context.
How often do vocabularies update
They're synchronized with official ATHENA releases. That means you should still treat version alignment as part of your workflow, especially for studies, regulated reporting, or any pipeline where reproducibility matters.
What about rate limits
Use the SDKs or your own client logic to handle pagination and backoff cleanly. In production, design for batching, caching, and retry behavior instead of firing uncontrolled parallel requests.
Should I self-host or use an API
If you need complete local control for policy or network reasons, self-hosting can be appropriate. If your main pain is operational overhead and repeated custom tooling around search, mapping, and hierarchy traversal, an API-driven model is usually easier to maintain.
Where should I start if I'm evaluating fit
Start with a known code-resolution workflow or a small phenotype concept set. If those two paths work cleanly in your environment, the rest of the integration usually follows without much surprise.
If you want to stop treating vocabularies like infrastructure and start using them like a service, take a look at OMOPHub. It's a practical way to search concepts, resolve codes, traverse hierarchies, and wire OMOP terminology operations into ETL, FHIR, and research workflows without standing up the whole stack yourself.


