Integration · OpenSharing

The provider directory archive, on Databricks

CMS publishes the National Provider Directory as a bulk export and serves only the current one. When a new release lands, the previous one stops existing. This is every release we have caught, kept as Delta tables partitioned by release, so comparing two versions is a WHERE clause rather than a re-download and a re-parse.

It is free. The underlying federal files are US government works and carry no copyright, and the extraction code is Apache-2.0.

Reference architecture

One ingest, two paths. The audit runs on BigQuery and publishes to the web. The archive runs on Databricks and publishes to consumers. They share the ingest and nothing else, which is why the MCP server keeps answering when the warehouse is asleep.

CMS NDH bulk exportdirectory.cms.gov · manifest.json · 8 NDJSON filesanalysis/fast_ingest_ndh.pyzstd NDJSON, flattened to typed columnsTHE AUDITBigQuery cms_npd32.5M FHIR resources, current releaseanalysis/h*.py54 registered hypotheses, 40 published/api/v1 static JSONfindings, states, crosswalk CSVsainpi.dev · MCP serverVercel. No Databricks anywhere on this path.DATABRICKS ACCOUNT · AWS us-west-2Parquet exportone file per resource per releaseUnity Catalog volumeanalysis/databricks_publish.py --uploadDelta tables workspace.ainpi6 tables, PARTITIONED BY release_dateShare ainpi-ndh-archiveDatabricks MarketplaceGet instant access, into their own catalogdelta-sharing (Python)No Databricks account neededEvery box is a real file or a real object.The two paths share an ingest and nothing else.

What is in it

Six tables, one per FHIR resource type, each partitioned by release_date. The current CMS release is 2026-08-20.

TableWhat it holds
practitionerIndividual providers, id is Practitioner-<NPI>
practitioner_rolePractitioner to organization, with specialty
organizationGroups, facilities and tax records
organization_affiliationOrganization to organization edges
locationSites, with coordinates for 98% of rows
endpointFHIR REST and Direct Trust addresses

Each row keeps the full FHIR resource as JSON alongside flattened columns for the fields worth querying directly, so a question the flattening did not anticipate is still answerable from the same row.

Get it

Two ways in, and the second needs no Databricks account at all.

From Databricks Marketplace

Find CMS National Provider Directory: Release Archive, take Get instant access, and the tables mount into a catalog in your own workspace. Then query them like any other table.

SELECT release_date, count(*) AS practitioners
FROM ainpi_release_archive.ainpi.practitioner
GROUP BY release_date
ORDER BY release_date;

Without a Databricks account

The share is open Delta Sharing, so any client that speaks the protocol can read it from a credential file. Request one at gene@fhiriq.com.

pip install delta-sharing

import delta_sharing
url = "ainpi.share#ainpi-ndh-archive.ainpi.practitioner"
df = delta_sharing.load_as_pandas(url, limit=1000)

Filter on release_date before anything else. Partition pruning is a hint to the client, not a guarantee from the server, so a query without it can pull every release when you wanted one.

Read this before you write a diff

CMS regenerates Endpoint and Location resource ids on every export. Join two releases on id and you get 100% churn every time, which is an artifact of id minting rather than anything that happened in the world.

  • Practitioner ids are stable, at 100% across releases, because the id is derived from the NPI. Stable ids do not mean unchanged records: of 20,000 practitioners present in two releases, zero were byte-identical.
  • Endpoint rejoins on address at 100.0%. Use that, not the id.
  • Location has no reliable cross-release key. The best composite matches 73.5% after normalising case and punctuation. Any Location diff has to state its match rate.

The table comments carry these warnings too, so they travel with the data rather than living only here. Full method in the methodology.

Roadmap

Current quarter
Archive live with two releases over OpenSharing. MCP server submitted for Marketplace validation. Account allow-listed as a public provider on 2026-08-31, so the archive listing moves from private to public.
Next quarter
Ingest the next CMS release into the archive within two weeks of publication. Rotate the sharing recipient token before it expires on 2026-11-21. A Cloudflare R2 migration is written and tested, held until a bill actually shows sharing egress.
Known limitation
The Location cross-release key above. It is a property of what CMS publishes rather than a bug we can fix, so it is documented rather than scheduled.

Where the numbers come from

  • Findings — every published measurement, each with its compute script.
  • Methodology — how a hypothesis gets registered before the number exists.
  • Data sources — every dataset used, considered or rejected, with licence terms.
  • Developer — the stable /api/v1 contract and the MCP tools, which are the left-hand path in the diagram.

This is a research project. Verify any number against the primary source before it informs a decision, and tell us when one is wrong: gene@fhiriq.com.