Loading documentation

Access required

Your account doesn't have access to the documentation. Contact your administrator.

Sign out
Skip to main content

CPT Search

Status: stable Category: lookup Added: 2026-10-14 Last reviewed: 2026-10-14

Summary​

Type-ahead search across the engine's CPT codebook. Pass a code prefix (9921) or words from a descriptor (office visit) and get back matching procedure codes, closest first. Designed to power a procedure picker; safe to call on every keystroke once q is at least two characters.

The codebook is curated, not the full CPT code set. It covers the procedures relevant to occupational health delivered virtually: office and telehealth visits, work-related and medical disability evaluations, physical and occupational therapy, behavioral health, remote monitoring, and care management. A well-formed CPT code outside it is not found. Every response names the CPT release year the codebook reflects.

Endpoint​

FieldValue
MethodGET
Path/api/lookup/cpt/search
Full URLhttps://engine.tripod-health.com/api/lookup/cpt/search
AuthenticationAPI key (required)
Request bodynone
Response bodyapplication/json
IdempotentYes
Rate-limitedYes

Authentication​

Send a valid API key in the apikey header. See authentication.md.

Request​

Headers​

HeaderRequiredDescription
apikeyYesConsumer API key.

Path parameters​

None.

Query parameters​

ParameterTypeRequiredDefaultDescription
qstringYes—Search text. Minimum two characters. A code-shaped value (one to four digits, optionally followed by a fifth digit or a category letter F, T, U or M, such as 9921 or 0001U) is matched as a code prefix. Anything else is matched word by word, as word prefixes, against the descriptors.
billablestringNo—true or false. Every code the search returns is billable, so false returns an empty list; the parameter exists so one client works across every code-set lookup. Any other value is a 400.
limitintNo10Maximum results to return. Range 1–50.

Results are ranked in this order: an exact code match; code-prefix matches, shorter codes first; descriptor text matches. When those return fewer than limit rows, a typo-tolerant match on the descriptors fills the remainder.

Sections, subsections and headings are never returned by search. Browse them with /api/lookup/cpt/tree.

Body​

None.

Response​

Success — 200 OK​

Request: GET /api/lookup/cpt/search?q=office%20visit&limit=5

{
"results": [
{
"code": "99211",
"label": "Office or other outpatient visit for the evaluation and management of an established patient that may not require the presence of a physician or other qualified health care professional",
"kind": "code",
"billable": true
},
{
"code": "99202",
"label": "Office or other outpatient visit for the evaluation and management of a new patient, which requires a medically appropriate history and/or examination and straightforward medical decision making. When using total time on the date of the encounter for code selection, 15 minutes must be met or exceeded",
"kind": "code",
"billable": true
},
{
"code": "99212",
"label": "Office or other outpatient visit for the evaluation and management of an established patient, which requires a medically appropriate history and/or examination and straightforward medical decision making. When using total time on the date of the encounter for code selection, 10 minutes must be met or exceeded",
"kind": "code",
"billable": true
},
{
"code": "99203",
"label": "Office or other outpatient visit for the evaluation and management of a new patient, which requires a medically appropriate history and/or examination and low level of medical decision making. When using total time on the date of the encounter for code selection, 30 minutes must be met or exceeded",
"kind": "code",
"billable": true
},
{
"code": "99204",
"label": "Office or other outpatient visit for the evaluation and management of a new patient, which requires a medically appropriate history and/or examination and moderate level of medical decision making. When using total time on the date of the encounter for code selection, 45 minutes must be met or exceeded",
"kind": "code",
"billable": true
}
],
"release": "2026",
"request_id": "e4892f24-bba2-4f02-bc94-14141beef14f",
"timestamp": "2026-10-14T00:15:58.007Z"
}

Text matches are ordered by relevance, not by code, so equally good matches can interleave (99211, 99202, 99212). Sort client-side if you need code order.

results is always present. An empty array is a normal response (the query matched nothing in the codebook), not an error.

Response fields​

FieldTypeAlways presentDescription
resultsarrayYesZero or more matches, in rank order.
results[].codestringYesThe five-character CPT code. Treat as text: codes such as 0001U carry letters and leading zeros.
results[].labelstringYesThe code's long descriptor.
results[].kindstringYesAlways code in search results.
results[].billablebooleanYesAlways true in search results.
releasestring | nullYesThe CPT year the codebook reflects, e.g. 2026.
request_idstringYesCorrelation ID. Quote in support tickets.
timestampstring (ISO 8601 UTC)YesServer time when the response was emitted.

Status codes​

CodeMeaningWhen
200OKSearch ran. results may be empty.
400ValidationErrorq missing or shorter than two characters, billable not true/false, limit out of range, or a parameter repeated. field names the offender.
401UnauthenticatedMissing or invalid API key.
429RateLimitedPer-consumer rate limit exceeded.
500InternalErrorUnexpected failure. Quote request_id in the ticket.

Examples​

curl​

curl -sS "https://engine.tripod-health.com/api/lookup/cpt/search?q=office%20visit&limit=5" \
-H "apikey: $ENGINE_API_KEY"

Code prefix​

curl -sS "https://engine.tripod-health.com/api/lookup/cpt/search?q=9921" \
-H "apikey: $ENGINE_API_KEY"
{
"results": [
{
"code": "99211",
"label": "Office or other outpatient visit for the evaluation and management of an established patient that may not require the presence of a physician or other qualified health care professional",
"kind": "code",
"billable": true
},
{
"code": "99212",
"label": "Office or other outpatient visit for the evaluation and management of an established patient, which requires a medically appropriate history and/or examination and straightforward medical decision making. When using total time on the date of the encounter for code selection, 10 minutes must be met or exceeded",
"kind": "code",
"billable": true
},
{
"code": "99213",
"label": "Office or other outpatient visit for the evaluation and management of an established patient, which requires a medically appropriate history and/or examination and low level of medical decision making. When using total time on the date of the encounter for code selection, 20 minutes must be met or exceeded",
"kind": "code",
"billable": true
},
{
"code": "99214",
"label": "Office or other outpatient visit for the evaluation and management of an established patient, which requires a medically appropriate history and/or examination and moderate level of medical decision making. When using total time on the date of the encounter for code selection, 30 minutes must be met or exceeded",
"kind": "code",
"billable": true
},
{
"code": "99215",
"label": "Office or other outpatient visit for the evaluation and management of an established patient, which requires a medically appropriate history and/or examination and high level of medical decision making. When using total time on the date of the encounter for code selection, 40 minutes must be met or exceeded",
"kind": "code",
"billable": true
}
],
"release": "2026",
"request_id": "c66c43e5-2cc1-4e92-b8ff-efae77427264",
"timestamp": "2026-10-14T00:15:58.449Z"
}

Python (requests)​

# Uses the call() helper from quickstart.md.
from urllib.parse import quote

result = call("GET", f"/api/lookup/cpt/search?q={quote('physical therapy')}&limit=5")
for row in result["results"]:
print(f"{row['code']} {row['label'][:80]}")

Node.js (native fetch)​

// Uses the call() helper from quickstart.md.
const result = await call("GET", "/api/lookup/cpt/search?q=9921");
for (const row of result.results) {
console.log(`${row.code} ${row.label.slice(0, 80)}`);
}

TypeScript​

interface CptSearchResult {
code: string;
label: string;
kind: "code";
billable: boolean;
}

interface CptSearchResponse {
results: CptSearchResult[];
release: string | null;
request_id: string;
timestamp: string;
}

const result = await call<CptSearchResponse>("GET", "/api/lookup/cpt/search?q=9921");

Error scenarios​

q too short​

Send:

curl -sS "https://engine.tripod-health.com/api/lookup/cpt/search?q=9" \
-H "apikey: $ENGINE_API_KEY" \
-w "\nHTTP %{http_code}\n"

Receive (400):

{
"timestamp": "2026-10-14T00:16:06.742Z",
"error": "ValidationError",
"message": "Query parameter 'q' must be at least 2 characters",
"field": "q",
"request_id": "013114bf-dab2-4284-a273-66db7ac89d57"
}

Intended use​

  • Procedure pickers and autocomplete for occupational-health visits, evaluations, therapy, behavioral health and monitoring services.
  • Resolving a partial code a user remembers (9921) into the full list of candidates with their descriptors.
  • Feeding a price lookup. Pick a code here, then price it for a jurisdiction with /api/lookup/fee_schedule/get.

Mistaken use​

  • Do not use search to fetch a code you already have. Use /api/lookup/cpt/get — one record with its category, add-on flag and place in the book.
  • Do not read an empty result as "this code does not exist". The codebook is curated; a valid CPT code outside it is simply not held. For pricing any CPT or HCPCS code, use /api/lookup/fee_schedule/search, which finds any code a jurisdiction's schedule prices by code prefix.
  • Do not put a modifier in q. Modifiers are not part of a CPT code. Search for the five-character code and carry the modifier separately.
  • Do not search for HCPCS Level II codes (G2212). They are a different code set and are not in this codebook.

Debugging​

  1. Capture request_id. Present in every response body.
  2. 400 ValidationError with field: "q". The text was missing or shorter than two characters.
  3. Empty results for a real CPT code. The code is outside the curated codebook. Browse what the codebook holds with /api/lookup/cpt/tree.
  4. Empty results with billable=false. Expected: every searchable CPT entry is a billable code.

Rate limits​

See rate-limits.md for the current per-consumer limits.

Change history​

DateChange
2026-10-14Initial publication.
2026-10-14The engine assigns every request ID; an X-Request-ID request header is not used.