# healthcare.dev > One REST API, MCP server, TypeScript SDK and CLI for current, versioned US healthcare reference > data: ICD-10-CM, ICD-10-PCS, HCPCS Level II, FDA NDC, RxNorm, with NPI providers coming next. > Reference data only, not medical, clinical or billing advice. Never send patient information (PHI). - API base URL: https://api.healthcare.dev/v1 (auth: `Authorization: Bearer hdev_live_...`) - OpenAPI 3.1 spec: https://api.healthcare.dev/openapi.json (also https://docs.healthcare.dev/openapi.json) - Remote MCP server (Streamable HTTP): https://mcp.healthcare.dev/mcp - Local MCP server: `npx -y @healthcare.dev/mcp` with `HDEV_API_KEY` - Every docs page has a Markdown version: append `.md` to its URL. - Every response is `{ data, meta: { source, data_version, retrieved_at, license }, links? }`; errors are RFC 9457 `application/problem+json`. # healthcare.dev URL: https://docs.healthcare.dev healthcare.dev serves US healthcare reference data (diagnosis and procedure codes, HCPCS, drugs, and soon providers) through one consistent API. Every response says where the data came from and which release it is, so you and your agents can cite it. ```sh curl https://api.healthcare.dev/v1/codes/icd10cm/E11.9 \ -H "Authorization: Bearer $HDEV_API_KEY" ``` ## Start here - [Quickstart](/quickstart): your first call in under two minutes. - [MCP server](/mcp): give Claude, Cursor, Codex or VS Code direct access to the data. - [API reference](/reference): every endpoint, generated from the OpenAPI spec. ## What you get | Dataset | Source | Updated | Endpoint | | ------------------------------------ | ------------- | --------- | -------------------- | | [ICD-10-CM](/datasets/icd10cm) | CMS, CDC NCHS | Yearly | `/v1/codes/icd10cm` | | [ICD-10-PCS](/datasets/icd10pcs) | CMS | Yearly | `/v1/codes/icd10pcs` | | [HCPCS Level II](/datasets/hcpcs) | CMS | Quarterly | `/v1/codes/hcpcs` | | [NDC Directory](/datasets/ndc) | FDA | Daily | `/v1/drugs/ndc` | | [RxNorm](/datasets/rxnorm) | NLM | Monthly | `/v1/drugs/rxnorm` | | [NPI registry](/datasets/npi) (soon) | CMS NPPES | Weekly | `/v1/providers` | ## Ground rules - **Reference data, not medical advice.** Nothing here is clinical, coding or billing advice. - **No PHI, ever.** Send only identifiers of public things (codes, NDCs, NPIs, names of drugs). Never send patient names, dates of birth, member IDs or anything else about a person. - **Always cite.** Each response carries `meta.source`, `meta.data_version` and `meta.license`. ## For agents Machine-readable entry points: [`/llms.txt`](/llms.txt), [`/llms-full.txt`](/llms-full.txt), [`/openapi.json`](/openapi.json), and a Markdown copy of every page (add `.md` to the URL, for example [`/quickstart.md`](/quickstart.md)). See [Agent skill](/agents/skill). --- # Quickstart URL: https://docs.healthcare.dev/quickstart ## 1. Get an API key Sign up at [app.healthcare.dev](https://app.healthcare.dev). The Free plan needs no card. Copy your key when it's shown: we store only a hash, so it's displayed once. Keys look like `hdev_live_ab12cd34_...` (production) or `hdev_test_...` (same data, lower limits, never billed). ```sh export HDEV_API_KEY=hdev_live_... ``` ## 2. Make a call Look up an ICD-10-CM code: ```sh curl https://api.healthcare.dev/v1/codes/icd10cm/E11.9 \ -H "Authorization: Bearer $HDEV_API_KEY" ``` ```json { "data": { "system": "icd10cm", "code": "E11.9", "display": "Type 2 diabetes mellitus without complications", "billable": true, "parent": "E11", "status": "active", "effective_start": "2015-10-01", "effective_end": null }, "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS)" } } ``` ## 3. Try the rest ```sh # Search codes by description curl "https://api.healthcare.dev/v1/codes/icd10cm?q=type+2+diabetes+kidney&limit=5" \ -H "Authorization: Bearer $HDEV_API_KEY" # NDC to RxNorm (any NDC format) curl https://api.healthcare.dev/v1/drugs/ndc/0093-1048-01 \ -H "Authorization: Bearer $HDEV_API_KEY" # What changed in the latest release curl "https://api.healthcare.dev/v1/changes?dataset=icd10cm" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` ## Use a client instead **TypeScript SDK** ```sh npm i @healthcare.dev/sdk ``` ```ts import { HealthcareDev } from "@healthcare.dev/sdk"; const hdev = new HealthcareDev(); // reads HDEV_API_KEY const { data, meta } = await hdev.codes.get("icd10cm", "E11.9"); console.log(data.display, meta.data_version); ``` **CLI** ```sh npx @healthcare.dev/cli code icd10 E11.9 ``` **MCP** (Claude Code) ```sh claude mcp add --transport http healthcare-dev https://mcp.healthcare.dev/mcp \ --header "Authorization: Bearer $HDEV_API_KEY" ``` Next: [Authentication](/authentication), [Errors](/errors), [API reference](/reference). --- # Authentication URL: https://docs.healthcare.dev/authentication Send your key in the `Authorization` header on every `/v1` request: ```http Authorization: Bearer hdev_live_ab12cd34_... ``` The MCP server also accepts `x-api-key: hdev_live_...`. ## Live and test keys | Prefix | Data | Limits | Billed | | ------------ | --------- | ------------------------------- | ------ | | `hdev_live_` | All | Your plan's limits | Yes | | `hdev_test_` | Same data | 2 requests/s, 1,000 calls/month | Never | ## Public endpoints `/v1/status`, `/healthz` and `/openapi.json` need no key. ## Handling keys - Keys are shown once. We store only a salted hash and a short public prefix (`hdev_live_ab12cd34`) so you can tell keys apart in the dashboard. - Keep keys on your server. Never ship a live key in browser or mobile code. - Revoke a leaked key in the dashboard; revocation takes effect within 30 seconds. ## Errors A missing, malformed or revoked key returns `401` with `type` `https://healthcare.dev/problems/unauthorized`. See [Errors](/errors). --- # Responses URL: https://docs.healthcare.dev/responses Every successful response has the same shape: ```json { "data": {}, "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS)" }, "links": { "self": "/v1/codes/icd10cm?q=diabetes", "next": null } } ``` | Field | Meaning | | ------------------- | ---------------------------------------------------------------------- | | `data` | One record, or a list for searches and listings | | `meta.source` | Upstream source id (`cms-icd10`, `cms-hcpcs`, `fda-ndc`, `nlm-rxnorm`) | | `meta.data_version` | The published dataset release the answer came from | | `meta.retrieved_at` | When we generated the response | | `meta.license` | License or attribution terms for the data | | `meta.as_of` | Present when you asked for a past date with `as_of` | | `links.next` | Cursor URL for the next page, `null` on the last page | ## Record lifecycle Codes and drugs carry `status` (`active`, `retired`, `replaced`), `effective_start` and `effective_end` (exclusive). Retired records stay available: a code that was valid on a claim from 2019 still resolves, and `replaced_by` lists its successors where the source says so. Pass `as_of=YYYY-MM-DD` on lookups to get a record as it was on that date. ## Caching Data responses carry a weak `ETag` that only changes with `data_version`. Send `If-None-Match` to get a `304` with no body. Responses are `Cache-Control: private`: cache them in your app, not in shared caches. --- # Errors URL: https://docs.healthcare.dev/errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)): ```json { "type": "https://healthcare.dev/problems/invalid-request", "title": "Invalid request", "status": 400, "detail": "limit must be at most 100", "errors": [{ "path": "limit", "message": "Too big: expected number to be <=100" }] } ``` Branch on `type`. Codes are stable and only ever added, never renamed. | `type` (under `https://healthcare.dev/problems/`) | Status | What to do | | ------------------------------------------------- | ------ | --------------------------------------------------------- | | `invalid-request` | 400 | Fix the parameter named in `errors[].path` | | `unauthorized` | 401 | Send a valid key: `Authorization: Bearer hdev_live_...` | | `forbidden` | 403 | Your plan or key can't use this dataset | | `not-found` | 404 | The id doesn't exist in any release (retired ones do) | | `rate-limited` | 429 | Wait `Retry-After` seconds, then retry | | `quota-exceeded` | 429 | Monthly calls used up; upgrade or wait for the next month | | `internal` | 500 | Retry with backoff; tell us if it persists | | `unavailable` | 503 | Service degraded; retry with backoff | | `dataset-unavailable` | 503 | The dataset has no published version yet | The SDK maps these to typed errors (`NotFoundError`, `RateLimitError`, `QuotaExceededError`, ...) and retries `rate-limited`, 5xx and network errors for you. --- # Rate limits and quotas URL: https://docs.healthcare.dev/rate-limits Each key has a per-second limit (one-second fixed windows) and a monthly call quota set by your plan. See [pricing](https://healthcare.dev/pricing) for the numbers. Every response carries: ```http RateLimit-Limit: 5 RateLimit-Remaining: 4 RateLimit-Reset: 1 ``` Over the per-second limit you get `429` with `type` `rate-limited` and a `Retry-After` header. On the Free plan, using up the monthly quota returns `429` `quota-exceeded` until the next calendar month (UTC); paid plans keep working and bill the overage. MCP tool calls count exactly like REST calls. --- # Pagination and batch URL: https://docs.healthcare.dev/pagination ## Cursors List and search endpoints return up to `limit` results (default 25, max 100) and a `links.next` URL. Follow it until it's `null`: ```sh curl "https://api.healthcare.dev/v1/codes/hcpcs?q=wheelchair&limit=100" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` ```ts for await (const code of hdev.codes.iterate("hcpcs", { q: "wheelchair" })) console.log(code.code); ``` Cursors are opaque; don't build them yourself. ## Batch Look up to 100 codes in one call. Each result says whether it was found: ```sh curl -X POST https://api.healthcare.dev/v1/codes/icd10cm/batch \ -H "Authorization: Bearer $HDEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{"codes": ["E11.9", "I10", "NOPE"]}' ``` Each item in a batch is billed as one call. --- # Versioning and changes URL: https://docs.healthcare.dev/versioning ## API versions The major version is in the URL (`/v1`). Within v1 we only add things: new endpoints, new optional parameters, new fields. Deprecations are announced six months ahead with `Deprecation` and `Sunset` headers and in the [changelog](/changelog). ## Dataset versions Each upstream release is loaded, checked against quality gates (schema, row counts, golden records) and published as an immutable version. `meta.data_version` names it. A bad release never replaces a good one: it's rejected and the previous version keeps serving. ## Change feed `GET /v1/changes?dataset=icd10cm` lists records added, changed or retired in each release: ```sh curl "https://api.healthcare.dev/v1/changes?dataset=icd10cm&since=2026-10-01T00:00:00Z" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` Webhooks for the same feed are coming in Phase 2. --- # ICD-10-CM URL: https://docs.healthcare.dev/datasets/icd10cm | | | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Source | CMS and CDC NCHS ([cms.gov](https://www.cms.gov/medicare/coding-billing/icd-10-codes)) | | Source id | `cms-icd10` | | Release cadence | Yearly (October 1), with occasional April updates | | License | Public domain (US government work) | | Endpoints | [`/v1/codes/icd10cm/{code}`](/reference/codes/look-up-a-code), [search](/reference/codes/search-codes), [hierarchy](/reference/codes/code-with-ancestors-and-children), [batch](/reference/codes/look-up-up-to-100-codes) | ICD-10-CM is the US clinical modification of ICD-10, used for diagnoses on claims. Codes are returned with or without the dot (`E11.9` and `E119` both work). ## Fields | Field | Meaning | | ----------------------------------------------------------- | -------------------------------------------------------------- | | `code` | The code with its dot, e.g. `E11.9` | | `display` | Short description | | `description` | Long description | | `billable` | `true` for codes valid on a claim, `false` for headers (`E11`) | | `parent` | The next code up the hierarchy | | `status`, `effective_start`, `effective_end`, `replaced_by` | Lifecycle across releases | ## Example ```sh curl https://api.healthcare.dev/v1/codes/icd10cm/E11.22/hierarchy \ -H "Authorization: Bearer $HDEV_API_KEY" ``` --- # ICD-10-PCS URL: https://docs.healthcare.dev/datasets/icd10pcs | | | | --------------- | ------------------------------------------------------------------------- | | Source | CMS ([cms.gov](https://www.cms.gov/medicare/coding-billing/icd-10-codes)) | | Source id | `cms-icd10` | | Release cadence | Yearly (October 1) | | License | Public domain (US government work) | | Endpoints | `/v1/codes/icd10pcs/{code}` and `/v1/codes/icd10pcs?q=` | ICD-10-PCS codes are seven characters, each with a meaning (section, body system, operation, ...). Same response shape as ICD-10-CM. ```sh curl "https://api.healthcare.dev/v1/codes/icd10pcs?q=appendectomy&limit=5" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` --- # HCPCS Level II URL: https://docs.healthcare.dev/datasets/hcpcs | | | | --------------- | ------------------------------------------------------------------------------------------------------------------------- | | Source | CMS ([quarterly update](https://www.cms.gov/medicare/coding-billing/healthcare-common-procedure-system/quarterly-update)) | | Source id | `cms-hcpcs` | | Release cadence | Quarterly | | License | Public domain, **excluding D-series (CDT) codes**, which are © ADA and never served | | Endpoints | `/v1/codes/hcpcs/{code}` and `/v1/codes/hcpcs?q=` | HCPCS Level II covers what CPT doesn't: ambulance, durable medical equipment, drugs given in a clinic (J codes) and more. `attributes` carries CMS fields such as coverage and BETOS codes. We don't serve CPT (HCPCS Level I): its descriptions are licensed by the AMA. ```sh curl https://api.healthcare.dev/v1/codes/hcpcs/E0110 \ -H "Authorization: Bearer $HDEV_API_KEY" ``` --- # NDC Directory URL: https://docs.healthcare.dev/datasets/ndc | | | | --------------- | ----------------------------------------------------------------------------------------------------------------------------------- | | Source | FDA ([NDC Directory](https://www.fda.gov/drugs/drug-approvals-and-databases/national-drug-code-directory)) | | Source id | `fda-ndc` | | Release cadence | Daily | | License | Public domain (US government work) | | Endpoints | [`/v1/drugs/ndc/{ndc}`](/reference/drugs/look-up-an-ndc), [`/v1/drugs/search`](/reference/drugs/search-drugs-across-rxnorm-and-ndc) | Pass an NDC in any format: 10-digit with dashes (`0093-1048-01`), 11-digit (`00093104801`) or a product NDC (`0093-1048`). Responses include every package with its normalized 11-digit NDC and the RxNorm concepts (`rxcuis`, `rxnorm`) for the product. Being listed in the NDC Directory does not mean a drug is FDA approved. ```sh curl https://api.healthcare.dev/v1/drugs/ndc/00093104801 \ -H "Authorization: Bearer $HDEV_API_KEY" ``` --- # RxNorm URL: https://docs.healthcare.dev/datasets/rxnorm | | | | --------------- | --------------------------------------------------------------------------------------------------------------------------------- | | Source | NLM ([RxNorm Current Prescribable Content](https://www.nlm.nih.gov/research/umls/rxnorm/docs/prescribe.html)) | | Source id | `nlm-rxnorm` | | Release cadence | Monthly (weekly updates in between) | | License | No license required for this subset | | Endpoints | [`/v1/drugs/rxnorm/{rxcui}`](/reference/drugs/look-up-an-rxnorm-concept), [`/v1/drugs/rxnorm?q=`](/reference/drugs/search-rxnorm) | RxNorm gives each clinical drug a concept id (RxCUI) and a term type (`tty`): `IN` ingredient, `SCD` semantic clinical drug, `SBD` branded drug, and so on. Concepts link to their ingredients and NDCs. This product uses publicly available data from the U.S. National Library of Medicine (NLM), National Institutes of Health, Department of Health and Human Services; NLM is not responsible for the product and does not endorse or recommend this or any other product. If a release is late, `/v1/status` and `/v1/datasets` flag it as not fresh. ```sh curl https://api.healthcare.dev/v1/drugs/rxnorm/861007 \ -H "Authorization: Bearer $HDEV_API_KEY" ``` --- # NPI registry (coming soon) URL: https://docs.healthcare.dev/datasets/npi | | | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | | Source | CMS NPPES ([data dissemination](https://www.cms.gov/medicare/regulations-guidance/administrative-simplification/data-dissemination)) | | Source id | `nppes` | | Release cadence | Weekly, with a monthly full file | | License | Public (FOIA-disclosable) | | Endpoints (planned) | `/v1/providers/{npi}`, `/v1/providers?q=`, `/v1/providers/{npi}/validate` | The provider endpoints are in progress. Today you can check an NPI's format and check digit with the MCP tool `validate_npi`, the SDK helper `isValidNpi`, or the [free NPI lookup](https://healthcare.dev/tools/npi-lookup). --- # Provider taxonomy (licensing) URL: https://docs.healthcare.dev/datasets/taxonomy | | | | --------------- | --------------------------------------------------------------------------------- | | Source | NUCC | | Release cadence | Twice a year | | License | Commercial license required (© American Medical Association); request in progress | | Endpoints | `/v1/taxonomies` (returns `503 dataset-unavailable` until licensed) | Provider records will carry taxonomy **codes** from NPPES either way. Descriptions and taxonomy search ship once the license is signed. --- # MCP server URL: https://docs.healthcare.dev/mcp The healthcare.dev MCP server exposes the API as read-only tools built around agent intents (`lookup_code`, `search_drugs`, `map_ndc_to_rxnorm`, ...). Results are compact, capped at 10 items and always cite `source` and `data_version`. | Mode | Address | Auth | | ------------------ | -------------------------------- | ------------------------------------- | | Remote (preferred) | `https://mcp.healthcare.dev/mcp` | `Authorization: Bearer hdev_live_...` | | Local (stdio) | `npx -y @healthcare.dev/mcp` | `HDEV_API_KEY` environment variable | Remote uses Streamable HTTP and needs nothing installed. Tool calls are ordinary API calls with your key, so limits, quotas and billing are the same as REST. ## Set up your client - [Claude](/mcp/claude) (Claude Code, Claude Desktop, claude.ai) - [Cursor](/mcp/cursor) - [VS Code](/mcp/vscode) - [Codex](/mcp/codex) Then see [Tools](/mcp/tools) for what each tool does and when not to use it. Every tool is reference data only, not clinical or billing advice. Never send patient information to any tool. --- # Claude URL: https://docs.healthcare.dev/mcp/claude ## Claude Code ```sh claude mcp add --transport http healthcare-dev https://mcp.healthcare.dev/mcp \ --header "Authorization: Bearer $HDEV_API_KEY" ``` Check it with `claude mcp list`, then ask: _"What is ICD-10-CM E11.22 and what are its parent codes?"_ ## Claude Desktop Add to `claude_desktop_config.json` (Settings → Developer → Edit Config): ```json { "mcpServers": { "healthcare-dev": { "command": "npx", "args": ["-y", "@healthcare.dev/mcp"], "env": { "HDEV_API_KEY": "hdev_live_..." } } } } ``` Restart Claude Desktop. The tools appear under the tools menu. ## claude.ai Settings → Connectors → Add custom connector, URL `https://mcp.healthcare.dev/mcp`. One-click OAuth sign-in is coming; until then use Claude Code or Claude Desktop with your key. --- # Cursor URL: https://docs.healthcare.dev/mcp/cursor Add to `~/.cursor/mcp.json` (all projects) or `.cursor/mcp.json` (one project): ```json { "mcpServers": { "healthcare-dev": { "url": "https://mcp.healthcare.dev/mcp", "headers": { "Authorization": "Bearer hdev_live_..." } } } } ``` Open Cursor Settings → MCP and check that `healthcare-dev` shows a green dot and its tools. Don't commit a project file that contains your key; use the global file or an environment variable. --- # VS Code URL: https://docs.healthcare.dev/mcp/vscode Add `.vscode/mcp.json` (note `servers`, not `mcpServers`). VS Code prompts for the key once and stores it securely: ```json { "inputs": [ { "type": "promptString", "id": "hdev-key", "description": "healthcare.dev API key", "password": true } ], "servers": { "healthcare-dev": { "type": "http", "url": "https://mcp.healthcare.dev/mcp", "headers": { "Authorization": "Bearer ${input:hdev-key}" } } } } ``` Open Copilot Chat in agent mode and pick the healthcare-dev tools from the tools menu. --- # Codex URL: https://docs.healthcare.dev/mcp/codex Add to `~/.codex/config.toml`: ```toml [mcp_servers.healthcare-dev] command = "npx" args = ["-y", "@healthcare.dev/mcp"] env = { HDEV_API_KEY = "hdev_live_..." } ``` Restart Codex and run `/mcp` to see the tools. --- # Tools URL: https://docs.healthcare.dev/mcp/tools All tools are read-only (`readOnlyHint: true`), return at most 10 results by default and include `source` and `data_version` so answers can be cited. | Tool | Use it to | Example input | Don't use it for | | ------------------------ | ------------------------------------------------------- | -------------------------------------------- | ------------------------------------------- | | `lookup_code` | Get one ICD-10-CM, ICD-10-PCS or HCPCS code | `{ "system": "icd10cm", "code": "E11.9" }` | Finding a code from a description (search) | | `search_codes` | Find codes by description or prefix | `{ "system": "icd10cm", "query": "asthma" }` | Picking a diagnosis for a patient | | `explain_code_hierarchy` | See a code's ancestors and children | `{ "system": "icd10cm", "code": "E11.22" }` | Code lookups where you only need the record | | `lookup_drug` | Get an FDA product by NDC or an RxNorm concept by RxCUI | `{ "ndc": "0093-1048-01" }` | Dosing or interaction questions | | `search_drugs` | Find drugs by name across RxNorm and NDC | `{ "query": "metformin" }` | Recommending a drug | | `map_ndc_to_rxnorm` | Turn an NDC into RxNorm concepts | `{ "ndc": "00093104801" }` | Products not in the FDA NDC Directory | | `validate_npi` | Check an NPI's format and check digit | `{ "npi": "1234567893" }` | Confirming a provider exists (coming soon) | | `list_datasets` | See versions and freshness of every dataset | `{}` | Record lookups | | `get_dataset_changes` | See what was added, changed or retired in a release | `{ "dataset": "icd10cm" }` | Full dataset downloads | Resources: `healthcare-dev://datasets`, `healthcare-dev://changes/{dataset}`. Prompts: `code_this_diagnosis`, `check_ndc`. The input examples are illustrative; your client shows each tool's exact JSON schema. --- # TypeScript SDK URL: https://docs.healthcare.dev/guides/typescript ```sh npm i @healthcare.dev/sdk ``` ```ts import { HealthcareDev, NotFoundError } from "@healthcare.dev/sdk"; const hdev = new HealthcareDev(); // reads HDEV_API_KEY const { data, meta } = await hdev.codes.get("icd10cm", "E11.9"); console.log(data.display, data.billable, meta.data_version); // One page, or every result const page = await hdev.codes.search("icd10cm", { q: "type 2 diabetes kidney", billable: true }); for await (const code of hdev.codes.iterate("hcpcs", { q: "wheelchair" })) console.log(code.code); // Hierarchy, batch (any length, split into requests of 100) and drugs const tree = await hdev.codes.hierarchy("icd10cm", "E11.22"); const many = await hdev.codes.batch("icd10cm", ["E11.9", "I10", "NOPE"]); const product = await hdev.drugs.ndc("0093-1048-01"); // includes linked RxNorm concepts try { await hdev.codes.get("icd10cm", "XYZ"); } catch (err) { if (err instanceof NotFoundError) console.log(err.detail); } ``` ## Behavior - **Retries:** 429 `rate-limited`, 5xx and network errors are retried twice with exponential backoff and jitter, honoring `Retry-After`. `QuotaExceededError` is never retried. - **Errors:** every failure is a `HealthcareDevError`; API problems are `ApiError` subclasses with `status`, the stable problem `code`, `detail` and `requestId`. - **Options:** `apiKey`, `baseUrl`, `maxRetries` (2), `timeoutMs` (30,000), `fetch`, `userAgent`. - Runs on Node 18+, Deno, Bun and edge runtimes. Never put a live key in browser code. Types are generated from the same OpenAPI spec as this reference, so they never drift from the API. A Python SDK is planned. --- # CLI URL: https://docs.healthcare.dev/guides/cli ```sh npm i -g @healthcare.dev/cli export HDEV_API_KEY=hdev_live_... hdev code icd10 E11.9 # one code hdev search icd10 type 2 diabetes --billable hdev tree icd10 E11.2 # ancestors and children hdev drug metformin # search by name hdev drug 0093-1048-01 # NDC, with linked RxNorm concepts hdev drug 861007 # RxCUI hdev changes icd10cm --since 2026-10-01 # what the latest release changed hdev npi 1234567893 # check digit (offline) hdev datasets # versions and freshness hdev status # no key needed ``` Tables by default. Put `--json` before the command for the raw response: ```sh hdev --json search hcpcs wheelchair | jq '.data[].code' ``` Errors go to stderr with exit code 1. Options: `--api-key` (default `HDEV_API_KEY`), `--api-url` (default `HDEV_API_URL`). --- # Agent skill URL: https://docs.healthcare.dev/agents/skill Drop this into your agent's skills folder (for Claude Code: `.claude/skills/healthcare-dev/SKILL.md`) or paste it into a system prompt. The raw file is at [`/skill.md`](/skill.md). ```md --- name: healthcare-dev description: Look up US healthcare reference data (ICD-10-CM/PCS, HCPCS, NDC, RxNorm, NPI check digits) with healthcare.dev. Use for code lookups, code search, NDC to RxNorm mapping and dataset freshness. Not for clinical advice or anything about a specific patient. --- # healthcare.dev - Base URL https://api.healthcare.dev/v1; header `Authorization: Bearer $HDEV_API_KEY`. - MCP: https://mcp.healthcare.dev/mcp (same key). Prefer MCP tools when they're connected. - Responses: `{ data, meta: { source, data_version, retrieved_at, license }, links }`. Cite `meta.source` and `meta.data_version` in answers. - Errors: problem+json; branch on `type` (`not-found`, `invalid-request`, `rate-limited`, `quota-exceeded`, `dataset-unavailable`). On `rate-limited`, wait `Retry-After` seconds. - Never send PHI: no patient names, dates of birth, member ids or free-text notes about a person. - This is reference data, not medical, coding or billing advice. Say so when it matters. ## Recipes - Look up a code: GET /v1/codes/{icd10cm|icd10pcs|hcpcs}/{code} (dot optional). - Find a code from words: GET /v1/codes/icd10cm?q=&billable=true&limit=10. Show the top matches with `display`; don't silently pick one. - Is a code billable? `data.billable`. Header codes (`E11`) are not billable; use a child. - Find a code's replacement: the record's `status` and `replaced_by`; retired codes still resolve. - A code as of a past date: add `as_of=YYYY-MM-DD`. - Many codes: POST /v1/codes/{system}/batch with {"codes": [...]} (max 100); check `found`. - NDC to RxNorm: GET /v1/drugs/ndc/{ndc} (any format) and read `rxcuis` / `rxnorm`. - Drug by name: GET /v1/drugs/search?q=. - Verify an NPI's check digit: Luhn with prefix 80840, or the MCP tool `validate_npi`. - What changed: GET /v1/changes?dataset=icd10cm&since=. - Freshness: GET /v1/status (no key). ``` ## Package skills Each package ships its own `SKILL.md` with rules and recipes for that tool: - SDK: [`@healthcare.dev/sdk` SKILL.md](https://github.com/healthcaredotdev/healthcare.dev/blob/main/packages/sdk-ts/SKILL.md) - CLI: [`@healthcare.dev/cli` SKILL.md](https://github.com/healthcaredotdev/healthcare.dev/blob/main/packages/cli/SKILL.md) - MCP server: [`@healthcare.dev/mcp` SKILL.md](https://github.com/healthcaredotdev/healthcare.dev/blob/main/apps/mcp/SKILL.md) ## Task recipes See [Recipes](/agents/recipes) for worked examples of the common tasks. --- # Recipes URL: https://docs.healthcare.dev/agents/recipes ## Verify an NPI An NPI is 10 digits; the last is a Luhn check digit computed over `80840` plus the first nine. ```ts import { isValidNpi } from "@healthcare.dev/sdk"; isValidNpi("1234567893"); // true ``` A valid check digit doesn't prove the provider exists or is active. Provider lookups (`/v1/providers/{npi}`) are coming with the NPPES dataset. ## Map an NDC to RxNorm ```sh curl https://api.healthcare.dev/v1/drugs/ndc/0093-1048-01 \ -H "Authorization: Bearer $HDEV_API_KEY" | jq '.data.rxnorm' ``` ```json [{ "rxcui": "861007", "name": "metformin hydrochloride 500 MG Oral Tablet", "tty": "SCD" }] ``` Any NDC format works: `0093-1048-01`, `00093104801` or the product NDC `0093-1048`. ## Find a code's replacement Retired codes still resolve, so you never have to guess: ```sh curl https://api.healthcare.dev/v1/codes/icd10cm/ \ -H "Authorization: Bearer $HDEV_API_KEY" | jq '.data | {status, effective_end, replaced_by}' ``` If `replaced_by` is empty, the source named no successor: search by description instead and let a person choose. ## Check a code was valid on a date ```sh curl "https://api.healthcare.dev/v1/codes/icd10cm/E11.9?as_of=2019-06-01" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` ## Keep a local copy current Poll `/v1/changes?dataset=icd10cm&since=` daily and apply `added`, `changed` and `retired` rows. --- # Example: referral checker URL: https://docs.healthcare.dev/agents/referral-checker Checks the structured parts of a referral: the receiving provider's NPI and the ICD-10-CM codes. It works on identifiers only; patient details never leave your system. ```ts import { HealthcareDev, isValidNpi } from "@healthcare.dev/sdk"; const hdev = new HealthcareDev(); export async function checkReferral(input: { npi: string; diagnosisCodes: string[] }) { const issues: string[] = []; if (!isValidNpi(input.npi)) issues.push(`NPI ${input.npi} fails the check digit`); const { data, meta } = await hdev.codes.batch("icd10cm", input.diagnosisCodes); for (const r of data) { if (!r.found) issues.push(`${r.code} is not an ICD-10-CM code`); else if (r.record && !r.record.billable) issues.push(`${r.code} is a header code; pick a more specific child`); else if (r.record && r.record.status !== "active") issues.push( `${r.code} is ${r.record.status}; replaced by ${r.record.replaced_by.join(", ") || "nothing listed"}`, ); } return { ok: issues.length === 0, issues, cite: `${meta.source} ${meta.data_version}` }; } ``` With MCP, give the agent `validate_npi`, `lookup_code` and `explain_code_hierarchy` and the instruction: _"Check each code is billable and active; suggest children for header codes; never choose a diagnosis yourself."_ --- # Example: claim code validator URL: https://docs.healthcare.dev/agents/claim-code-validator Runs before a claim is submitted: every code must exist, be billable and be active on the date of service. Uses `as_of` so last year's claims are checked against last year's codes. ```ts import { HealthcareDev, NotFoundError } from "@healthcare.dev/sdk"; const hdev = new HealthcareDev(); type System = "icd10cm" | "icd10pcs" | "hcpcs"; export async function validateClaimCodes( serviceDate: string, codes: { system: System; code: string }[], ) { return Promise.all( codes.map(async ({ system, code }) => { try { const { data, meta } = await hdev.codes.get(system, code, { as_of: serviceDate }); const valid = data.billable && data.status === "active"; return { system, code, valid, display: data.display, version: meta.data_version }; } catch (err) { if (err instanceof NotFoundError) return { system, code, valid: false, display: null, version: null }; throw err; } }), ); } ``` This checks code validity only. It doesn't check medical necessity, coverage or payer edits, and it isn't coding advice. --- # Example: prescription lookup assistant URL: https://docs.healthcare.dev/agents/prescription-lookup Turns whatever identifier a system has (an NDC in any format, an RxCUI or a name) into normalized RxNorm concepts and FDA package data. ```ts import { HealthcareDev } from "@healthcare.dev/sdk"; const hdev = new HealthcareDev(); export async function resolveDrug(input: string) { const digits = input.replace(/\D/g, ""); if (/^[\d-]+$/.test(input) && digits.length >= 9) { const { data, meta } = await hdev.drugs.ndc(input); return { kind: "ndc", product: data.generic_name, rxnorm: data.rxnorm, packages: data.packages, version: meta.data_version, }; } const { data, meta } = await hdev.drugs.search({ q: input, limit: 5 }); return { kind: "search", candidates: data, version: meta.data_version }; } ``` For MCP agents, the `check_ndc` prompt does the same with `lookup_drug` and `map_ndc_to_rxnorm`. Drug data here is reference data: it's not dosing, interaction or prescribing guidance. --- # Overview URL: https://docs.healthcare.dev/reference US healthcare reference data. Reference data only, not clinical advice. Never send PHI. Base URL: `https://api.healthcare.dev`. The machine-readable spec is at [`https://api.healthcare.dev/openapi.json`](https://api.healthcare.dev/openapi.json) and [`/openapi.json`](/openapi.json) on this site. ## Codes | Endpoint | What it does | | --- | --- | | [`GET /v1/codes/{system}/{code}`](/reference/codes/look-up-a-code) | Look up a code | | [`GET /v1/codes/{system}`](/reference/codes/search-codes) | Search codes | | [`GET /v1/codes/{system}/{code}/children`](/reference/codes/child-codes) | Child codes | | [`GET /v1/codes/{system}/{code}/parents`](/reference/codes/ancestor-codes) | Ancestor codes | | [`GET /v1/codes/{system}/{code}/hierarchy`](/reference/codes/code-with-ancestors-and-children) | Code with ancestors and children | | [`POST /v1/codes/{system}/batch`](/reference/codes/look-up-up-to-100-codes) | Look up up to 100 codes | ## Drugs | Endpoint | What it does | | --- | --- | | [`GET /v1/drugs/ndc/{ndc}`](/reference/drugs/look-up-an-ndc) | Look up an NDC | | [`GET /v1/drugs/rxnorm/{rxcui}`](/reference/drugs/look-up-an-rxnorm-concept) | Look up an RxNorm concept | | [`GET /v1/drugs/rxnorm`](/reference/drugs/search-rxnorm) | Search RxNorm | | [`GET /v1/drugs/search`](/reference/drugs/search-drugs-across-rxnorm-and-ndc) | Search drugs across RxNorm and NDC | ## Datasets | Endpoint | What it does | | --- | --- | | [`GET /v1/datasets`](/reference/datasets/dataset-catalog) | Dataset catalog | | [`GET /v1/changes`](/reference/datasets/change-feed) | Change feed | ## Taxonomies | Endpoint | What it does | | --- | --- | | [`GET /v1/taxonomies/{code}`](/reference/taxonomies/look-up-a-provider-taxonomy-code) | Look up a provider taxonomy code | | [`GET /v1/taxonomies`](/reference/taxonomies/search-provider-taxonomies) | Search provider taxonomies | ## Service | Endpoint | What it does | | --- | --- | | [`GET /healthz`](/reference/service/process-liveness) | Process liveness | | [`GET /readyz`](/reference/service/dependency-readiness) | Dependency readiness | | [`GET /v1/status`](/reference/service/service-and-data-freshness-status) | Service and data freshness status | --- # Look up a code URL: https://docs.healthcare.dev/reference/codes/look-up-a-code ```http GET https://api.healthcare.dev/v1/codes/{system}/{code} ``` Returns one ICD-10-CM, ICD-10-PCS or HCPCS Level II code with its description, billable flag, parent and lifecycle (`status`, `effective_start`, `effective_end`). Retired codes stay available. Pass `as_of` to get the code as it was on a past date. Requires an API key: `Authorization: Bearer hdev_live_...`. See [Authentication](/authentication). ## Path parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `system` | "icd10cm" \| "icd10pcs" \| "hcpcs" | yes | Code system | `icd10cm` | | `code` | string | yes | Code, with or without the dot | `E11.9` | ## Query parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `as_of` | string (date) | no | Return the record as it was on this date (YYYY-MM-DD) | `2025-01-01` | | `view` | "compact" \| "full" | no | `compact` returns only the fields an agent usually needs (fewer tokens); `full` (default) returns every field | `compact` | | `fields` | string | no | Comma-separated record fields to return, e.g. `code,display,billable` | `code,display,billable` | ## Examples **curl** ```sh curl "https://api.healthcare.dev/v1/codes/icd10cm/E11.9" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/v1/codes/icd10cm/E11.9", { headers: { Authorization: `Bearer ${process.env.HDEV_API_KEY}` }, }); const { data, meta } = await res.json(); ``` **Python** ```python import os import requests res = requests.get("https://api.healthcare.dev/v1/codes/icd10cm/E11.9", headers={"Authorization": f"Bearer {os.environ['HDEV_API_KEY']}"}) body = res.json() ``` ## Response The code ```json { "data": { "system": "icd10cm", "code": "E11.9", "display": "Type 2 diabetes mellitus without complications", "description": "Type 2 diabetes mellitus without complications", "billable": true, "parent": "E11", "attributes": {}, "status": "active", "effective_start": "2015-10-01", "effective_end": null, "replaced_by": [] }, "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS). Reference data, not medical advice." }, "links": { "self": "/v1/codes/icd10cm/E11.9", "next": null } } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `system` | "icd10cm" \| "icd10pcs" \| "hcpcs" | yes | | | `code` | string | yes | | | `display` | string | yes | Short description | | `description` | string \| null | yes | Long description | | `billable` | boolean | yes | Valid for billing (leaf / header flag) | | `parent` | string \| null | yes | | | `attributes` | object | no | System-specific attributes, e.g. HCPCS coverage and BETOS codes | | `status` | "active" \| "retired" \| "replaced" | yes | | | `effective_start` | string (date) | yes | | | `effective_end` | string \| null (date) | yes | | | `replaced_by` | string[] | no | | ## Errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)). Branch on `type`, not on `title`. See [Errors](/errors). | Status | `type` | When | | --- | --- | --- | | 400 | `invalid-request` | A parameter or the body failed validation; `errors` lists each field. | | 401 | `unauthorized` | Missing, malformed or revoked API key. | | 404 | `not-found` | No record with that id (retired records are still returned). | | 429 | `rate-limited / quota-exceeded` | Too many requests per second (retry after `Retry-After`), or the monthly quota is used up. | | 503 | `dataset-unavailable / unavailable` | The dataset has no published version yet, or the service is degraded. | --- # Search codes URL: https://docs.healthcare.dev/reference/codes/search-codes ```http GET https://api.healthcare.dev/v1/codes/{system} ``` Search by description or code prefix. Exact code matches rank first, then code prefixes, then descriptions containing every word of the query (stemmed, any order) by relevance, then close matches for typos. Retired codes are excluded unless `include_retired=true`. Requires an API key: `Authorization: Bearer hdev_live_...`. See [Authentication](/authentication). ## Path parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `system` | "icd10cm" \| "icd10pcs" \| "hcpcs" | yes | Code system | `icd10cm` | ## Query parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `q` | string | yes | Search text (fuzzy) | `diabetes` | | `limit` | integer | no | Page size (max 100) | `25` | | `cursor` | string | no | Opaque cursor from `links.next` | | | `billable` | "true" \| "false" | no | Only billable (true) or header (false) codes | `true` | | `include_retired` | "true" \| "false" | no | Also return retired codes (default false) | `true` | | `view` | "compact" \| "full" | no | `compact` returns only the fields an agent usually needs (fewer tokens); `full` (default) returns every field | `compact` | | `fields` | string | no | Comma-separated record fields to return, e.g. `code,display,billable` | `code,display,billable` | ## Examples **curl** ```sh curl "https://api.healthcare.dev/v1/codes/icd10cm?q=diabetes&limit=25" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/v1/codes/icd10cm?q=diabetes&limit=25", { headers: { Authorization: `Bearer ${process.env.HDEV_API_KEY}` }, }); const { data, meta } = await res.json(); ``` **Python** ```python import os import requests res = requests.get("https://api.healthcare.dev/v1/codes/icd10cm?q=diabetes&limit=25", headers={"Authorization": f"Bearer {os.environ['HDEV_API_KEY']}"}) body = res.json() ``` ## Response Matching codes, best first ```json { "data": [ { "system": "icd10cm", "code": "string", "display": "string", "description": "string", "billable": true, "parent": "string", "attributes": {}, "status": "active", "effective_start": "2026-10-01", "effective_end": "2026-10-01", "replaced_by": [ "string" ], "match_score": 0 } ], "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS). Reference data, not medical advice." }, "links": { "self": "/v1/codes/icd10cm?q=diabetes&limit=25", "next": "/v1/codes/icd10cm?q=diabetes&limit=25&cursor=eyJrIjoiRTExLjkifQ" } } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `system` | "icd10cm" \| "icd10pcs" \| "hcpcs" | yes | | | `code` | string | yes | | | `display` | string | yes | Short description | | `description` | string \| null | yes | Long description | | `billable` | boolean | yes | Valid for billing (leaf / header flag) | | `parent` | string \| null | yes | | | `attributes` | object | no | System-specific attributes, e.g. HCPCS coverage and BETOS codes | | `status` | "active" \| "retired" \| "replaced" | yes | | | `effective_start` | string (date) | yes | | | `effective_end` | string \| null (date) | yes | | | `replaced_by` | string[] | no | | | `match_score` | number | yes | How well this result matches the query: 1 exact code or id, 0.9 code prefix, 0.5 to 0.9 every query word in the text (higher is closer), under 0.5 a fuzzy (typo-tolerant) match. Below 0.5, check the result before relying on it. | ## Errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)). Branch on `type`, not on `title`. See [Errors](/errors). | Status | `type` | When | | --- | --- | --- | | 400 | `invalid-request` | A parameter or the body failed validation; `errors` lists each field. | | 401 | `unauthorized` | Missing, malformed or revoked API key. | | 404 | `not-found` | No record with that id (retired records are still returned). | | 429 | `rate-limited / quota-exceeded` | Too many requests per second (retry after `Retry-After`), or the monthly quota is used up. | | 503 | `dataset-unavailable / unavailable` | The dataset has no published version yet, or the service is degraded. | --- # Child codes URL: https://docs.healthcare.dev/reference/codes/child-codes ```http GET https://api.healthcare.dev/v1/codes/{system}/{code}/children ``` Direct children of a code in the hierarchy (active codes only). Requires an API key: `Authorization: Bearer hdev_live_...`. See [Authentication](/authentication). ## Path parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `system` | "icd10cm" \| "icd10pcs" \| "hcpcs" | yes | Code system | `icd10cm` | | `code` | string | yes | Code, with or without the dot | `E11.9` | ## Query parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `view` | "compact" \| "full" | no | `compact` returns only the fields an agent usually needs (fewer tokens); `full` (default) returns every field | `compact` | | `fields` | string | no | Comma-separated record fields to return, e.g. `code,display,billable` | `code,display,billable` | ## Examples **curl** ```sh curl "https://api.healthcare.dev/v1/codes/icd10cm/E11.9/children" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/v1/codes/icd10cm/E11.9/children", { headers: { Authorization: `Bearer ${process.env.HDEV_API_KEY}` }, }); const { data, meta } = await res.json(); ``` **Python** ```python import os import requests res = requests.get("https://api.healthcare.dev/v1/codes/icd10cm/E11.9/children", headers={"Authorization": f"Bearer {os.environ['HDEV_API_KEY']}"}) body = res.json() ``` ## Response Children ```json { "data": [ { "system": "icd10cm", "code": "E11.9", "display": "Type 2 diabetes mellitus without complications", "description": "Type 2 diabetes mellitus without complications", "billable": true, "parent": "E11", "attributes": {}, "status": "active", "effective_start": "2015-10-01", "effective_end": null, "replaced_by": [] } ], "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS). Reference data, not medical advice." }, "links": { "self": "/v1/codes/icd10cm/E11.9/children", "next": "/v1/codes/icd10cm/E11.9/children?cursor=eyJrIjoiRTExLjkifQ" } } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `system` | "icd10cm" \| "icd10pcs" \| "hcpcs" | yes | | | `code` | string | yes | | | `display` | string | yes | Short description | | `description` | string \| null | yes | Long description | | `billable` | boolean | yes | Valid for billing (leaf / header flag) | | `parent` | string \| null | yes | | | `attributes` | object | no | System-specific attributes, e.g. HCPCS coverage and BETOS codes | | `status` | "active" \| "retired" \| "replaced" | yes | | | `effective_start` | string (date) | yes | | | `effective_end` | string \| null (date) | yes | | | `replaced_by` | string[] | no | | ## Errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)). Branch on `type`, not on `title`. See [Errors](/errors). | Status | `type` | When | | --- | --- | --- | | 400 | `invalid-request` | A parameter or the body failed validation; `errors` lists each field. | | 401 | `unauthorized` | Missing, malformed or revoked API key. | | 404 | `not-found` | No record with that id (retired records are still returned). | | 429 | `rate-limited / quota-exceeded` | Too many requests per second (retry after `Retry-After`), or the monthly quota is used up. | | 503 | `dataset-unavailable / unavailable` | The dataset has no published version yet, or the service is degraded. | --- # Ancestor codes URL: https://docs.healthcare.dev/reference/codes/ancestor-codes ```http GET https://api.healthcare.dev/v1/codes/{system}/{code}/parents ``` Ancestors of a code from the root down to its immediate parent. Requires an API key: `Authorization: Bearer hdev_live_...`. See [Authentication](/authentication). ## Path parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `system` | "icd10cm" \| "icd10pcs" \| "hcpcs" | yes | Code system | `icd10cm` | | `code` | string | yes | Code, with or without the dot | `E11.9` | ## Query parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `view` | "compact" \| "full" | no | `compact` returns only the fields an agent usually needs (fewer tokens); `full` (default) returns every field | `compact` | | `fields` | string | no | Comma-separated record fields to return, e.g. `code,display,billable` | `code,display,billable` | ## Examples **curl** ```sh curl "https://api.healthcare.dev/v1/codes/icd10cm/E11.9/parents" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/v1/codes/icd10cm/E11.9/parents", { headers: { Authorization: `Bearer ${process.env.HDEV_API_KEY}` }, }); const { data, meta } = await res.json(); ``` **Python** ```python import os import requests res = requests.get("https://api.healthcare.dev/v1/codes/icd10cm/E11.9/parents", headers={"Authorization": f"Bearer {os.environ['HDEV_API_KEY']}"}) body = res.json() ``` ## Response Ancestors ```json { "data": [ { "system": "icd10cm", "code": "E11.9", "display": "Type 2 diabetes mellitus without complications", "description": "Type 2 diabetes mellitus without complications", "billable": true, "parent": "E11", "attributes": {}, "status": "active", "effective_start": "2015-10-01", "effective_end": null, "replaced_by": [] } ], "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS). Reference data, not medical advice." }, "links": { "self": "/v1/codes/icd10cm/E11.9/parents", "next": "/v1/codes/icd10cm/E11.9/parents?cursor=eyJrIjoiRTExLjkifQ" } } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `system` | "icd10cm" \| "icd10pcs" \| "hcpcs" | yes | | | `code` | string | yes | | | `display` | string | yes | Short description | | `description` | string \| null | yes | Long description | | `billable` | boolean | yes | Valid for billing (leaf / header flag) | | `parent` | string \| null | yes | | | `attributes` | object | no | System-specific attributes, e.g. HCPCS coverage and BETOS codes | | `status` | "active" \| "retired" \| "replaced" | yes | | | `effective_start` | string (date) | yes | | | `effective_end` | string \| null (date) | yes | | | `replaced_by` | string[] | no | | ## Errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)). Branch on `type`, not on `title`. See [Errors](/errors). | Status | `type` | When | | --- | --- | --- | | 400 | `invalid-request` | A parameter or the body failed validation; `errors` lists each field. | | 401 | `unauthorized` | Missing, malformed or revoked API key. | | 404 | `not-found` | No record with that id (retired records are still returned). | | 429 | `rate-limited / quota-exceeded` | Too many requests per second (retry after `Retry-After`), or the monthly quota is used up. | | 503 | `dataset-unavailable / unavailable` | The dataset has no published version yet, or the service is degraded. | --- # Code with ancestors and children URL: https://docs.healthcare.dev/reference/codes/code-with-ancestors-and-children ```http GET https://api.healthcare.dev/v1/codes/{system}/{code}/hierarchy ``` The code, its ancestors (root first) and its direct active children in one call. Requires an API key: `Authorization: Bearer hdev_live_...`. See [Authentication](/authentication). ## Path parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `system` | "icd10cm" \| "icd10pcs" \| "hcpcs" | yes | Code system | `icd10cm` | | `code` | string | yes | Code, with or without the dot | `E11.9` | ## Query parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `view` | "compact" \| "full" | no | `compact` returns only the fields an agent usually needs (fewer tokens); `full` (default) returns every field | `compact` | | `fields` | string | no | Comma-separated record fields to return, e.g. `code,display,billable` | `code,display,billable` | ## Examples **curl** ```sh curl "https://api.healthcare.dev/v1/codes/icd10cm/E11.9/hierarchy" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/v1/codes/icd10cm/E11.9/hierarchy", { headers: { Authorization: `Bearer ${process.env.HDEV_API_KEY}` }, }); const { data, meta } = await res.json(); ``` **Python** ```python import os import requests res = requests.get("https://api.healthcare.dev/v1/codes/icd10cm/E11.9/hierarchy", headers={"Authorization": f"Bearer {os.environ['HDEV_API_KEY']}"}) body = res.json() ``` ## Response Hierarchy ```json { "data": { "parents": [ { "system": "icd10cm", "code": "E11.9", "display": "Type 2 diabetes mellitus without complications", "description": "Type 2 diabetes mellitus without complications", "billable": true, "parent": "E11", "attributes": {}, "status": "active", "effective_start": "2015-10-01", "effective_end": null, "replaced_by": [] } ], "code": { "system": "icd10cm", "code": "E11.9", "display": "Type 2 diabetes mellitus without complications", "description": "Type 2 diabetes mellitus without complications", "billable": true, "parent": "E11", "attributes": {}, "status": "active", "effective_start": "2015-10-01", "effective_end": null, "replaced_by": [] }, "children": [ { "system": "icd10cm", "code": "E11.9", "display": "Type 2 diabetes mellitus without complications", "description": "Type 2 diabetes mellitus without complications", "billable": true, "parent": "E11", "attributes": {}, "status": "active", "effective_start": "2015-10-01", "effective_end": null, "replaced_by": [] } ] }, "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS). Reference data, not medical advice." }, "links": { "self": "/v1/codes/icd10cm/E11.9/hierarchy", "next": null } } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `parents` | Code[] | yes | | | `code` | Code | yes | | | `children` | Code[] | yes | | ## Errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)). Branch on `type`, not on `title`. See [Errors](/errors). | Status | `type` | When | | --- | --- | --- | | 400 | `invalid-request` | A parameter or the body failed validation; `errors` lists each field. | | 401 | `unauthorized` | Missing, malformed or revoked API key. | | 404 | `not-found` | No record with that id (retired records are still returned). | | 429 | `rate-limited / quota-exceeded` | Too many requests per second (retry after `Retry-After`), or the monthly quota is used up. | | 503 | `dataset-unavailable / unavailable` | The dataset has no published version yet, or the service is degraded. | --- # Look up up to 100 codes URL: https://docs.healthcare.dev/reference/codes/look-up-up-to-100-codes ```http POST https://api.healthcare.dev/v1/codes/{system}/batch ``` Looks up many codes in one request. Results come back in request order; unknown codes have `found: false`. Requires an API key: `Authorization: Bearer hdev_live_...`. See [Authentication](/authentication). ## Path parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `system` | "icd10cm" \| "icd10pcs" \| "hcpcs" | yes | Code system | `icd10cm` | ## Query parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `view` | "compact" \| "full" | no | `compact` returns only the fields an agent usually needs (fewer tokens); `full` (default) returns every field | `compact` | | `fields` | string | no | Comma-separated record fields to return, e.g. `code,display,billable` | `code,display,billable` | ## Request body ```json { "codes": [ "E11.9", "I10" ] } ``` ## Examples **curl** ```sh curl -X POST "https://api.healthcare.dev/v1/codes/icd10cm/batch" \ -H "Authorization: Bearer $HDEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{"codes":["E11.9","I10"]}' ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/v1/codes/icd10cm/batch", { method: "POST", headers: { Authorization: `Bearer ${process.env.HDEV_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({"codes":["E11.9","I10"]}), }); const { data, meta } = await res.json(); ``` **Python** ```python import os import requests res = requests.post("https://api.healthcare.dev/v1/codes/icd10cm/batch", headers={"Authorization": f"Bearer {os.environ['HDEV_API_KEY']}"}, json={"codes":["E11.9","I10"]}) body = res.json() ``` ## Response Results in request order ```json { "data": [ { "code": "E11.9", "found": true, "record": { "system": "icd10cm", "code": "E11.9", "display": "Type 2 diabetes mellitus without complications", "description": "Type 2 diabetes mellitus without complications", "billable": true, "parent": "E11", "attributes": {}, "status": "active", "effective_start": "2015-10-01", "effective_end": null, "replaced_by": [] } } ], "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS). Reference data, not medical advice." }, "links": { "self": "/v1/codes/icd10cm/batch", "next": "/v1/codes/icd10cm/batch?cursor=eyJrIjoiRTExLjkifQ" } } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `code` | string | yes | | | `found` | boolean | yes | | | `record` | | yes | | ## Errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)). Branch on `type`, not on `title`. See [Errors](/errors). | Status | `type` | When | | --- | --- | --- | | 400 | `invalid-request` | A parameter or the body failed validation; `errors` lists each field. | | 401 | `unauthorized` | Missing, malformed or revoked API key. | | 404 | `not-found` | No record with that id (retired records are still returned). | | 429 | `rate-limited / quota-exceeded` | Too many requests per second (retry after `Retry-After`), or the monthly quota is used up. | | 503 | `dataset-unavailable / unavailable` | The dataset has no published version yet, or the service is degraded. | --- # Look up an NDC URL: https://docs.healthcare.dev/reference/drugs/look-up-an-ndc ```http GET https://api.healthcare.dev/v1/drugs/ndc/{ndc} ``` Accepts a product NDC (`0002-0152`), a package NDC in any 10-digit layout (`0002-0152-01`) or an 11-digit NDC (`00002015201`). Returns the FDA product with its packages (each normalized to NDC-11) and the linked RxNorm concepts (`rxcuis`). Requires an API key: `Authorization: Bearer hdev_live_...`. See [Authentication](/authentication). ## Path parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `ndc` | string | yes | Product, package (any 10-digit layout) or 11-digit NDC, with or without hyphens | `0002-0152-01` | ## Query parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `view` | "compact" \| "full" | no | `compact` returns only the fields an agent usually needs (fewer tokens); `full` (default) returns every field | `compact` | | `fields` | string | no | Comma-separated record fields to return, e.g. `code,display,billable` | `code,display,billable` | ## Examples **curl** ```sh curl "https://api.healthcare.dev/v1/drugs/ndc/0002-0152-01" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/v1/drugs/ndc/0002-0152-01", { headers: { Authorization: `Bearer ${process.env.HDEV_API_KEY}` }, }); const { data, meta } = await res.json(); ``` **Python** ```python import os import requests res = requests.get("https://api.healthcare.dev/v1/drugs/ndc/0002-0152-01", headers={"Authorization": f"Bearer {os.environ['HDEV_API_KEY']}"}) body = res.json() ``` ## Response The product ```json { "data": { "product_ndc": "0093-1048", "spl_document_ids": [ "b7b1c1f2-2a5e-4e3c-9b39-4c7c1d8f0a11" ], "brand_name": null, "generic_name": "Metformin Hydrochloride", "labeler": "Teva Pharmaceuticals USA, Inc.", "dosage_form": "TABLET, FILM COATED", "route": [ "ORAL" ], "active_ingredients": [ { "name": "METFORMIN HYDROCHLORIDE", "strength": "500 mg/1" } ], "product_type": "HUMAN PRESCRIPTION DRUG", "marketing_category": "ANDA", "application_number": "ANDA075977", "pharm_classes": [ "Biguanide [EPC]" ], "dea_schedule": null, "listing_certified_through": "2026-12-31", "rxcuis": [ "861007" ], "rxnorm": [ { "rxcui": "861007", "name": "metformin hydrochloride 500 MG Oral Tablet", "tty": "SCD" } ], "packages": [ { "ndc": "0093-1048-01", "ndc11": "00093104801", "description": "100 TABLET, FILM COATED in 1 BOTTLE (0093-1048-01)", "marketing_start": "2002-01-24", "marketing_end": null } ], "status": "active", "effective_start": "2026-10-01", "effective_end": null, "replaced_by": [] }, "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS). Reference data, not medical advice." }, "links": { "self": "/v1/drugs/ndc/0002-0152-01", "next": null } } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `product_ndc` | string | yes | | | `spl_document_ids` | string[] | yes | SPL documents listing this product (FDA PRODUCTID suffixes) | | `brand_name` | string \| null | yes | | | `generic_name` | string \| null | yes | | | `labeler` | string | yes | | | `dosage_form` | string \| null | yes | | | `route` | string[] | yes | | | `active_ingredients` | object[] | yes | | | `product_type` | string | yes | | | `marketing_category` | string \| null | yes | | | `application_number` | string \| null | yes | | | `pharm_classes` | string[] | yes | | | `dea_schedule` | string \| null | yes | | | `listing_certified_through` | string \| null (date) | yes | | | `rxcuis` | string[] | no | Linked RxNorm concepts (filled at query time) | | `rxnorm` | object[] | no | Linked RxNorm concepts with names and term types (filled at query time) | | `packages` | NdcPackage[] | yes | | | `status` | "active" \| "retired" \| "replaced" | yes | | | `effective_start` | string (date) | yes | | | `effective_end` | string \| null (date) | yes | | | `replaced_by` | string[] | no | | ## Errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)). Branch on `type`, not on `title`. See [Errors](/errors). | Status | `type` | When | | --- | --- | --- | | 400 | `invalid-request` | A parameter or the body failed validation; `errors` lists each field. | | 401 | `unauthorized` | Missing, malformed or revoked API key. | | 404 | `not-found` | No record with that id (retired records are still returned). | | 429 | `rate-limited / quota-exceeded` | Too many requests per second (retry after `Retry-After`), or the monthly quota is used up. | | 503 | `dataset-unavailable / unavailable` | The dataset has no published version yet, or the service is degraded. | --- # Look up an RxNorm concept URL: https://docs.healthcare.dev/reference/drugs/look-up-an-rxnorm-concept ```http GET https://api.healthcare.dev/v1/drugs/rxnorm/{rxcui} ``` An RxNorm concept with its term type, ingredients, related concepts and linked NDC-11s. Requires an API key: `Authorization: Bearer hdev_live_...`. See [Authentication](/authentication). ## Path parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `rxcui` | string | yes | RxNorm concept unique identifier | `861007` | ## Query parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `view` | "compact" \| "full" | no | `compact` returns only the fields an agent usually needs (fewer tokens); `full` (default) returns every field | `compact` | | `fields` | string | no | Comma-separated record fields to return, e.g. `code,display,billable` | `code,display,billable` | ## Examples **curl** ```sh curl "https://api.healthcare.dev/v1/drugs/rxnorm/861007" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/v1/drugs/rxnorm/861007", { headers: { Authorization: `Bearer ${process.env.HDEV_API_KEY}` }, }); const { data, meta } = await res.json(); ``` **Python** ```python import os import requests res = requests.get("https://api.healthcare.dev/v1/drugs/rxnorm/861007", headers={"Authorization": f"Bearer {os.environ['HDEV_API_KEY']}"}) body = res.json() ``` ## Response The concept ```json { "data": { "rxcui": "861007", "name": "metformin hydrochloride 500 MG Oral Tablet", "tty": "SCD", "prescribable_name": "metformin hydrochloride 500 MG Oral Tablet", "synonyms": [], "ingredients": [ { "rxcui": "6809", "name": "metformin" } ], "related": [], "ndcs": [ "00093104801" ], "status": "active", "effective_start": "2026-10-06", "effective_end": null, "replaced_by": [] }, "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS). Reference data, not medical advice." }, "links": { "self": "/v1/drugs/rxnorm/861007", "next": null } } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `rxcui` | string | yes | | | `name` | string | yes | | | `tty` | string | yes | RxNorm term type, e.g. SCD, SBD, IN | | `prescribable_name` | string \| null | yes | RxNorm PSN, when one exists | | `synonyms` | string[] | yes | | | `ingredients` | object[] | yes | | | `related` | object[] | yes | | | `ndcs` | string[] | yes | NDC-11s linked by RxNorm | | `status` | "active" \| "retired" \| "replaced" | yes | | | `effective_start` | string (date) | yes | | | `effective_end` | string \| null (date) | yes | | | `replaced_by` | string[] | no | | ## Errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)). Branch on `type`, not on `title`. See [Errors](/errors). | Status | `type` | When | | --- | --- | --- | | 400 | `invalid-request` | A parameter or the body failed validation; `errors` lists each field. | | 401 | `unauthorized` | Missing, malformed or revoked API key. | | 404 | `not-found` | No record with that id (retired records are still returned). | | 429 | `rate-limited / quota-exceeded` | Too many requests per second (retry after `Retry-After`), or the monthly quota is used up. | | 503 | `dataset-unavailable / unavailable` | The dataset has no published version yet, or the service is degraded. | --- # Search RxNorm URL: https://docs.healthcare.dev/reference/drugs/search-rxnorm ```http GET https://api.healthcare.dev/v1/drugs/rxnorm ``` Fuzzy search over RxNorm names, prescribable names and synonyms. Filter by term type with `tty` (e.g. `IN`, `SCD`, `SBD`). Requires an API key: `Authorization: Bearer hdev_live_...`. See [Authentication](/authentication). ## Query parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `q` | string | yes | Search text (fuzzy) | `diabetes` | | `limit` | integer | no | Page size (max 100) | `25` | | `cursor` | string | no | Opaque cursor from `links.next` | | | `tty` | string | no | Only concepts of this RxNorm term type | `SCD` | | `view` | "compact" \| "full" | no | `compact` returns only the fields an agent usually needs (fewer tokens); `full` (default) returns every field | `compact` | | `fields` | string | no | Comma-separated record fields to return, e.g. `code,display,billable` | `code,display,billable` | ## Examples **curl** ```sh curl "https://api.healthcare.dev/v1/drugs/rxnorm?q=diabetes&limit=25" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/v1/drugs/rxnorm?q=diabetes&limit=25", { headers: { Authorization: `Bearer ${process.env.HDEV_API_KEY}` }, }); const { data, meta } = await res.json(); ``` **Python** ```python import os import requests res = requests.get("https://api.healthcare.dev/v1/drugs/rxnorm?q=diabetes&limit=25", headers={"Authorization": f"Bearer {os.environ['HDEV_API_KEY']}"}) body = res.json() ``` ## Response Matching concepts, best first ```json { "data": [ { "rxcui": "string", "name": "string", "tty": "string", "prescribable_name": "string", "synonyms": [ "string" ], "ingredients": [ { "rxcui": "string", "name": "string" } ], "related": [ { "rxcui": "string", "name": "string", "tty": "string", "rela": "string" } ], "ndcs": [ "string" ], "status": "active", "effective_start": "2026-10-01", "effective_end": "2026-10-01", "replaced_by": [ "string" ], "match_score": 0 } ], "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS). Reference data, not medical advice." }, "links": { "self": "/v1/drugs/rxnorm?q=diabetes&limit=25", "next": "/v1/drugs/rxnorm?q=diabetes&limit=25&cursor=eyJrIjoiRTExLjkifQ" } } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `rxcui` | string | yes | | | `name` | string | yes | | | `tty` | string | yes | RxNorm term type, e.g. SCD, SBD, IN | | `prescribable_name` | string \| null | yes | RxNorm PSN, when one exists | | `synonyms` | string[] | yes | | | `ingredients` | object[] | yes | | | `related` | object[] | yes | | | `ndcs` | string[] | yes | NDC-11s linked by RxNorm | | `status` | "active" \| "retired" \| "replaced" | yes | | | `effective_start` | string (date) | yes | | | `effective_end` | string \| null (date) | yes | | | `replaced_by` | string[] | no | | | `match_score` | number | yes | How well this result matches the query: 1 exact code or id, 0.9 code prefix, 0.5 to 0.9 every query word in the text (higher is closer), under 0.5 a fuzzy (typo-tolerant) match. Below 0.5, check the result before relying on it. | ## Errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)). Branch on `type`, not on `title`. See [Errors](/errors). | Status | `type` | When | | --- | --- | --- | | 400 | `invalid-request` | A parameter or the body failed validation; `errors` lists each field. | | 401 | `unauthorized` | Missing, malformed or revoked API key. | | 404 | `not-found` | No record with that id (retired records are still returned). | | 429 | `rate-limited / quota-exceeded` | Too many requests per second (retry after `Retry-After`), or the monthly quota is used up. | | 503 | `dataset-unavailable / unavailable` | The dataset has no published version yet, or the service is degraded. | --- # Search drugs across RxNorm and NDC URL: https://docs.healthcare.dev/reference/drugs/search-drugs-across-rxnorm-and-ndc ```http GET https://api.healthcare.dev/v1/drugs/search ``` Searches RxNorm concepts and FDA NDC products together, ranked by `match_score` across both (RxNorm first on ties); `limit` applies to each source. Requires an API key: `Authorization: Bearer hdev_live_...`. See [Authentication](/authentication). ## Query parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `q` | string | yes | Search text (fuzzy) | `diabetes` | | `limit` | integer | no | Page size (max 100) | `25` | | `view` | "compact" \| "full" | no | `compact` returns only the fields an agent usually needs (fewer tokens); `full` (default) returns every field | `compact` | | `fields` | string | no | Comma-separated record fields to return, e.g. `code,display,billable` | `code,display,billable` | ## Examples **curl** ```sh curl "https://api.healthcare.dev/v1/drugs/search?q=diabetes&limit=25" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/v1/drugs/search?q=diabetes&limit=25", { headers: { Authorization: `Bearer ${process.env.HDEV_API_KEY}` }, }); const { data, meta } = await res.json(); ``` **Python** ```python import os import requests res = requests.get("https://api.healthcare.dev/v1/drugs/search?q=diabetes&limit=25", headers={"Authorization": f"Bearer {os.environ['HDEV_API_KEY']}"}) body = res.json() ``` ## Response Hits ```json { "data": [ { "type": "rxnorm", "id": "861007", "name": "metformin hydrochloride 500 MG Oral Tablet", "tty": "SCD", "labeler": null } ], "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS). Reference data, not medical advice." }, "links": { "self": "/v1/drugs/search?q=diabetes&limit=25", "next": "/v1/drugs/search?q=diabetes&limit=25&cursor=eyJrIjoiRTExLjkifQ" } } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `type` | "rxnorm" \| "ndc" | yes | | | `id` | string | yes | RxCUI or product NDC | | `name` | string | yes | | | `tty` | string \| null | yes | RxNorm term type (rxnorm hits) | | `labeler` | string \| null | yes | Labeler (ndc hits) | | `match_score` | number | yes | How well this result matches the query: 1 exact code or id, 0.9 code prefix, 0.5 to 0.9 every query word in the text (higher is closer), under 0.5 a fuzzy (typo-tolerant) match. Below 0.5, check the result before relying on it. | ## Errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)). Branch on `type`, not on `title`. See [Errors](/errors). | Status | `type` | When | | --- | --- | --- | | 400 | `invalid-request` | A parameter or the body failed validation; `errors` lists each field. | | 401 | `unauthorized` | Missing, malformed or revoked API key. | | 404 | `not-found` | No record with that id (retired records are still returned). | | 429 | `rate-limited / quota-exceeded` | Too many requests per second (retry after `Retry-After`), or the monthly quota is used up. | | 503 | `dataset-unavailable / unavailable` | The dataset has no published version yet, or the service is degraded. | --- # Dataset catalog URL: https://docs.healthcare.dev/reference/datasets/dataset-catalog ```http GET https://api.healthcare.dev/v1/datasets ``` Every published dataset with its current version, publish time, expected cadence and freshness. Requires an API key: `Authorization: Bearer hdev_live_...`. See [Authentication](/authentication). ## Examples **curl** ```sh curl "https://api.healthcare.dev/v1/datasets" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/v1/datasets", { headers: { Authorization: `Bearer ${process.env.HDEV_API_KEY}` }, }); const { data, meta } = await res.json(); ``` **Python** ```python import os import requests res = requests.get("https://api.healthcare.dev/v1/datasets", headers={"Authorization": f"Bearer {os.environ['HDEV_API_KEY']}"}) body = res.json() ``` ## Response Datasets ```json { "data": [ { "id": "icd10cm", "name": "ICD-10-CM", "source": "cms-icd10", "license": "Public domain (CMS)", "current_version": "2026.1", "published_at": "2026-10-01T06:00:00Z", "expected_cadence_days": 365, "fresh": true } ], "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS). Reference data, not medical advice." }, "links": { "self": "/v1/datasets", "next": "/v1/datasets?cursor=eyJrIjoiRTExLjkifQ" } } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `id` | string | yes | Dataset id, e.g. `nppes`, `icd10cm` | | `name` | string | yes | | | `source` | string | yes | | | `license` | string | yes | | | `source_url` | string \| null (uri) | yes | Upstream page the data is published on | | `current_version` | string \| null | yes | | | `published_at` | string \| null (date-time) | yes | | | `expected_cadence_days` | integer | yes | | | `fresh` | boolean | yes | False when older than 1.5x the expected cadence | ## Errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)). Branch on `type`, not on `title`. See [Errors](/errors). | Status | `type` | When | | --- | --- | --- | | 401 | `unauthorized` | Missing, malformed or revoked API key. | | 429 | `rate-limited / quota-exceeded` | Too many requests per second (retry after `Retry-After`), or the monthly quota is used up. | --- # Change feed URL: https://docs.healthcare.dev/reference/datasets/change-feed ```http GET https://api.healthcare.dev/v1/changes ``` Records added, changed or retired by each published release of a dataset. Oldest first by default (for feed consumers); `order=desc` returns the most recent first. Page with `cursor`. The first (baseline) load of a dataset writes no change rows. Requires an API key: `Authorization: Bearer hdev_live_...`. See [Authentication](/authentication). ## Query parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `dataset` | string | yes | Dataset id from `/v1/datasets` | `icd10cm` | | `since` | string (date-time) | no | Only changes published after this time | | | `limit` | integer | no | Page size, 1 to 1000 (default 100) | `100` | | `order` | "asc" \| "desc" | no | asc = oldest first (default), desc = newest first | `asc` | | `cursor` | string | no | Opaque cursor from `links.next` | | ## Examples **curl** ```sh curl "https://api.healthcare.dev/v1/changes?dataset=icd10cm&limit=100" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/v1/changes?dataset=icd10cm&limit=100", { headers: { Authorization: `Bearer ${process.env.HDEV_API_KEY}` }, }); const { data, meta } = await res.json(); ``` **Python** ```python import os import requests res = requests.get("https://api.healthcare.dev/v1/changes?dataset=icd10cm&limit=100", headers={"Authorization": f"Bearer {os.environ['HDEV_API_KEY']}"}) body = res.json() ``` ## Response Changes ```json { "data": [ { "dataset": "icd10cm", "key": "E11.A", "kind": "added", "data_version": "2026.1", "published_at": "2026-10-01T06:00:00Z" } ], "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS). Reference data, not medical advice." }, "links": { "self": "/v1/changes?dataset=icd10cm&limit=100", "next": "/v1/changes?dataset=icd10cm&limit=100&cursor=eyJrIjoiRTExLjkifQ" } } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `dataset` | string | yes | | | `key` | string | yes | | | `kind` | "added" \| "changed" \| "retired" | yes | | | `data_version` | string | yes | | | `published_at` | string (date-time) | yes | | ## Errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)). Branch on `type`, not on `title`. See [Errors](/errors). | Status | `type` | When | | --- | --- | --- | | 400 | `invalid-request` | A parameter or the body failed validation; `errors` lists each field. | | 401 | `unauthorized` | Missing, malformed or revoked API key. | | 404 | `not-found` | No record with that id (retired records are still returned). | | 429 | `rate-limited / quota-exceeded` | Too many requests per second (retry after `Retry-After`), or the monthly quota is used up. | | 503 | `dataset-unavailable / unavailable` | The dataset has no published version yet, or the service is degraded. | --- # Look up a provider taxonomy code URL: https://docs.healthcare.dev/reference/taxonomies/look-up-a-provider-taxonomy-code ```http GET https://api.healthcare.dev/v1/taxonomies/{code} ``` NUCC Health Care Provider Taxonomy code with classification, specialization and definition. Returns 503 `dataset-unavailable` until the NUCC license is in place. Requires an API key: `Authorization: Bearer hdev_live_...`. See [Authentication](/authentication). > **Not public yet.** NUCC taxonomy descriptions need a commercial license, so these endpoints return `503 dataset-unavailable` until it is signed. Provider records will still carry taxonomy codes. ## Path parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `code` | string | yes | 10-character NUCC taxonomy code | `207Q00000X` | ## Query parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `view` | "compact" \| "full" | no | `compact` returns only the fields an agent usually needs (fewer tokens); `full` (default) returns every field | `compact` | | `fields` | string | no | Comma-separated record fields to return, e.g. `code,display,billable` | `code,display,billable` | ## Examples **curl** ```sh curl "https://api.healthcare.dev/v1/taxonomies/207Q00000X" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/v1/taxonomies/207Q00000X", { headers: { Authorization: `Bearer ${process.env.HDEV_API_KEY}` }, }); const { data, meta } = await res.json(); ``` **Python** ```python import os import requests res = requests.get("https://api.healthcare.dev/v1/taxonomies/207Q00000X", headers={"Authorization": f"Bearer {os.environ['HDEV_API_KEY']}"}) body = res.json() ``` ## Response The taxonomy ```json { "data": { "code": "207Q00000X", "grouping": "(NUCC grouping)", "classification": "(NUCC classification)", "specialization": null, "display_name": "(NUCC display name)", "definition": null, "notes": null, "section": "Individual", "status": "active", "effective_start": "2026-07-01", "effective_end": null, "replaced_by": [] }, "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS). Reference data, not medical advice." }, "links": { "self": "/v1/taxonomies/207Q00000X", "next": null } } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `code` | string | yes | | | `grouping` | string | yes | | | `classification` | string | yes | | | `specialization` | string \| null | yes | | | `display_name` | string | yes | | | `definition` | string \| null | yes | | | `notes` | string \| null | yes | | | `section` | "individual" \| "non-individual" | yes | | | `status` | "active" \| "retired" \| "replaced" | yes | | | `effective_start` | string (date) | yes | | | `effective_end` | string \| null (date) | yes | | | `replaced_by` | string[] | no | | ## Errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)). Branch on `type`, not on `title`. See [Errors](/errors). | Status | `type` | When | | --- | --- | --- | | 400 | `invalid-request` | A parameter or the body failed validation; `errors` lists each field. | | 401 | `unauthorized` | Missing, malformed or revoked API key. | | 404 | `not-found` | No record with that id (retired records are still returned). | | 429 | `rate-limited / quota-exceeded` | Too many requests per second (retry after `Retry-After`), or the monthly quota is used up. | | 503 | `dataset-unavailable / unavailable` | The dataset has no published version yet, or the service is degraded. | --- # Search provider taxonomies URL: https://docs.healthcare.dev/reference/taxonomies/search-provider-taxonomies ```http GET https://api.healthcare.dev/v1/taxonomies ``` Fuzzy search over taxonomy names, classifications and specializations. Requires an API key: `Authorization: Bearer hdev_live_...`. See [Authentication](/authentication). > **Not public yet.** NUCC taxonomy descriptions need a commercial license, so these endpoints return `503 dataset-unavailable` until it is signed. Provider records will still carry taxonomy codes. ## Query parameters | Name | Type | Required | Description | Example | | --- | --- | --- | --- | --- | | `q` | string | yes | Search text (fuzzy) | `diabetes` | | `limit` | integer | no | Page size (max 100) | `25` | | `cursor` | string | no | Opaque cursor from `links.next` | | | `view` | "compact" \| "full" | no | `compact` returns only the fields an agent usually needs (fewer tokens); `full` (default) returns every field | `compact` | | `fields` | string | no | Comma-separated record fields to return, e.g. `code,display,billable` | `code,display,billable` | ## Examples **curl** ```sh curl "https://api.healthcare.dev/v1/taxonomies?q=diabetes&limit=25" \ -H "Authorization: Bearer $HDEV_API_KEY" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/v1/taxonomies?q=diabetes&limit=25", { headers: { Authorization: `Bearer ${process.env.HDEV_API_KEY}` }, }); const { data, meta } = await res.json(); ``` **Python** ```python import os import requests res = requests.get("https://api.healthcare.dev/v1/taxonomies?q=diabetes&limit=25", headers={"Authorization": f"Bearer {os.environ['HDEV_API_KEY']}"}) body = res.json() ``` ## Response Matches ```json { "data": [ { "code": "string", "grouping": "string", "classification": "string", "specialization": "string", "display_name": "string", "definition": "string", "notes": "string", "section": "individual", "status": "active", "effective_start": "2026-10-01", "effective_end": "2026-10-01", "replaced_by": [ "string" ], "match_score": 0 } ], "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS). Reference data, not medical advice." }, "links": { "self": "/v1/taxonomies?q=diabetes&limit=25", "next": "/v1/taxonomies?q=diabetes&limit=25&cursor=eyJrIjoiRTExLjkifQ" } } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `code` | string | yes | | | `grouping` | string | yes | | | `classification` | string | yes | | | `specialization` | string \| null | yes | | | `display_name` | string | yes | | | `definition` | string \| null | yes | | | `notes` | string \| null | yes | | | `section` | "individual" \| "non-individual" | yes | | | `status` | "active" \| "retired" \| "replaced" | yes | | | `effective_start` | string (date) | yes | | | `effective_end` | string \| null (date) | yes | | | `replaced_by` | string[] | no | | | `match_score` | number | yes | How well this result matches the query: 1 exact code or id, 0.9 code prefix, 0.5 to 0.9 every query word in the text (higher is closer), under 0.5 a fuzzy (typo-tolerant) match. Below 0.5, check the result before relying on it. | ## Errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)). Branch on `type`, not on `title`. See [Errors](/errors). | Status | `type` | When | | --- | --- | --- | | 400 | `invalid-request` | A parameter or the body failed validation; `errors` lists each field. | | 401 | `unauthorized` | Missing, malformed or revoked API key. | | 404 | `not-found` | No record with that id (retired records are still returned). | | 429 | `rate-limited / quota-exceeded` | Too many requests per second (retry after `Retry-After`), or the monthly quota is used up. | | 503 | `dataset-unavailable / unavailable` | The dataset has no published version yet, or the service is degraded. | --- # Process liveness URL: https://docs.healthcare.dev/reference/service/process-liveness ```http GET https://api.healthcare.dev/healthz ``` Returns 200 while the process is up. Does not check dependencies. Public: no API key needed. ## Examples **curl** ```sh curl "https://api.healthcare.dev/healthz" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/healthz"); const { data, meta } = await res.json(); ``` **Python** ```python import requests res = requests.get("https://api.healthcare.dev/healthz") body = res.json() ``` ## Response Process is alive ```json { "status": "ok", "version": "string" } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `status` | "ok" | yes | | | `version` | string | yes | | --- # Dependency readiness URL: https://docs.healthcare.dev/reference/service/dependency-readiness ```http GET https://api.healthcare.dev/readyz ``` Returns 200 when the database and cache are reachable, 503 otherwise. Public: no API key needed. ## Examples **curl** ```sh curl "https://api.healthcare.dev/readyz" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/readyz"); const { data, meta } = await res.json(); ``` **Python** ```python import requests res = requests.get("https://api.healthcare.dev/readyz") body = res.json() ``` ## Response Ready ```json { "status": "ok", "checks": {} } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `status` | "ok" \| "degraded" | yes | | | `checks` | object | yes | | ## Errors Errors are `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)). Branch on `type`, not on `title`. See [Errors](/errors). | Status | `type` | When | | --- | --- | --- | | 503 | `dataset-unavailable / unavailable` | The dataset has no published version yet, or the service is degraded. | --- # Service and data freshness status URL: https://docs.healthcare.dev/reference/service/service-and-data-freshness-status ```http GET https://api.healthcare.dev/v1/status ``` Public, no authentication. `degraded` when any dataset is older than 1.5x its expected cadence. Public: no API key needed. ## Examples **curl** ```sh curl "https://api.healthcare.dev/v1/status" ``` **TypeScript** ```ts const res = await fetch("https://api.healthcare.dev/v1/status"); const { data, meta } = await res.json(); ``` **Python** ```python import requests res = requests.get("https://api.healthcare.dev/v1/status") body = res.json() ``` ## Response Status ```json { "data": { "status": "ok", "datasets": [ { "id": "string", "version": "string", "published_at": "string", "fresh": true } ] }, "meta": { "source": "cms-icd10", "data_version": "2026.1", "retrieved_at": "2026-10-24T12:00:00Z", "license": "Public domain (CMS). Reference data, not medical advice." }, "links": { "self": "/v1/status", "next": null } } ``` ### Fields | Field | Type | Always present | Description | | --- | --- | --- | --- | | `status` | "ok" \| "degraded" | yes | | | `datasets` | object[] | yes | | --- # Changelog URL: https://docs.healthcare.dev/changelog Dataset releases (new ICD-10, HCPCS, NDC and RxNorm versions) are listed per record in [`/v1/changes`](/reference/datasets/change-feed) and on [healthcare.dev/changelog](https://healthcare.dev/changelog). ## 2026-10-24 **Added** - Docs site with quickstart, concepts, dataset pages, MCP setup guides, example agents and a generated API reference. Every page has a Markdown copy (`.md`), plus `llms.txt` and `llms-full.txt`. - MCP server (`@healthcare.dev/mcp`): 9 read-only tools, remote at `mcp.healthcare.dev/mcp` and local over stdio. - TypeScript SDK (`@healthcare.dev/sdk`) and CLI (`@healthcare.dev/cli`, `hdev`). - API v1: codes (ICD-10-CM, ICD-10-PCS, HCPCS) with search, hierarchy, batch and `as_of`; drugs (NDC, RxNorm, unified search); datasets, change feed and status. - API keys, per-plan rate limits with `RateLimit-*` headers, and monthly quotas. --- # Status and data freshness URL: https://docs.healthcare.dev/status A dataset is **fresh** while its latest release is younger than 1.5 times its usual release cadence. The same data is at [`/v1/status`](/reference/service/service-and-data-freshness-status) (no key needed). Live uptime and incidents: [healthcare.dev/status](https://healthcare.dev/status).