CPT Tree
Status:
stableCategory:lookupAdded:2026-10-14Last reviewed:2026-10-14
Summary
Returns one level of the CPT codebook's structure: a node, its
ancestors, and its direct children, each child flagged with
has_children. Call it without node to get the sections in book
order, then pass any child's code back as node to drill down —
section, subsection, heading, subheading, code.
Structural nodes are keyed by path, not by code range:
evaluation-management, then evaluation-management.office, then
evaluation-management.office.est. A key spells its own breadcrumb and
can never be mistaken for a code. Treat keys as opaque values read from
this endpoint; do not build them by hand.
The codebook is curated for occupational health delivered virtually and is not the full CPT code set.
Endpoint
| Field | Value |
|---|---|
| Method | GET |
| Path | /api/lookup/cpt/tree |
| Full URL | https://engine.tripod-health.com/api/lookup/cpt/tree |
| 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 |
|---|---|---|---|---|
node | string | No | — | A structural key as returned by this endpoint (evaluation-management.office), or a five-character code (99213). Omit it to get the sections. |
Body
None.
Response
Success — 200 OK
Request: GET /api/lookup/cpt/tree?node=evaluation-management.office
{
"node": {
"code": "evaluation-management.office",
"label": "Office or Other Outpatient Services",
"kind": "subsection",
"billable": false
},
"ancestors": [
{
"code": "evaluation-management",
"label": "Evaluation and Management",
"kind": "section",
"billable": false
}
],
"children": [
{
"code": "evaluation-management.office.new",
"label": "New Patient",
"kind": "heading",
"billable": false,
"has_children": true
},
{
"code": "evaluation-management.office.est",
"label": "Established Patient",
"kind": "heading",
"billable": false,
"has_children": true
}
],
"release": "2026",
"request_id": "c15dfc43-38aa-4de2-8611-4e171d80007a",
"timestamp": "2026-10-14T00:16:04.816Z"
}
Without node, node is null, ancestors is empty, and children
holds the sections:
{
"node": null,
"ancestors": [],
"children": [
{
"code": "evaluation-management",
"label": "Evaluation and Management",
"kind": "section",
"billable": false,
"has_children": true
},
{
"code": "medicine",
"label": "Medicine",
"kind": "section",
"billable": false,
"has_children": true
}
],
"release": "2026",
"request_id": "a2d5be1c-5101-4bd3-b1dd-aa958ba82670",
"timestamp": "2026-10-14T00:15:59.130Z"
}
Response fields
| Field | Type | Always present | Description |
|---|---|---|---|
node | object | null | Yes | The expanded node as { code, label, kind, billable }. null when node was omitted. |
ancestors | array | Yes | The node's ancestors, section first, each { code, label, kind, billable }. Empty at the top level and for a section. |
children | array | Yes | The node's direct children, in book order. Empty for a code. |
children[].code | string | Yes | A structural key or a five-character code. Pass it back as node to expand it, or as code to get. |
children[].label | string | Yes | The heading text, or the code's long descriptor. |
children[].kind | string | Yes | section, subsection, heading, subheading, or code. |
children[].billable | boolean | Yes | true for a code, false for a structural node. |
children[].has_children | boolean | Yes | true when expanding the child returns further children. |
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 | Level returned. |
400 | ValidationError | node is neither a structural key nor a five-character code, carries a modifier, is a HCPCS Level II code, or is repeated. field is node. |
401 | Unauthenticated | Missing or invalid API key. |
404 | NotFound | node is well-formed but the codebook holds no such node. |
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/tree?node=evaluation-management.office" \
-H "apikey: $ENGINE_API_KEY"
A heading's codes
curl -sS "https://engine.tripod-health.com/api/lookup/cpt/tree?node=evaluation-management.office.est" \
-H "apikey: $ENGINE_API_KEY"
{
"node": {
"code": "evaluation-management.office.est",
"label": "Established Patient",
"kind": "heading",
"billable": false
},
"ancestors": [
{
"code": "evaluation-management",
"label": "Evaluation and Management",
"kind": "section",
"billable": false
},
{
"code": "evaluation-management.office",
"label": "Office or Other Outpatient Services",
"kind": "subsection",
"billable": false
}
],
"children": [
{
"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,
"has_children": false
},
{
"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,
"has_children": false
},
{
"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,
"has_children": false
},
{
"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,
"has_children": false
},
{
"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,
"has_children": false
}
],
"release": "2026",
"request_id": "8391301c-0345-4b59-9bf7-db29991e1bba",
"timestamp": "2026-10-14T00:16:05.230Z"
}
Python (requests)
# Uses the call() helper from quickstart.md.
def walk(node=None, depth=0):
path = "/api/lookup/cpt/tree" + (f"?node={node}" if node else "")
for child in call("GET", path)["children"]:
print(" " * depth + f"{child['code']} {child['label'][:60]}")
if child["has_children"]:
walk(child["code"], depth + 1)
walk("evaluation-management.office")
Node.js (native fetch)
// Uses the call() helper from quickstart.md.
const sections = await call("GET", "/api/lookup/cpt/tree");
for (const section of sections.children) {
const level = await call("GET", `/api/lookup/cpt/tree?node=${encodeURIComponent(section.code)}`);
console.log(section.label, "->", level.children.map((c) => c.label).join(", "));
}
TypeScript
type CptKind = "section" | "subsection" | "heading" | "subheading" | "code";
interface CptNode {
code: string;
label: string;
kind: CptKind;
billable: boolean;
}
interface CptTreeResponse {
node: CptNode | null;
ancestors: CptNode[];
children: (CptNode & { has_children: boolean })[];
release: string | null;
request_id: string;
timestamp: string;
}
const level = await call<CptTreeResponse>("GET", "/api/lookup/cpt/tree?node=medicine");
Error scenarios
Unknown node
Send:
curl -sS "https://engine.tripod-health.com/api/lookup/cpt/tree?node=surgery" \
-H "apikey: $ENGINE_API_KEY" \
-w "\nHTTP %{http_code}\n"
Receive (404):
{
"timestamp": "2026-10-14T00:16:06.485Z",
"error": "NotFound",
"message": "No CPT node 'surgery'",
"request_id": "b880f925-12ed-4b6e-b65c-5939e8b7c4a9"
}
Intended use
- Browsing what the codebook covers — the sections, then the headings under each, then the codes.
- Grouped procedure pickers where a user chooses a heading (for example "Established Patient") before a code.
- Breadcrumbs.
ancestorsis the path from the section to the node, ready to render.
Mistaken use
- Do not use the tree to find codes by words or prefix. Use
/api/lookup/cpt/search. - Do not construct structural keys yourself. Read them from this
endpoint; a guessed key such as
surgeryis a404. - Do not expect the full CPT book. Sections outside the curated
codebook do not exist here. To price a code the codebook does not
hold, use
/api/lookup/fee_schedule/get.
Debugging
- Capture
request_id. Present in every response body. 404 NotFound. The key is not in the codebook. Start from the root (nodeomitted) and follow the returnedcodevalues.- Empty
children. The node is a code. Itshas_childrenwasfalsein the parent's listing.
Rate limits
See rate-limits.md for the current per-consumer limits.
Related
- lookup-cpt-search.md — find codes by descriptor or code prefix.
- lookup-cpt-get.md — one code's or node's full record.
- lookup-icd10cm-tree.md — the same tree shape for diagnosis codes.
- lookup-fee_schedule-tree.md — the jurisdictions and localities the fee schedule lookup covers.
- 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. |