Loading documentation

Access required

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

Sign out
Skip to main content

Regulations Tree

Status: stable Category: regulations Added: 2026-07-01 Last reviewed: 2026-07-01

Summary

Returns one CFR part as a nested subpart/section tree, in document order. Use it to build a browse or navigation surface over a part — each leaf entry carries the section number, its official heading, and a stable id, so your application can render the part's structure and fetch individual sections selectively via /api/regulations/get.

The tree carries headings only, never section text. It answers "what is in this part and in what order," not "what does this section say."

Endpoint

FieldValue
MethodGET
Path/api/regulations/tree
Full URLhttps://engine.tripod-health.com/api/regulations/tree
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.
X-Request-IDNoOptional correlation ID, echoed in the response body's request_id and the X-Request-ID response header.

Path parameters

None.

Query parameters

ParameterTypeRequiredDefaultDescription
titleintegerYesCFR title number, 150. OSHA recordkeeping lives under title 29.
partstringYesCFR part number within the title, e.g. 1904. Treat as opaque text.

Both parameters are required. Omitting or malforming either returns 400 ValidationError naming the offending parameter.

Body

None.

Response

Success — 200 OK

The response is the whole part as one nested object: the part's heading, then one node per subpart in document order, each holding its leaf entries in document order. Leaf entries are either regulation sections or appendices, distinguished by type.

The example below is a real capture of 29 CFR part 1904, abbreviated for readability: it shows the first eight leaf entries (subparts A and B in full, the start of subpart C) and the last two (the end of subpart F, and subpart G). The full response contains every subpart (A through G) and every section of the part.

{
"cfr_title": 29,
"part": "1904",
"heading": "PART 1904—RECORDING AND REPORTING OCCUPATIONAL INJURIES AND ILLNESSES",
"children": [
{
"type": "subpart",
"subpart": "A",
"heading": "Subpart A—Purpose",
"children": [
{ "type": "regulation", "id": 102434, "section": "1904.0", "heading": "Purpose." }
]
},
{
"type": "subpart",
"subpart": "B",
"heading": "Subpart B—Scope",
"children": [
{ "type": "regulation", "id": 102436, "section": "1904.1", "heading": "Partial exemption for employers with 10 or fewer employees." },
{ "type": "regulation", "id": 102437, "section": "1904.2", "heading": "Partial exemption for establishments in certain industries." },
{ "type": "regulation", "id": 102438, "section": "1904.3", "heading": "Keeping records for more than one agency." },
{ "type": "appendix", "id": 102439, "section": "Non-Mandatory Appendix A to Subpart B of Part 1904", "heading": "Non-Mandatory Appendix A to Subpart B of Part 1904—Partially Exempt Industries" }
]
},
{
"type": "subpart",
"subpart": "C",
"heading": "Subpart C—Recordkeeping Forms and Recording Criteria",
"children": [
{ "type": "regulation", "id": 102441, "section": "1904.4", "heading": "Recording criteria." },
{ "type": "regulation", "id": 102442, "section": "1904.5", "heading": "Determination of work-relatedness." },
{ "type": "regulation", "id": 102443, "section": "1904.6", "heading": "Determination of new cases." }
]
},
{
"type": "subpart",
"subpart": "F",
"heading": "Subpart F—Transition From the Former Rule",
"children": [
{ "type": "regulation", "id": 102471, "section": "1904.45", "heading": "OMB control numbers under the Paperwork Reduction Act" }
]
},
{
"type": "subpart",
"subpart": "G",
"heading": "Subpart G—Definitions",
"children": [
{ "type": "regulation", "id": 102473, "section": "1904.46", "heading": "Definitions." }
]
}
],
"request_id": "ab861045-5af0-4878-b4ab-7b0a7565e7be",
"timestamp": "2026-07-02T00:42:48.636Z"
}

Response fields

FieldTypeAlways presentDescription
cfr_titleintegerYesEchoes the requested title.
partstringYesEchoes the requested part.
headingstringYesOfficial part heading as published in the CFR.
childrenarrayYesSubpart nodes in document order.
children[].typestringYesAlways subpart at this level.
children[].subpartstringYesSubpart letter, e.g. "C".
children[].headingstringYesOfficial subpart heading.
children[].childrenarrayYesLeaf entries within the subpart, in document order.
children[].children[].typestringYesregulation or appendix.
children[].children[].idintegerYesStable identifier for the entry. Use it to enumerate what to fetch via /api/regulations/get.
children[].children[].sectionstringYesSection number (e.g. "1904.5"), a reserved range (e.g. "1904.13-1904.28"), or the full appendix designation.
children[].children[].headingstringYesOfficial heading of the section or appendix. Headings only — the tree never carries section text.
request_idstringYesCorrelation ID. Quote in support tickets.
timestampstring (ISO 8601 UTC)YesServer time when the response was emitted.

Status codes

CodeMeaningWhen
200OKPart found; tree returned.
400ValidationErrortitle missing or not an integer 150, or part missing or malformed. field names the offender.
401UnauthenticatedMissing or invalid API key.
404NotFoundNo part matches (title, part).
429RateLimitedPer-consumer rate limit exceeded.
500InternalErrorUnexpected failure. Quote request_id in the ticket.

Examples

curl

curl -sS "https://engine.tripod-health.com/api/regulations/tree?title=29&part=1904" \
-H "apikey: $ENGINE_API_KEY"

Python (requests)

# Uses the call() helper from quickstart.md.
tree = call("GET", "/api/regulations/tree?title=29&part=1904")
for subpart in tree["children"]:
print(subpart["heading"])
for entry in subpart["children"]:
print(f" {entry['section']}: {entry['heading']}")

Node.js (native fetch)

// Uses the call() helper from quickstart.md.
const tree = await call("GET", "/api/regulations/tree?title=29&part=1904");
const leaves = tree.children.flatMap((s) => s.children);
console.log(`${tree.part}: ${leaves.length} entries`);

Error scenarios

Missing parameter

Send:

curl -sS "https://engine.tripod-health.com/api/regulations/tree?title=29" \
-H "apikey: $ENGINE_API_KEY" \
-H "X-Request-ID: docs-regulations-tree-missing-part" \
-w "\nHTTP %{http_code}\n"

Receive (400):

{
"timestamp": "2026-07-01T17:32:10.812Z",
"error": "ValidationError",
"message": "Query parameter 'part' is required",
"request_id": "docs-regulations-tree-missing-part",
"field": "part"
}

Unknown part

Send:

curl -sS "https://engine.tripod-health.com/api/regulations/tree?title=29&part=9999" \
-H "apikey: $ENGINE_API_KEY" \
-H "X-Request-ID: docs-regulations-tree-unknown-part" \
-w "\nHTTP %{http_code}\n"

Receive (404):

{
"timestamp": "2026-07-01T17:32:10.812Z",
"error": "NotFound",
"message": "No part '9999' under title 29",
"request_id": "docs-regulations-tree-unknown-part"
}

Intended use

  • Building a browse/navigation UI over a part — the tree is already in document order and grouped by subpart, so it renders directly as a sidebar or table of contents.
  • Enumerating a part's sections to fetch selectively. Walk the leaves, pick the sections you need, and pull their full text via /api/regulations/get — one tree call replaces guessing at section numbers.
  • Detecting appendices. Appendices do not follow the part.section numbering scheme; the tree is the reliable way to discover they exist and what they are called.

Mistaken use

  • Do not use the tree for text search. The tree matches nothing — it returns structure. Use /api/regulations/search to find sections by content.
  • Do not expect section text. Leaf entries carry headings only. Use /api/regulations/get to fetch the full text of a section or appendix.
  • Do not parse section as a number. Values include reserved ranges ("1904.13-1904.28") and full appendix designations. Treat the field as opaque display text and use id for lookups.

Debugging

  1. Capture request_id. Present in every response body and in the X-Request-ID response header.
  2. 400 ValidationError — both title and part are required; the field extra names the missing or malformed one. title must be an integer 150.
  3. 404 NotFound for a part you're sure exists — confirm the title is right. The same part number can exist under one title and not another.
  4. Fewer leaves than you expected — reserved section ranges are collapsed into a single entry (e.g. "1904.13-1904.28"), so the leaf count is lower than the raw section-number span.

Rate limits

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

Change history

DateChange
2026-07-01Initial publication.