ICD-10 Code Lookup API: Search Diagnoses and Procedures Programmatically
ICD-10 has 126,000+ codes across diagnoses (CM) and procedures (PCS). Here's how to look up codes, search by description, and get FHIR codings and HCC mappings — with working TypeScript examples.

ICD-10 is the backbone of clinical coding in the US. Every diagnosis on a claim, every procedure in an EHR, every risk adjustment model — they all reference ICD-10 codes. But working with the code set programmatically is painful: CMS publishes flat files with inconsistent formatting, and the sheer volume (72,000+ CM codes, 54,000+ PCS codes) makes local lookups unwieldy.
This tutorial shows how to look up, search, and batch-process ICD-10 codes using FHIRfly's API and TypeScript SDK.
ICD-10-CM vs. ICD-10-PCS
The US uses two ICD-10 code sets:
- ICD-10-CM (Clinical Modification) — diagnosis codes like
E11.9(Type 2 diabetes without complications). Used on all claims. - ICD-10-PCS (Procedure Coding System) — inpatient procedure codes like
02HA0QZ(insertion of device in heart). Used only on inpatient claims.
FHIRfly covers both in a single endpoint. The API auto-detects which code system you're querying based on the code format.
Setup
npm install @fhirfly-io/terminology
import { Fhirfly } from "@fhirfly-io/terminology";
const fhirfly = new Fhirfly({ apiKey: process.env.FHIRFLY_API_KEY! });
Free tier includes 10,000 requests/month — get your key here.
Look Up a Single Code
The most common operation: you have an ICD-10 code and need the description and metadata.
// Diagnosis code (ICD-10-CM)
const result = await fhirfly.icd10.lookup("E11.9", { shape: "standard" });
console.log(result.data.code);
// "E11.9"
console.log(result.data.type);
// "cm"
console.log(result.data.display);
// "Type 2 diabetes mellitus without complications"
console.log(result.data.chapter);
// "4"
console.log(result.data.chapter_description);
// "Endocrine, nutritional and metabolic diseases"
console.log(result.data.billable);
// true
// Procedure code (ICD-10-PCS)
const proc = await fhirfly.icd10.lookup("02HA0QZ", { shape: "standard" });
console.log(proc.data.display);
// "Insertion of Infusion Device into Heart, Open Approach"
console.log(proc.data.body_system);
// "Heart and Great Vessels"
console.log(proc.data.root_operation);
// "Insertion"
Response Shapes
| Shape | Fields | Best for |
|---|---|---|
compact | Code, type (cm/pcs), display name | Autocomplete, search results |
standard | + Chapter, section, billable flag, FHIR coding, HCC mappings, SNOMED | Claims processing, detail views |
full | + Includes/excludes notes, code-first rules, effective dates, PCS components | Compliance auditing, coding tools |
FHIR-Ready Coding
Every response includes a pre-built FHIR coding:
const result = await fhirfly.icd10.lookup("J18.9", { shape: "standard" });
console.log(result.data.fhir_coding);
// {
// system: "http://hl7.org/fhir/sid/icd-10-cm",
// code: "J18.9",
// display: "Pneumonia, unspecified organism"
// }
Drop this directly into a FHIR Condition.code or Encounter.reasonCode.
Search by Description
When users need to find a code from a clinical description — or when you're mapping free-text diagnoses to ICD-10:
const results = await fhirfly.icd10.search(
{ q: "type 2 diabetes", billable: true },
{ limit: 10 }
);
console.log(`Found ${results.total} billable codes matching "type 2 diabetes"`);
for (const code of results.items) {
console.log(`${code.code} — ${code.display}`);
}
// "E11.9 — Type 2 diabetes mellitus without complications"
// "E11.65 — Type 2 diabetes mellitus with hyperglycemia"
// "E11.21 — Type 2 diabetes mellitus with diabetic nephropathy"
// ...
Search Filters
Narrow results with structured filters:
// Only diagnosis codes
await fhirfly.icd10.search({ q: "fracture femur", code_system: "CM" });
// Only billable codes (leaf nodes)
await fhirfly.icd10.search({ q: "hypertension", billable: true });
// Filter by chapter
await fhirfly.icd10.search({ q: "infection", chapter: "1" }); // Infectious diseases
// PCS: filter by body system and root operation
await fhirfly.icd10.search({
q: "knee",
code_system: "PCS",
body_system: "Lower Joints",
root_operation: "Replacement",
});
// Sort by code for organized output
await fhirfly.icd10.search(
{ q: "acute myocardial infarction" },
{ sort: "code" }
);
Pagination
let page = 1;
let hasMore = true;
while (hasMore) {
const results = await fhirfly.icd10.search(
{ q: "neoplasm", code_system: "CM", billable: true },
{ limit: 50, page }
);
for (const code of results.items) {
await processCode(code);
}
hasMore = results.has_more;
page++;
}
HCC Risk Adjustment Mappings
For Medicare Advantage and risk adjustment workflows, the standard shape includes HCC (Hierarchical Condition Category) mappings:
const result = await fhirfly.icd10.lookup("E11.9", { shape: "standard" });
console.log(result.data.hcc);
// [{ cc_number: 19, model_version: "V28", model_type: "CMS-HCC" }]
This tells you that E11.9 maps to HCC 19 (Diabetes without Complication) in the CMS-HCC V28 model. Essential for risk adjustment factor (RAF) score calculations.
The full shape includes additional HCC detail like payment year and release type — useful for auditing which model version applies to a specific date of service.
SNOMED CT Cross-References
ICD-10-CM codes include SNOMED CT mappings where available:
const result = await fhirfly.icd10.lookup("I10", { shape: "standard" });
console.log(result.data.snomed);
// [{ concept_id: "38341003", term: "Hypertensive disorder" }]
Useful when you need to bridge between ICD-10 (billing) and SNOMED CT (clinical) terminologies.
Batch Lookups
Processing a claims file with hundreds of diagnosis codes? Use the batch endpoint:
const response = await fhirfly.icd10.lookupMany(
["E11.9", "I10", "J18.9", "Z99.99"],
{ shape: "standard" }
);
for (const result of response.results) {
if (result.status === "ok") {
const billable = result.data.billable ? "billable" : "header";
console.log(`${result.input}: ${result.data.display} (${billable})`);
} else {
console.log(`${result.input}: ${result.status}`);
}
}
// "E11.9: Type 2 diabetes mellitus without complications (billable)"
// "I10: Essential (primary) hypertension (billable)"
// "J18.9: Pneumonia, unspecified organism (billable)"
// "Z99.99: not_found"
Batch accepts up to 100 codes per request. You can mix CM and PCS codes in the same batch.
Coding Rules (Full Shape)
The full shape exposes ICD-10-CM coding rules that are critical for compliance:
const result = await fhirfly.icd10.lookup("E11.9", { shape: "full" });
// Excludes1: codes that can NEVER be used with this code
console.log(result.data.excludes1);
// ["E13.- drug or chemical induced diabetes mellitus"]
// Use additional: codes that should be coded additionally
console.log(result.data.use_additional);
// ["Use additional code to identify control using insulin (Z79.4)"]
These rules help build compliant coding suggestion tools — flagging invalid code combinations before claims submission.
REST API (Without the SDK)
# Single lookup
curl -H "x-api-key: $FHIRFLY_API_KEY" \
"https://api.fhirfly.io/v1/icd10/E11.9?shape=standard"
# Search
curl -H "x-api-key: $FHIRFLY_API_KEY" \
"https://api.fhirfly.io/v1/icd10/search?q=diabetes&billable=true&limit=10"
# Batch
curl -X POST -H "x-api-key: $FHIRFLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"codes": ["E11.9", "I10", "J18.9"]}' \
"https://api.fhirfly.io/v1/icd10/_batch?shape=standard"
Common Use Cases
| Use Case | Approach |
|---|---|
| Claims enrichment | Batch lookup with standard shape |
| Diagnosis search in EHR | Search with billable: true, compact shape |
| HCC/RAF calculation | Lookup with standard shape, read hcc field |
| Code validation | Batch lookup, check for not_found status |
| FHIR Condition resources | Lookup, use fhir_coding field |
| Coding compliance checks | Lookup with full shape, check excludes/includes |
| ICD-10 to SNOMED mapping | Lookup with standard shape, read snomed field |
Key Takeaways
- 126K+ codes across ICD-10-CM (diagnoses) and ICD-10-PCS (procedures)
- Auto-detection — the API knows whether your code is CM or PCS
- Billable flag — instantly identify leaf-node codes valid for claims
- HCC mappings — built-in risk adjustment crosswalks
- SNOMED cross-references — bridge billing and clinical terminologies
- FHIR coding included — ready for FHIR resources
- Batch endpoint — up to 100 codes per request
Next Steps
- Get a free API key from the FHIRfly dashboard
- Install the SDK:
npm install @fhirfly-io/terminology - Try searching for codes in your domain
- Check the ICD-10 API docs for the complete parameter reference
Related Posts
Written by The FHIRfly Team — a collective of healthcare data experts, AI specialists, and industry veterans building better clinical coding APIs.