ICD-10 API Lookup: A Practical Developer's Guide for 2026

You're trying to wire an ICD-10 API lookup into a product, and the first problem isn't code, it's terminology. The moment you search for “ICD-10,” you run into different scopes, different update rhythms, and different access patterns, so a clean lookup can turn into a messy integration if you pick the wrong endpoint on day one.
The practical move is to treat this as a vocabulary decision, not just a search problem. If you need diagnosis coding in a U.S. workflow, ICD-10-CM is not the same thing as WHO's international ICD-10, and procedure coding adds a third layer of complexity with ICD-10-PCS. That split is exactly why teams end up juggling public APIs, browser tools, and internal crosswalk logic when they only wanted a reliable code lookup.
Why ICD-10 API Lookups Are So Confusing
The confusion starts with the name itself. ICD-10 is a family of resources, not one uniform dataset. WHO maintains the international terminology service, the U.S. clinical environment leans on ICD-10-CM for diagnoses, and procedure workflows often need ICD-10-PCS, which is a separate coding system altogether.
That distinction matters because the APIs are built for different jobs. The WHO ICD API is documented as a cloud-hosted service at id.who.int and requires OAuth 2 client credentials over HTTPS only. By contrast, the National Library of Medicine's ICD-10-CM lookup is exposed as a free public service at the NLM Clinical Tables ICD-10-CM API, and the documentation says it's offered “as is” and free of charge.

Two public paths, two different operating models
WHO's service is the authoritative international reference platform for ICD terminology, and its documentation shows versioned endpoints for both ICD-10 and ICD-11. The guide also points to a token service at https://icdaccessmanagement.who.int/connect/token, which makes it suitable for systems that already handle OAuth-based integration patterns.
NLM's ICD-10-CM service is simpler to get running. Its documentation says the API is no-auth required and updated annually, with the current release listed as 2026. It also supports access through the FHIR ValueSet $expand operation, so it can fit into interoperability workflows rather than living as a standalone lookup utility.
That split creates a real trap for developers. A search for “ICD-10 API lookup” often mixes WHO ICD-10, U.S. ICD-10-CM, and procedure codes in one result set, even though those resources differ in data model, authentication, and maintenance cadence. The result is predictable, mismatched code coverage and brittle integrations.
Practical rule: choose the code set first, then choose the API. If the workflow is clinical diagnosis in the U.S., don't assume WHO ICD-10 is interchangeable with ICD-10-CM.
If you need a quick refresher on how crosswalks behave in medical coding, the overview at what a crosswalk is in medical terminology work is a useful companion. For a clinical coding example that sits in the same ecosystem, mastering weight loss claim documentation shows why the code family matters before anyone writes integration logic.
WHO's search mechanics also show how specific ICD-10 handling gets under the hood. The documented search endpoint is GET /icd/release/10/{release_id}/search?q={query}&useFlexisearch=false&flatResults=true, and code lookup is GET /icd/release/10/{release_id}/{code}. Common release_id values include 2019, 2016, and 2010, with 2019 recommended for current ICD-10 use, so even a seemingly simple lookup has release-management implications. The WHO ICD API documentation also notes that 2019 is the common current release identifier for ICD-10 search, which reinforces that the modern stack still carries release-specific behavior.
Unifying Your Workflow with a Terminology Service
A fragmented ICD-10 workflow usually breaks at the integration layer first. One team calls a WHO endpoint, another depends on NLM, and a third keeps a local crosswalk in sync by hand. A unified terminology service removes that split by giving your application one surface for search, mapping, and code resolution.
OMOP-oriented terminology infrastructure makes that consolidation practical. A managed service can expose the same REST and FHIR interface across a broad vocabulary set, so the same lookup pattern works for ICD-10-CM, SNOMED CT, LOINC, RxNorm, and other OMOP vocabularies without forcing client code to change every time the code system changes.

Why one service beats a pile of endpoints
Self-hosting a vocabulary stack sounds simple until you have to keep it current. A self-hosted ATHENA setup takes 1-2 days to stand up, needs manual updates every ~6 months, and carries infrastructure costs of $150–400/month for the database and compute layer. A managed alternative shortens the path to first request and removes the recurring import work that comes with scheduled updates.
That operational difference matters because terminology infrastructure rarely sits still. EHR integrations, research pipelines, and NLP systems all depend on the same vocabulary layer, and each extra endpoint adds another place for drift, auth failures, and release mismatches to enter the system.
A well-designed terminology service also keeps vocabulary boundaries out of application code. Your client asks one API, receives one predictable concept object, and lets the service handle mapping traversal behind the scenes. That is a cleaner architecture than pushing crosswalk logic into every caller.
The true benefit isn't just fewer requests. It's fewer places where code meaning can drift between source systems and analytics.
If you are evaluating managed vocabulary tooling, OMOPHub is one option in this category. It exposes programmatic access to the OHDSI ATHENA vocabulary set through REST and FHIR, and the OMOP vocabulary API guide is useful if you want to see how that layer fits into a broader lookup workflow.
How to Perform ICD-10 Lookups with OMOPHub
The cleanest implementation starts with a simple rule. Resolve by code first, then layer on text search only when you need recall for user-entered terms or messy source data. That keeps your lookup path deterministic, which is what you want in production clinical software.
The web lookup tool at OMOPHub concept lookup is handy for validating a code before you bake it into application logic, and the same terminology layer is available through SDKs. If you need a broader vocabulary reference, the OMOP vocabulary API guide is the right companion piece.
Python lookup pattern
A basic workflow with the Python SDK should authenticate with an API key and search by the ICD-10-CM code you already have in hand.
from omophub import OMOPHubClient
client = OMOPHubClient(api_key="oh_your_api_key")
result = client.vocabulary.search(
vocabulary_ids=["ICD10CM"],
query="E11.9"
)
print(result)
A response from a lookup like this should be read as a vocabulary object, not just a label. The fields you care about are the concept name, the vocabulary identifier, and whether the code is marked as standard for analytics or is serving as a source term.
R lookup pattern
The R interface follows the same logic. Use the code as your primary key, keep the lookup narrow, and expand only if you need broader term matching.
library(omophub)
res <- omophub::concept_lookup(
query = "E11.9",
vocabulary_ids = c("ICD10CM")
)
print(res)
The NLM ICD-10-CM API documents a similar search pattern in its own tooling. Its R interface exposes icd10api() with icd_code, term, field, and limit, and the default limit is 500L. That makes the broader lesson pretty clear, exact-code lookup and term-based retrieval solve different problems, so don't conflate them.
When semantic search helps
Semantic and fuzzy search are useful when the source system stores a messy problem list entry or a clinician types something that doesn't match the canonical term exactly. Use that for discovery, not for final normalization. Final mappings should still resolve to a stable concept before they land in analytics or reporting.
For code lookup work, the critical habit is to separate the human search step from the machine normalization step. Search can be forgiving. Mapping can't.
Advanced Mapping from ICD-10 to OMOP Concepts
A code lookup tells you what a code means. A mapping tells your pipeline what to do with it. That difference is the whole reason standardized terminology services matter in ETL, analytics, and clinical warehousing.
The useful pattern is to resolve a source ICD-10-CM code into its OMOP standard concept in one call, then preserve the mapping metadata alongside the record. The resolution endpoint can handle the traversal for you, so your application doesn't need to chase relationship chains or guess which concept is the correct standardized target.

Mapping should end in a standard concept
The core workflow is simple. Send the source code, resolve it against the vocabulary service, and store the returned standard concept for downstream analytics. OMOPHub can resolve a FHIR system URI + code and return the standard concept, domain, mapping type, and CDM target table in one API call, with Maps to traversal handled server-side.
That matters because the target object is more than just a string label. The domain tells you where the concept belongs in OMOP, the mapping type tells you how the translation happened, and the CDM target table gives your ETL layer the destination shape without extra branch logic.
Batch workflows matter too. When you're processing larger files, translate codes in batches instead of making one request per row. That reduces repeated network overhead and keeps your pipeline simpler to reason about under load.
Good ETL habit: treat the mapping response as lineage data. Keep the source code, resolved concept, and mapping metadata together so you can audit later.
If you're specifically mapping diagnosis codes into clinical research structures, the guide on mapping ICD-10 to SNOMED CT is the most relevant companion resource. It fits well with the pattern above because the goal is the same, preserve meaning while normalizing source vocabulary.
A strong mapping layer also makes downstream phenotype logic cleaner. Instead of encoding source-system exceptions throughout your analysis, you normalize once and let the model work off standard concepts consistently.
Building Performant and Compliant Lookup Features
Production terminology features need three things at once, security, speed, and a clear compliance story. If you solve only one of those, the integration still fails somewhere else in the stack.
OMOPHub is a vocabulary lookup service that receives terminology codes and concept IDs, never Protected Health Information. Access is via per-user, revocable, scopeable Bearer API keys over HTTPS (TLS 1.2+). That makes the service fit neatly into environments where teams want vocabulary access without sending patient records through the terminology layer.
Security patterns that hold up in real systems
Store the API key the same way you'd store any production secret, not in client code and not in an environment that gets copied into logs. Use one key per user or service account so revocation is practical when a team changes or a credential leaks.
For application design, keep lookup calls server-side whenever possible. That lets you control key exposure, shape requests before they leave your network boundary, and cache the most common responses close to your app.
Performance without overengineering
A terminology lookup feature doesn't need to be expensive to be reliable. Cache repeated code resolutions on your side, especially for common diagnosis codes and the vocabulary hits you already know will recur. That reduces call volume and keeps user-facing flows snappy without turning your app into a second vocabulary database.
The better architectural pattern is to cache intentionally, not indiscriminately. Cache stable code-to-concept mappings, but still leave room for vocabulary refresh logic so you don't freeze a stale translation into production for months.
Compliance gets easier when the terminology layer stays outside the patient record itself. You're moving codes, concepts, and vocabulary IDs, not notes, identifiers, or encounter text. That's a simpler boundary for security review and a cleaner one for audit documentation.
Troubleshooting Common Issues and Pro Tips
A lookup that looks correct in the UI can still fail in production because the vocabulary family is wrong. Teams often type “ICD10” into their code and expect the API to infer the exact family, but ICD10CM is a different target from a WHO ICD resource, and procedure codes sit in yet another branch. Check the vocabulary ID first, then verify whether the request is meant for diagnosis, procedure, or international ICD content.
A second failure mode is treating every returned code as ready for analytics. A concept can have a valid label and still not be the standard concept you want to join into downstream tables, so inspect the standard_concept field before you store the mapping. That check matters in the code path, not just in a one-off manual review, because bad mappings tend to spread once they enter a pipeline.
Use the OMOPHub concept lookup tool for debugging queries before you wire the same request into application code: the OMOPHub concept lookup tool for debugging queries. Confirm the vocabulary ID, the search term, and the returned concept, then mirror that request shape in your service layer. The tool is useful because it shows whether the problem is your code, your vocabulary choice, or the way you interpret the result.
Practical debugging checklist
- Confirm the code family: Target the right vocabulary, especially when a U.S. diagnosis code should not be treated like the WHO international release.
- Check standardness: Review the concept metadata before you save any mapping for analytics or reporting.
- Test the smallest query first: Start with one code, then move to batch workflows after the single lookup behaves the way you expect.
- Keep the lookup path consistent: Use the same service for search and resolution so you do not introduce hidden translation differences between screens, jobs, or services.
For implementation details, the main documentation at OMOPHub docs and the SDK repositories for Python, R, and MCP are the right places to inspect request shapes and client patterns. The SDKs cut down on raw API glue code, which makes it easier to keep lookup behavior aligned across services and languages.
If the feature still feels brittle, the problem is usually vocabulary selection or how the response gets interpreted, not the lookup endpoint itself. Tighten the code family, inspect the mapping metadata, and keep the production path on one consistent terminology service. That is the difference between a quick demo and a lookup layer that survives real clinical workflows.


