healthcare.dev docs

Joined answers

Everything about an NDC or an NPI in one call: RxNorm, J-codes, NADAC, label, shortage and recall flags for a drug; taxonomy, location, Medicare enrollment, opt-out and OIG exclusions for a provider.

Two routes answer "what do we know about this?" in one request: GET /v1/drugs/ndc/{ndc}/full for a drug and GET /v1/providers/{npi}/full for a provider. Both are part of the Pro and Team plans (403 plan-upgrade-required on Free and Builder) and count as one lookup, however many datasets they join. The MCP tools are get_drug_full and get_provider_full; the SDK methods are hdev.drugs.full() and hdev.providers.full().

Drugs

Pass a product NDC (0006-3026), a package NDC in any 10-digit layout (0006-3026-02) or an 11-digit NDC (00006302602). The datasets are looked up together:

ComponentWhat it holdsDataset
productThe FDA product with its packagesNDC Directory
rxnormRxNorm concepts linked to the product's (or the package's) NDC-11sRxNorm
aspJ-codes the current NDC-HCPCS crosswalk assigns, each with the payment limit in effect today and the newest quarterMedicare Part B ASP
nadacThe current NADAC rate of the package, or of each package of a productNADAC (CMS)
labelFDA label status: set id, version, effective date and which sections exist (not their text)FDA drug labels
shortageWhether FDA lists a current shortage, with the shortage list entriesFDA drug shortages
recallsWhether FDA has a recall of the NDC it hasn't terminated, with the open recalls and closed ones from the last recall_months months (default 12)FDA drug recalls

Package or product

With a package NDC, every source that names packages is matched at the package level: RxNorm links, crosswalk entries, NADAC rates, shortage entries (each is one presentation) and recalls (the NDCs a recall names). A shortage entry or recall that names no package matches by product, says matched_on: "product", and the component's reason notes it. product is always the whole NDC Directory product, as /v1/drugs/ndc/{ndc} returns it.

hcpcs_codes lists the J-codes the newest or current quarter's crosswalk assigns. Codes only an earlier quarter assigned are in asp.data.historical, with the last quarter that listed them.

open_recall is true for any recall of the NDC FDA hasn't terminated, however old; recall_months only limits which closed recalls are listed next to the open ones.

Nothing is left out silently

Every component is always in the response, with a status:

  • available: the dataset was consulted and data holds its answer. For the shortage and recall flags, false is an answer: the dataset was checked and lists nothing.
  • not_listed: the dataset was consulted and has nothing for this NDC. data is null and reason says what that means (for example, most retail pharmacy drugs have no J-code).
  • unavailable: the dataset isn't published yet, or its license keeps it private. data and source are null and reason says which.

missing lists every component that isn't available, with its reason, so even the compact view says why something has no answer. The flags (active_shortage, open_recall, boxed_warning) are null, never false, when the data to answer isn't available.

Provenance per component

Each component carries its own source: the dataset, data_version, as_of (the date that version takes effect), when it was published, the source URL, hashes and license terms. The top-level meta combines every dataset consulted, the NDC Directory first, with each one's provenance in meta.sources (see Responses).

Views

view=compact returns the flags and key ids only: ndc, product_ndc, ndc11, name, rxcuis, hcpcs_codes, label_set_ids, flags and missing. standard and full (the default) return every component. The MCP tool defaults to compact.

curl "https://api.healthcare.dev/v1/drugs/ndc/0006-3026-02/full?view=compact" \
  -H "Authorization: Bearer $HDEV_API_KEY"
{
  "data": {
    "ndc": "00006302602",
    "product_ndc": "0006-3026",
    "ndc11": "00006302602",
    "name": "Keytruda (pembrolizumab)",
    "rxcuis": [],
    "hcpcs_codes": ["J9271"],
    "label_set_ids": [],
    "flags": { "active_shortage": false, "open_recall": false, "boxed_warning": null },
    "missing": [
      {
        "component": "rxnorm",
        "status": "not_listed",
        "reason": "RxNorm links no concept to this package."
      },
      {
        "component": "nadac",
        "status": "not_listed",
        "reason": "CMS publishes no current NADAC rate for this package (NADAC covers drugs retail pharmacies dispense; physician-administered and new products often have none)."
      },
      {
        "component": "label",
        "status": "not_listed",
        "reason": "No current human prescription label on DailyMed lists this product (OTC, animal and withdrawn labels are not served)."
      }
    ]
  },
  "meta": {
    "source": "fda-ndc+nlm-rxnorm+cms-asp+cms-nadac+nlm-dailymed+openfda-drug-shortages+openfda-drug-enforcement",
    "data_version": "ndc@2026-10-23,rxnorm@2026-10-05,medicare-asp@2026-10-r20261008,...",
    "sources": ["..."]
  }
}

The example is illustrative and shortened. A payment limit is not a coverage decision or a patient price, NADAC is an average pharmacy acquisition cost, and no recall or shortage listed means FDA lists none, not that a product is safe. Reference data, not clinical or billing advice.

Providers

GET /v1/providers/{npi}/full takes a 10-digit NPI and looks up:

ComponentWhat it holdsDataset
providerWho the NPI is: name, individual or organization, active or deactivated, enumeration and deactivation datesNPI
taxonomyEvery taxonomy listed for the NPI, the primary one, and NUCC's names when that code set is servedNPI
locationThe practice location addressNPI
enrollmentenrolled and the Medicare fee-for-service enrollments that list the NPIMedicare enrollment
opt_outopted_out today and the affidavit in effect, else the latest listed (in_effect says which)Medicare opt-out
exclusionexclusion_recorded, matched_by: "npi_as_listed" and the exclusion records, in effect or reinstatedOIG exclusions

The checks answer exactly as /v1/providers/{npi}/enrollment, /opt-out and /exclusions do, with the same note. Provider data comes from the CMS NPI Registry until the NPPES file is published (the provider source says which). An NPI the provider source has no record of is a 404 with a hint.

Not listed is not "no"

A check whose current file doesn't list the NPI (no records, or only ones a later release dropped) is not_listed, and its reason is the check's own note. Above all for exclusions: exclusions are matched by NPI as listed in the OIG file, and most OIG records carry no NPI, so exclusion_recorded: false means no exclusion recorded with this NPI, never that the provider is not excluded. Search by name too (/v1/exclusions?q=) and confirm identity with OIG's online search. exclusion_note carries that rule in words, in every view; show it with the answer.

A dataset that isn't published, or whose license keeps it private, is unavailable: its flag is null, never false. flags are medicare_enrolled, opted_out and exclusion_recorded; missing lists every component that isn't available, with its reason.

Views and provenance

view=compact returns npi, name, entity_type, status, primary_taxonomy, practice_location, flags, exclusion_note and missing. Each component has its own source with data_version and as_of, and meta combines the provider source, NUCC (when it named taxonomies) and each check dataset consulted.

curl "https://api.healthcare.dev/v1/providers/1003926940/full?view=compact" \
  -H "Authorization: Bearer $HDEV_API_KEY"
{
  "data": {
    "npi": "1003926940",
    "name": "ROY S SHELBURNE, DDS",
    "entity_type": "individual",
    "status": "active",
    "primary_taxonomy": { "code": "1223G0001X", "name": null },
    "practice_location": { "city": "BRISTOL", "state": "VA", "postal_code": "242024317" },
    "flags": { "medicare_enrolled": false, "opted_out": true, "exclusion_recorded": true },
    "exclusion_note": "Matched by NPI as listed in the OIG file (LEIE). Most LEIE records carry no NPI, so an empty answer means no exclusion recorded with this NPI, not that the provider is not excluded: ...",
    "missing": [
      {
        "component": "enrollment",
        "status": "not_listed",
        "reason": "Matched by NPI (the enrollment's NPI or one of its additional NPIs) in CMS's Medicare Fee-For-Service Public Provider Enrollment file, release 2026-10-01. Not listed means that file has no enrollment with this NPI, not a determination of eligibility."
      }
    ]
  },
  "meta": {
    "data_version": "nppes@2026-10,medicare-enrollment@2026-10-01,medicare-opt-out@2026-08-01,oig-exclusions@2026-10-09",
    "sources": ["..."]
  }
}

The example is illustrative and shortened. Reference data, not a credentialing decision: confirm an exclusion's identity with OIG before acting on it.

On this page