NAICS Search
Status:
stableCategory:naicsAdded:2026-04-27Last reviewed:2026-04-27
Summary
Type-ahead search across BLS industry safety benchmarks. Pass a short
fragment of either the industry name or a numeric NAICS prefix and get
back the matching codes ranked closest first. Designed to power UI
autocomplete; safe to call on every keystroke once q is at least two
characters.
The dataset is the BLS Survey of Occupational Injuries and Illnesses,
reseeded annually. Lookups always read the latest published year for
each (naics_code, ownership) pair.
Endpoint
| Field | Value |
|---|---|
| Method | GET |
| Path | /api/naics/search |
| Full URL | https://engine.tripod-health.com/api/naics/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. |
X-Request-ID | No | Optional correlation ID, up to 128 characters. Echoed in the response body's request_id and the X-Request-ID response header. |
Path parameters
None.
Query parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
q | string | Yes | — | Search fragment. Minimum two characters. All-digit values are matched as a code prefix (naics_code LIKE 'q%'); anything else is matched as an industry-name substring (industry_name ILIKE '%q%'). |
ownership | string | No | private | One of private, state_government, local_government. Picks the BLS ownership cohort. |
limit | int | No | 10 | Maximum results to return. Range 1–50. |
Body
None.
Response
Success — 200 OK
{
"results": [
{
"naics_code": "236220",
"industry_name": "Commercial Building Construction",
"ownership": "private",
"total_recordable_rate": 2.6
},
{
"naics_code": "23622",
"industry_name": "Commercial and Institutional Building Construction",
"ownership": "private",
"total_recordable_rate": 2.6
}
],
"request_id": "8f2c3b1d-5e4a-4a9c-9b1e-2a7f1d3e4c5b",
"timestamp": "2026-04-27T17:32:10.812Z"
}
results is always present. An empty array is a normal response (the
query matched nothing in the requested ownership cohort), not an error.
Response fields
| Field | Type | Always present | Description |
|---|---|---|---|
results | array | Yes | Zero or more match objects, ordered by code length (shortest first), then alphabetical industry name. |
results[].naics_code | string | Yes | NAICS code, 2–6 digits. The string preserves leading-context characters; treat as opaque text rather than parsing as a number. |
results[].industry_name | string | Yes | Industry name as published by BLS. |
results[].ownership | string | Yes | Echoes the ?ownership= value. |
results[].total_recordable_rate | number | null | Yes | Total recordable case rate per 100 FTE. null when BLS suppressed the cell for sample-size reasons. |
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 shorter than two characters, ownership not in the allowed set, or limit out of range. |
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/naics/search?q=construction&limit=5" \
-H "apikey: $ENGINE_API_KEY"
Numeric prefix
curl -sS "https://engine.tripod-health.com/api/naics/search?q=236" \
-H "apikey: $ENGINE_API_KEY"
Python (requests)
# Uses the call() helper from quickstart.md.
result = call("GET", "/api/naics/search?q=hospital&limit=5")
for row in result["results"]:
print(f"{row['naics_code']:6} {row['industry_name']:60} TRR={row['total_recordable_rate']}")
Node.js (native fetch)
// Uses the call() helper from quickstart.md.
const result = await call("GET", "/api/naics/search?q=hospital&limit=5");
for (const row of result.results) {
console.log(`${row.naics_code.padEnd(6)} ${row.industry_name} TRR=${row.total_recordable_rate}`);
}
TypeScript
interface NaicsSearchResult {
naics_code: string;
industry_name: string;
ownership: "private" | "state_government" | "local_government";
total_recordable_rate: number | null;
}
interface NaicsSearchResponse {
results: NaicsSearchResult[];
request_id: string;
timestamp: string;
}
const result = await call<NaicsSearchResponse>(
"GET",
"/api/naics/search?q=construction",
);
Error scenarios
q too short
Send:
curl -sS "https://engine.tripod-health.com/api/naics/search?q=h" \
-H "apikey: $ENGINE_API_KEY" \
-H "X-Request-ID: docs-naics-search-short-q" \
-w "\nHTTP %{http_code}\n"
Receive (400):
{
"timestamp": "2026-04-27T17:32:10.812Z",
"error": "ValidationError",
"message": "Query parameter 'q' must be at least 2 characters",
"request_id": "docs-naics-search-short-q",
"field": "q"
}
Invalid ownership
Send:
curl -sS "https://engine.tripod-health.com/api/naics/search?q=hospital&ownership=federal" \
-H "apikey: $ENGINE_API_KEY" \
-H "X-Request-ID: docs-naics-search-bad-ownership" \
-w "\nHTTP %{http_code}\n"
Receive (400):
{
"timestamp": "2026-04-27T17:32:10.812Z",
"error": "ValidationError",
"message": "Query parameter 'ownership' must be one of private, state_government, local_government",
"request_id": "docs-naics-search-bad-ownership",
"field": "ownership"
}
Intended use
- Autocomplete UIs that let an employer find their industry by typing a few letters or digits.
- Onboarding flows where the user has a NAICS code from another system and wants to confirm it lines up with the published industry name before submitting a calculation.
- Building lookup tables when you need to display the industry name alongside an internally-stored NAICS code.
Mistaken use
- Do not call
/api/naics/searchto fetch a single known code. Use/api/naics/get— one record, full benchmark fields, no ranking layer. - Do not interpret an empty
resultsarray as a failure. It means the query matched nothing in the requested ownership cohort. Try a shorter fragment or a different?ownership=. - Do not pass a NAICS code to
qand expect it to behave like/get. Search returns multiple rows — for exampleq=23matches every code beginning with23. To resolve a single record, call/api/naics/get?code=23.
Debugging
- Capture
request_id. Present in every response body and in theX-Request-IDresponse header. - Empty
resultsfor a search you expected to match. Double-check?ownership=— most BLS data ships only underprivate, and a request forstate_governmentorlocal_governmentwill be empty for industries the BLS does not publish under that cohort. 400 ValidationErrorwithfield: "q". The fragment was shorter than two characters. UI clients should not send the request until the user has typed at least two characters.nullrate values in results. BLS suppresses cells when the survey sample is too small to publish a stable estimate. This is expected, especially on narrow 6-digit codes.
Rate limits
See rate-limits.md for the current per-consumer limits.
Related
- naics-get.md — single-record lookup once the user has chosen a code.
- naics-calculate.md — compute employer rates and compare against the benchmark.
- authentication.md, errors.md, rate-limits.md, conventions.md — cross-cutting contract rules.
Change history
| Date | Change |
|---|---|
| 2026-04-27 | Initial publication. |