CPT Search
Status:
stableCategory:lookupAdded:2026-10-14Last 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
| Field | Value |
|---|---|
| Method | GET |
| Path | /api/lookup/cpt/search |
| Full URL | https://engine.tripod-health.com/api/lookup/cpt/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 (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. |
billable | string | No | — | 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. |
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; 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
| Field | Type | Always present | Description |
|---|---|---|---|
results | array | Yes | Zero or more matches, in rank order. |
results[].code | string | Yes | The five-character CPT code. Treat as text: codes such as 0001U carry letters and leading zeros. |
results[].label | string | Yes | The code's long descriptor. |
results[].kind | string | Yes | Always code in search results. |
results[].billable | boolean | Yes | Always true in search results. |
release | string | null | Yes | The CPT year the codebook reflects, e.g. 2026. |
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/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
- Capture
request_id. Present in every response body. 400 ValidationErrorwithfield: "q". The text was missing or shorter than two characters.- Empty
resultsfor a real CPT code. The code is outside the curated codebook. Browse what the codebook holds with/api/lookup/cpt/tree. - Empty
resultswithbillable=false. Expected: every searchable CPT entry is a billable code.
Rate limits
See rate-limits.md for the current per-consumer limits.
Related
- lookup-cpt-get.md — one code's full record.
- lookup-cpt-tree.md — browse the codebook's sections and headings.
- lookup-fee_schedule-get.md — the workers' compensation maximum for a code.
- lookup-icd10cm-search.md — the same search shape over diagnosis 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. |