# NPI Provider Registry - US Doctors and Organisations (`alaudinburki/npi-provider-registry`) Actor

Search the official US National Provider Identifier registry as flat rows - name, credential, specialty, address and status. Free public CMS API.

- **URL**: https://apify.com/alaudinburki/npi-provider-registry.md
- **Developed by:** [alaudin burki](https://apify.com/alaudinburki) (community)
- **Categories:** Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 92.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## NPI Provider Registry — US Doctors and Organisations

Searches the US National Provider Identifier registry — the CMS directory of every provider issued an
NPI — and returns one flat row per provider: name, credential, gender, status, address and specialty.
The CMS API is public, so no key is needed. The NPI itself is carried on every row inside the `id`
field, prefixed with `npi:`.

### How to use

1. Give at least one filter: a two-letter `state`, a `taxonomy` (specialty), a `lastName`, an
   `organizationName`, or an `enumerationType` of `NPI-1` (individual) or `NPI-2` (organisation).
2. Set `maxItems` (default 500) and `maxPages` (default 5). Each request returns up to 200 records.
3. Run the Actor. Rows land in the default dataset, and `SUMMARY` reports the row count, the stop
   reason and whether the result was truncated.

### Inputs

| Field | What it does | Default |
|---|---|---|
| `state` | Two-letter US state, sent as `state`, e.g. `NY`. | none |
| `taxonomy` | Specialty text, sent as `taxonomy_description`, e.g. `Cardiovascular Disease`. | none |
| `lastName` | Individual provider's family name, sent as `last_name`. | none |
| `organizationName` | Organisation name, sent as `organization_name`. | none |
| `enumerationType` | `NPI-1` for individuals or `NPI-2` for organisations, sent as `enumeration_type`. | none |
| `maxItems` | Hard row cap. The runner also refuses to go above 20,000. | 500 |
| `maxPages` | Hard request cap, 200 records per request. The runner also refuses to go above 200. | 5 |

```json
{
  "state": "NY",
  "taxonomy": "Cardiovascular Disease",
  "maxItems": 50
}
```

### Output

One row per provider record.

| Field | Meaning |
|---|---|
| `enumerationType` | `NPI-1` for an individual, `NPI-2` for an organisation. |
| `firstName` | Given name (`basic.first_name`). Empty for organisations. |
| `lastName` | Family name (`basic.last_name`). Empty for organisations. |
| `organizationName` | Organisation name (`basic.organization_name`). Empty for individuals. |
| `credential` | Credential suffix as recorded, e.g. `MD`, `DO`, `NP`. |
| `gender` | Gender code as recorded (`M` or `F`), not translated. |
| `status` | The register's status code (`basic.status`); `A` means active. |
| `lastUpdated` | The date the register last changed the record (`basic.last_updated`). |
| `address1` | First line of the first address (`addresses[0].address_1`). |
| `city` | City of that address. |
| `state` | State of that address. |
| `postalCode` | Postal code of that address, as published. |
| `taxonomy` | Description of the first specialty (`taxonomies[0].desc`). |
| `taxonomyCode` | Code of that first specialty (`taxonomies[0].code`), from the NUCC code set. |

Every row also carries `id` (`npi:` followed by the 10-digit NPI), `source` (`npi-registry`) and
`scrapedAt` (an ISO timestamp for the run); the first is the identifier, the last two are added by the
runner. Absent values are dropped from the row, so an organisation simply has no `firstName` key.

### Limitations

- **At least one search criterion is required.** With every filter blank the CMS API rejects the
  query, and the run stops with an error instead of returning rows.
- **There is no `number` column.** The NPI is the row identifier: it appears as `id`, prefixed with
  `npi:`, e.g. `npi:1234567890`.
- **Only the first address is mapped.** The register labels addresses as practice location or mailing
  address, and this Actor takes whichever one is listed first, so it may be a mailing address.
- **Only the first taxonomy is mapped.** A provider with several specialties returns one, and it is
  not guaranteed to be the one the register marks as primary.
- **The registry is a directory, not a licence check.** An active NPI means the provider is enrolled
  for identification; it is not evidence of a current state licence or of competence.
- **Names are as recorded** — often in capitals, with no normalisation of punctuation or spacing.
- **Paging is 200 records per request.** With the default `maxPages` of 5, a run stops at about 1,000
  rows even when the query matches more, so raise the cap for broad searches.
- **No financial, ownership or affiliation data is returned.** The dataset is the NPI record only.

### Why this is different

This Actor is different because it queries the official CMS NPI registry directly — no search page is
rendered and no key is issued or rotated. Each row is identified by the NPI itself, a number that is
never reused, so output can be joined across runs and with other provider data. Absent values are
omitted rather than blanked, the output is sorted deterministically, and every run writes a `SUMMARY`
record naming why it stopped, so a capped result is visible as capped.

### FAQ

**What exactly is an NPI?** A 10-digit identifier CMS issues to US healthcare providers. `NPI-1`
records are individuals; `NPI-2` records are organisations. Numbers are never reassigned.

**Do I need an API key?** No. The CMS registry API is public and the Actor sends no credentials.

**Can I look up one provider by NPI number?** Not through this input set. Search by last name and
state, and the NPI comes back in `id`.

**Why does a provider show only one address and one specialty?** Because only the first entry of each
list is mapped; the register can hold several.

**Does an active status mean the doctor is licensed?** No. Status `A` means the record is active in
the NPI registry, which is an enrolment directory, not a licensing board.

### Pricing and limits

The price is shown on the Actor's Apify pricing panel; billing is per event under Apify's
pay-per-event model. Each run is bounded by `maxItems` (default 500, hard-capped at 20,000) and
`maxPages` (default 5, hard-capped at 200), with up to 200 records per request. When a limit stops the
run before the query is exhausted, `SUMMARY.truncated` is `true` and `SUMMARY.stopReason` names the
limit.

# Actor input Schema

## `state` (type: `string`):

Two-letter US state, e.g. NY, CA, TX.

## `taxonomy` (type: `string`):

Specialty description, e.g. Cardiology, Dermatology, Nurse Practitioner.

## `lastName` (type: `string`):

Individual provider's last name. At least one search field is required; this one defaults to "Smith".

## `organizationName` (type: `string`):

Organisation legal name.

## `enumerationType` (type: `string`):

NPI-1 for individuals, NPI-2 for organisations.

## `maxItems` (type: `integer`):

Stop after this many rows.

## `maxPages` (type: `integer`):

Stop after this many pages.

## Actor input object example

```json
{
  "lastName": "Smith",
  "maxItems": 500,
  "maxPages": 5
}
```

# Actor output Schema

## `results` (type: `string`):

One row per item, with the 14 fields listed under Views.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "lastName": "Smith",
    "maxItems": 500,
    "maxPages": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("alaudinburki/npi-provider-registry").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "lastName": "Smith",
    "maxItems": 500,
    "maxPages": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("alaudinburki/npi-provider-registry").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "lastName": "Smith",
  "maxItems": 500,
  "maxPages": 5
}' |
apify call alaudinburki/npi-provider-registry --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,alaudinburki/npi-provider-registry"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/kRc1aR7JQzzbHxnhd/builds/48QdOgkU79TA1mako/openapi.json
