ICD-10-CM Search
Status:
stableCategory:lookupAdded:2026-10-14Last reviewed:2026-10-14
Summary
Type-ahead search across the US ICD-10-CM diagnosis code set. Pass a
code fragment (S62.0, s620) or plain words (heart attack) and get
back matching categories, subcategories and codes, closest first.
Designed to power a diagnosis picker; safe to call on every keystroke
once q is at least two characters.
The code set is ICD-10-CM (the US clinical modification), not WHO
ICD-10 and not ICD-10-PCS. Every response names the release it
reflects (for example FY2027), because a code's validity is tied to
the year.
Endpoint
| Field | Value |
|---|---|
| Method | GET |
| Path | /api/lookup/icd10cm/search |
| Full URL | https://engine.tripod-health.com/api/lookup/icd10cm/search |
| Authentication | API key (required) |
| Request body | none |
| Response body | application/json |
| Idempotent | Yes |
| Rate-limited | Yes |
Authentication
Send a valid API key in the apikey header. See
authentication.md.
Request
Headers
| Header | Required | Description |
|---|---|---|
apikey | Yes | Consumer API key. |
Path parameters
None.
Query parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
q | string | Yes | — | Search text. Minimum two characters. A code-shaped value (a letter then a digit, such as S6, S62.0 or s620) is matched as a code prefix, with or without the dot and in any case. Anything else is matched word by word, as word prefixes, against the official descriptions, the inclusion terms and the alphabetic index — so heart attack finds I21.9. |
billable | string | No | — | true returns only billable codes; false returns only non-billable headers. Omit it to get both. Any other value is a 400. |
limit | int | No | 10 | Maximum results to return. Range 1–50. |
Results are ranked in this order: an exact code match; code-prefix
matches, shorter codes first; text matches, a hit on the description
above a hit on an inclusion or index term, billable codes above
headers. When those return fewer than limit rows, a typo-tolerant
match on the descriptions fills the remainder (diabetis still finds
diabetes codes).
Chapters and sections are never returned by search. Browse them with
/api/lookup/icd10cm/tree.
Body
None.
Response
Success — 200 OK
Request: GET /api/lookup/icd10cm/search?q=heart%20attack&limit=5
{
"results": [
{
"code": "I21.9",
"label": "Acute myocardial infarction, unspecified",
"kind": "code",
"billable": true
},
{
"code": "I20.9",
"label": "Angina pectoris, unspecified",
"kind": "code",
"billable": true
},
{
"code": "I45.9",
"label": "Conduction disorder, unspecified",
"kind": "code",
"billable": true
},
{
"code": "R55",
"label": "Syncope and collapse",
"kind": "code",
"billable": true
},
{
"code": "F45.8",
"label": "Other somatoform disorders",
"kind": "code",
"billable": true
}
],
"release": "FY2027",
"request_id": "04b584c6-7c44-4166-b98a-3e5f525f8df3",
"timestamp": "2026-10-14T00:15:09.507Z"
}
label is always the code's official description, so a result that
matched on an inclusion or index term need not repeat the words you
typed.
results is always present. An empty array is a normal response (the
query matched nothing), not an error.
Response fields
| Field | Type | Always present | Description |
|---|---|---|---|
results | array | Yes | Zero or more matches, in rank order. |
results[].code | string | Yes | The code, always uppercase and dotted after the third character (S62.001A, R55). |
results[].label | string | Yes | The official long description. |
results[].kind | string | Yes | category (three-character header), subcategory (a longer header), or code (billable). |
results[].billable | boolean | Yes | true when the code is valid on a claim. Headers are false. Test this field, not kind. |
release | string | null | Yes | The ICD-10-CM release the results reflect, e.g. FY2027. |
request_id | string | Yes | Correlation ID. Quote in support tickets. |
timestamp | string (ISO 8601 UTC) | Yes | Server time when the response was emitted. |
Status codes
| Code | Meaning | When |
|---|---|---|
200 | OK | Search ran. results may be empty. |
400 | ValidationError | q missing or shorter than two characters, billable not true/false, limit out of range, or a parameter repeated. field names the offender. |
401 | Unauthenticated | Missing or invalid API key. |
429 | RateLimited | Per-consumer rate limit exceeded. |
500 | InternalError | Unexpected failure. Quote request_id in the ticket. |
Examples
curl
curl -sS "https://engine.tripod-health.com/api/lookup/icd10cm/search?q=heart%20attack&limit=5" \
-H "apikey: $ENGINE_API_KEY"
Code prefix, billable codes only
curl -sS "https://engine.tripod-health.com/api/lookup/icd10cm/search?q=S62.00&billable=true&limit=3" \
-H "apikey: $ENGINE_API_KEY"
{
"results": [
{
"code": "S62.001A",
"label": "Unspecified fracture of navicular [scaphoid] bone of right wrist, initial encounter for closed fracture",
"kind": "code",
"billable": true
},
{
"code": "S62.001B",
"label": "Unspecified fracture of navicular [scaphoid] bone of right wrist, initial encounter for open fracture",
"kind": "code",
"billable": true
},
{
"code": "S62.001D",
"label": "Unspecified fracture of navicular [scaphoid] bone of right wrist, subsequent encounter for fracture with routine healing",
"kind": "code",
"billable": true
}
],
"release": "FY2027",
"request_id": "af6753ff-37c0-45cd-9d9f-cbda57ffb4ed",
"timestamp": "2026-10-14T00:15:28.681Z"
}
Python (requests)
# Uses the call() helper from quickstart.md.
from urllib.parse import quote
result = call("GET", f"/api/lookup/icd10cm/search?q={quote('heart attack')}&billable=true")
print("release:", result["release"])
for row in result["results"]:
print(f"{row['code']:9} {row['label']}")
Node.js (native fetch)
// Uses the call() helper from quickstart.md.
const q = encodeURIComponent("heart attack");
const result = await call("GET", `/api/lookup/icd10cm/search?q=${q}&billable=true`);
for (const row of result.results) {
console.log(`${row.code.padEnd(9)} ${row.label}`);
}
TypeScript
interface Icd10cmSearchResult {
code: string;
label: string;
kind: "category" | "subcategory" | "code";
billable: boolean;
}
interface Icd10cmSearchResponse {
results: Icd10cmSearchResult[];
release: string | null;
request_id: string;
timestamp: string;
}
const result = await call<Icd10cmSearchResponse>(
"GET",
"/api/lookup/icd10cm/search?q=S62.0&billable=true",
);
Error scenarios
q too short
Send:
curl -sS "https://engine.tripod-health.com/api/lookup/icd10cm/search?q=h" \
-H "apikey: $ENGINE_API_KEY" \
-w "\nHTTP %{http_code}\n"
Receive (400):
{
"timestamp": "2026-10-14T00:15:27.698Z",
"error": "ValidationError",
"message": "Query parameter 'q' must be at least 2 characters",
"field": "q",
"request_id": "a946add1-3a79-4db7-8239-713fe36d89bd"
}
Invalid billable
Send:
curl -sS "https://engine.tripod-health.com/api/lookup/icd10cm/search?q=S62&billable=yes" \
-H "apikey: $ENGINE_API_KEY" \
-w "\nHTTP %{http_code}\n"
Receive (400):
{
"timestamp": "2026-10-14T00:15:28.327Z",
"error": "ValidationError",
"message": "Query parameter 'billable' must be true or false",
"field": "billable",
"request_id": "822b5d25-6a2b-4ac2-a3f4-a4707f299e45"
}
Intended use
- Diagnosis pickers and autocomplete where a user types either a code fragment or everyday words and picks a code.
- Claim-entry forms that must only offer codes valid on a claim:
pass
billable=true. - Translating lay or index vocabulary into codes — the search covers the alphabetic index, so terms that never appear in an official description still find their code.
Mistaken use
- Do not use search to fetch a code you already have. Use
/api/lookup/icd10cm/get— one record with its notes and every ancestor's notes. - Do not treat search results as coding advice. A match means the
words or code fragment matched; whether the code is correct for a
case depends on the coding notes. Read them via
/api/lookup/icd10cm/get. - Do not use search to browse chapters or sections. They are never
returned here. Use
/api/lookup/icd10cm/tree. - Do not test
kindto decide whether a code is billable. Use thebillablefield — a three-character code such asR55is billable.
Debugging
- Capture
request_id. Present in every response body. 400 ValidationErrorwithfield: "q". The text was missing or shorter than two characters. UI clients should not send the request until the user has typed at least two characters.- Expected code missing from results. Raise
limit, or narrowq— a broad word such asfracturematches thousands of codes and only the toplimitare returned. If you passbillable=true, headers such asS62are excluded. - Results reflect a different year than you expected. Check
release; the code set changes every fiscal year.
Rate limits
See rate-limits.md for the current per-consumer limits.
Related
- lookup-icd10cm-get.md — one code's full record with coding notes.
- lookup-icd10cm-tree.md — browse the chapter, section and category hierarchy.
- lookup-cpt-search.md — the same search shape over procedure codes.
- lookup-naics-search.md,
lookup-regulations-search.md — the
other lookup resources, which validate
qandlimitthe same way. - authentication.md, errors.md, rate-limits.md, conventions.md — cross-cutting contract rules.
Change history
| Date | Change |
|---|---|
| 2026-10-14 | Initial publication. |
| 2026-10-14 | The engine assigns every request ID; an X-Request-ID request header is not used. |