---
title: "Look up a single NUCC taxonomy code"
method: POST
path: "/v1/healthcare/taxonomy/lookup"
tags: ["healthcare"]
---

# Look up a single NUCC taxonomy code

`POST /v1/healthcare/taxonomy/lookup`

## Request

- Base URL: `https://api.snipget.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.snipget.ai/v1/healthcare/taxonomy/lookup`
- Auth: none declared

Fetch the full row for a single NUCC provider taxonomy code. Returns the code's grouping (top level), classification (middle), specialization (leaf, may be null), definition, notes, canonical display name, and provider section. Use the 'fields' parameter to restrict the response to a subset. Every response includes 'dataset' with the currently-served NUCC release info.

## Query parameters

- `include_receipt` boolean

## Headers

- `authorization` string, nullable
- `X-API-Key` string, nullable

## Request body

- TaxonomyLookupRequest
  - `code` string, required: NUCC provider taxonomy code (e.g. '207Q00000X').
  - `fields` string[], nullable: Optional list of fields to return per row. Defaults to all. Valid fields: code, grouping, classification, specialization, definition, notes, display_name, section. The 'code' field is always returned.
  - `include_trace` boolean

## Response `200`

Successful Response

- HealthcareTaxonomyLookupResponse: Success envelope for `/v1/healthcare/taxonomy/lookup` — `result` carries this utility's precise shape.
  - `status` string
  - `confidence` number, required
  - `result` object, required: Result of :func:`lookup`. ``found`` and ``dataset`` are always present; ``taxonomy`` is the projected record on a hit and ``None`` on a miss/empty input.
    - `found` boolean, required
    - `taxonomy` HealthcareTaxonomyLookupTaxonomyRecord, required: One NUCC taxonomy row, as projected by ``_project`` (the item shape of ``lookup.taxonomy`` and each ``list_children`` item). All fields are ``NotRequired`` because the ``fields`` param may project any subset; in practice ``code`` is always force-included.
      - `code` string
      - `grouping` string, nullable
      - `classification` string, nullable
      - `specialization` string, nullable
      - `definition` string, nullable
      - `notes` string, nullable
      - `display_name` string, nullable
      - `section` string, nullable
    - `dataset` object, required
  - `meta` ResponseMeta: Metadata attached to every successful response.
    - `version` string
    - `build` string
    - `elapsed_ms` integer
    - `cost_units` integer: Cost units charged for this call: one per item processed (a batch of N items = N; live-registry lookups bill 2 per item). A call is one request; cost units are the billing measure.
    - `request_id` string, nullable
    - `trace` string[], nullable
    - `rate_limit_remaining` integer, nullable
    - `rate_limit_reset` integer, nullable
    - `quota_remaining` integer, nullable: Cost units left in the plan's monthly included bucket before this call's charge lands (None on unlimited tiers).
    - `quota_reset` integer, nullable: Unix timestamp when the monthly included bucket resets.
    - `credit_remaining_usd` number, nullable: Prepaid overage-allowance balance in USD, populated once the included cost units are used up and this call is drawing on it.
    - `receipt` ReceiptMeta: Opt-in execution receipt (ADR #68 B1) — caller-verifiable hashes. Requested with the ``include_receipt=true`` query parameter (free, like ``include_trace``). Reproduce either hash with any RFC 8785 (JCS) library: ``input_hash = sha256(jcs({"tool": <request path>, "args": <your JSON body minus include_trace/include_receipt>}))``; ``result_hash = sha256(jcs(result))``. For deterministic tools (everything except the generators) the same input on the same ``build`` reproduces ``result_hash`` — disputes are honored by replay.
      - `receipt_id` string, required
      - `build` string, required
      - `input_hash` string, nullable
      - `result_hash` string, nullable
      - `error` string, nullable
      - `message` string, nullable

## Other responses

- `400`: Input was syntactically valid but semantically unusable (`INVALID_INPUT`). Not retryable without changing the input.
- `401`: Missing or unrecognized API key. Send it as `Authorization: Bearer <key>` or `X-API-Key: <key>`. Keys are issued at https://snipget.ai.
- `403`: The key is valid but this caller may not use it: the request IP is outside the key's allowlist (`IP_NOT_ALLOWED`) or the account is deactivated (`ACCOUNT_DEACTIVATED`).
- `422`: The request body failed schema validation (`INVALID_REQUEST`). `details` lists the per-field errors. Not retryable without changing the request.
- `429`: Two distinct conditions share this status — branch on `error_code`. **`RATE_LIMITED`** is a per-second throughput throttle: retry after `retry_after_seconds` (the precise float; the `Retry-After` header is the same value rounded up). **`QUOTA_EXCEEDED`** is monthly capacity and is NOT retryable: recovery depends on `limit_type` — upgrade (`monthly_quota`), buy an overage allowance (`included_exhausted`), or top up (`overage_balance_exhausted`).
- `503`: A transient, retryable service condition — branch on `error_code`. **`MAINTENANCE_MODE`**: an admin-toggled maintenance window (auth, portal, and webhook surfaces stay up). **`UPSTREAM_UNAVAILABLE`**: a utility's external data source (PubChem, RxNorm, ClinicalTrials.gov, the FX feed, NPPES…) is down, blocking us, or timed out. **`UPSTREAM_RATE_LIMITED`**: that external source is throttling Snipget (it returned a 429) — the caller's own rate is fine, so this is NOT our `RATE_LIMITED` (429); it's a service-side throttle. All three are retryable; wait for `retry_after_seconds` / the `Retry-After` header when present.

---

[API](https://skmtc.dev/snipget/apis/snipget-api.md) · [All operations](https://skmtc.dev/snipget/apis/snipget-api/llms.txt) · [OpenAPI document](https://skmtc.dev/snipget/apis/snipget-api/revisions/ed1077fb1bcb?raw)
