# Check Medicare coverage for a code and diagnosis

URL: https://docs.healthcare.dev/recipes/medicare-coverage

|                  |                                                                                                                                                                                                                        |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Plan             | **Pro**, or a preview on Free and Builder (below). `as_of`, the answer on a past date, is **Team**                                                                                                                     |
| Datasets         | [Medicare coverage support](/datasets/medicare-coverage) (CMS Medicare Coverage Database), [ICD-10-CM](/datasets/icd10cm) (every plan)                                                                                 |
| Calls per answer | 1, plus 1 if you check the diagnosis code first                                                                                                                                                                        |
| Limits           | Each account can look up a limited number of different code and diagnosis pairs a day (5,000 on Pro, 20,000 on Team; previews have [their own](/rate-limits#daily-lookup-limits-on-derived-data)); repeats don't count |

<Callout title="Try it before you upgrade">
  Free and Builder keys can call it as a preview: 50 preview calls a month on Free, 200 on Builder,
  per feature. A preview answer is the real answer, with `meta.preview` (calls `remaining` this
  month and the plan that `unlocks` it) and `links.upgrade`. Preview calls count toward your
  included calls. Once they're used up, the `403` `plan-upgrade-required` adds `upgrade_url` and a
  sample answer for a fixed demo subject. See [Plans](/plans#previews).
</Callout>

## 1. Check the diagnosis code (any plan)

Send the full billable ICD-10-CM code. A category such as `B35` matches only where a document
lists the category itself, so check first that the code is billable:

```sh
curl https://api.healthcare.dev/v1/codes/icd10cm/B35.1 \
  -H "Authorization: Bearer $HDEV_API_KEY" | jq '.data | {code, display, billable, status}'
```

## 2. Ask for coverage support

```sh
curl "https://api.healthcare.dev/v1/coverage/medicare?code=11720&dx=B35.1&state=TX&view=compact" \
  -H "Authorization: Bearer $HDEV_API_KEY"
```

```json
{
  "data": {
    "code": "11720",
    "dx": "B35.1",
    "state": "TX",
    "disclaimer": "Reference data, not a coverage determination.",
    "coverage": {
      "answer": "supported",
      "confidence": 1,
      "derivation": "source_stated",
      "evidence": [
        {
          "url": "https://www.cms.gov/medicare-coverage-database/view/article.aspx?articleid=56640&ver=16",
          "anchor": "h3Icd10SupportHeader"
        }
      ],
      "as_of": "2026-10-19T06:55:00.000Z"
    },
    "basis": "documents_agree"
  }
}
```

Leave out `view=compact` (the default is `full`) to get `results`: one entry per LCD or billing
article that lists the code, each with its own answer, `basis` and document.

**TypeScript**

```ts
import { HealthcareDev, PlanUpgradeRequiredError } from "@healthcare.dev/sdk";

const hdev = new HealthcareDev();

try {
  const { data } = await hdev.coverage.medicare({ code: "11720", dx: "B35.1", state: "TX" });
  const { answer, derivation, confidence, evidence } = data.coverage;
  console.log(answer, derivation, confidence, evidence[0]?.url);
  for (const r of data.results ?? []) console.log(r.document.id, r.coverage.answer, r.basis);
  console.log(data.disclaimer); // show it with the answer
} catch (err) {
  if (err instanceof PlanUpgradeRequiredError) console.log(`Needs the ${err.requiredPlan} plan`);
  else throw err;
}
```

**Python**

```python
from healthcare_dev import HealthcareDev

hdev = HealthcareDev()

cov = hdev.coverage.medicare(code="11720", dx="B35.1", state="TX")["data"]
c = cov["coverage"]
print(c["answer"], c["derivation"], c["confidence"], [e["url"] for e in c["evidence"]])
for r in cov.get("results", []):
    print(r["document"]["id"], r["coverage"]["answer"], r["basis"])
print(cov["disclaimer"])
```

## Ask an agent

> Does Medicare support HCPCS/CPT code 11720 for diagnosis B35.1 in Texas? Tell me the answer,
> how it was reached (derivation and confidence), and link the CMS document section to read.
> Remind me this isn't a coverage determination.

The agent uses `check_medicare_coverage` (and `lookup_code` for the diagnosis).

## Read the answer

`coverage.answer` is one of three:

- **`supported`**: a document lists the diagnosis among the codes that support medical necessity
  for this code.
- **`not_supported`**: a document lists it among the codes that don't, or says unlisted
  diagnoses don't support the code and this one isn't listed.
- **`unclear`**: the documents don't settle it (narrative criteria only, extra conditions, lists
  not tied to this code), or they disagree. No document listing the code at all is also
  `unclear`, with empty `results`: there is no local policy for it.

Every answer says how it was reached:

- **`derivation`**: `source_stated` means the CMS document states it in its published code
  lists and we only read the list (every `supported` and `not_supported`). `derived` means we
  concluded it from what the document says, without the document stating it outright (every
  `unclear`). `reviewed` means a person checked it.
- **`confidence`**: from 0 to 1. `1` when the document states the answer, `0` for `unclear`.
  Don't act on an answer below your own threshold without reading the evidence.
- **`evidence`**: the document's page in the Medicare Coverage Database and the section
  (`anchor`) to read. We serve facts and links, never the policy text.
- **`as_of`**: when CMS published the export the answer was read from.

## What it is not

**Reference data, not a coverage determination.** A listed diagnosis doesn't guarantee payment:
the service must still be reasonable and necessary, meet the LCD's criteria, and be supported by
the medical record. It is not prior authorization, a Medicare Advantage plan's criteria (see
[MA internal criteria](/recipes/ma-internal-criteria)) or a payment amount. CPT codes are served
as numbers only, never with their descriptions.

Next: get pushed when a coverage document changes, in [Keep your data fresh](/recipes/keep-data-fresh).
