# NPI Lookup & Bulk Roster Validator: NPPES Active Check + Score (`willed_nursery/npi-roster-validator`) Actor

Bulk-validate a provider roster against the CMS NPPES NPI Registry. Each NPI gets a check-digit test, found/active status, name, state, taxonomy and ZIP mismatch flags, and a 0–100 hygiene score with reason codes. Bad check digits are flagged free.

- **URL**: https://apify.com/willed_nursery/npi-roster-validator.md
- **Developed by:** [Joel Sumner](https://apify.com/willed_nursery) (community)
- **Categories:** AI, Other
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 npi validateds

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 Lookup & Bulk Roster Validator — NPPES Active Check, Field Diff, 0–100 Score

**Bulk NPI lookup and NPPES roster validation for payer, provider and credentialing-ops data teams.** Instead of scraping the NPI Registry, check *your* roster: offline check digit, found/active status, name/state/taxonomy/ZIP mismatch flags and a 0–100 data-hygiene score per NPI.

### Search scraper vs roster validator

| | NPI Registry scrapers/search Actors | This Actor |
|---|---|---|
| Input | search query (state, taxonomy, name) | your roster (NPI + expected fields) |
| Output | provider records | one audit row per roster line: match flags + score + reason codes |
| Bad NPIs | not detected | Luhn check digit offline, **free** |
| Contact data | often included | phone/fax/email always stripped |

Paste a provider roster (NPI + optional name, state, taxonomy, ZIP) and get one row back per NPI:

- **Check digit** (Luhn, prefix 80840) computed offline. Bad rows are flagged **free** with no lookup.
- **Found / active** in the NPPES NPI Registry. Deactivated NPIs are not returned by the public API, so they show `NOT_FOUND_OR_DEACTIVATED`.
- Entity type, primary taxonomy code and description, normalized practice address, enumeration and last-updated dates.
- **Match flags** for your name, state, taxonomy and ZIP.
- **Score 0–100** with reason codes: `BAD_CHECKDIGIT`, `BAD_FORMAT`, `NOT_FOUND_OR_DEACTIVATED`, `DEACTIVATED`, `NAME_MISMATCH`, `TAXONOMY_MISMATCH`, `STATE_MISMATCH`, `ZIP_MISMATCH`, `STALE_>3Y`, `NO_PRACTICE_ADDRESS`, `UNKNOWN_STATUS` (registry returned no status — never assumed active).
- A run summary in `OUTPUT`: score distribution and reason counts.

### Example input

```json
{"rows":[{"npi":"1234567893","name":"Jane Doe","state":"TX","taxonomy":"207Q00000X","zip":"75201"}]}
```

Or a plain list: `{"npis":["1003000126","1336848233"]}`.

### Output sample (real smoke row, trimmed)

```json
{"npi":"1336848233","checkDigitValid":true,"found":true,"status":"active","entityType":"organization",
 "registryName":"1 PLUS, LLC","primaryTaxonomyCode":"251C00000X","nameMatch":true,"stateMatch":false,
 "score":75,"reasonCodes":["STATE_MISMATCH","STALE_>3Y"]}
```

### All input options

`npis` (list), `rows` (JSON), `csvUrl` or `datasetId`, using the columns `npi,name,state,taxonomy,zip`. **Provider roster fields only. Never send patient data.** Any other column is dropped before processing.

### Privacy and scope

- Phone, fax and email are **always stripped** in v1. There is no contact enrichment.
- Stateless: nothing is stored between runs.
- The tool makes one lookup per NPI (`number=`), paced at about 2 requests/second with backoff.

### Source and disclaimer

Data comes from the CMS NPPES NPI Registry public API (v2.1). This Actor is independent and is not affiliated with or endorsed by CMS or HHS.
**A valid or active NPI does not mean a provider is licensed or credentialed.** This tool is not credentialing advice and is not primary-source verification (PSV). It does not check state licenses, DEA or OIG exclusions.

### Pricing (pay per event)

| Event | Price |
|---|---|
| Run start | $0.005 |
| `npi-validated` (per NPI looked up, found or not found) | $0.0015 |
| `score-report` (optional) | $0.01 |
1,000-row roster ≈ $1.51. Details:
$0.005 per run (Apify start event), plus $0.0015 per NPI looked up. **Rows that come back not found (`NOT_FOUND_OR_DEACTIVATED`) are still charged $0.0015**, because the registry lookup was made. Invalid check-digit / bad-format rows are free (checked offline, no lookup). Rows skipped after your max-charge limit or lookup errors are not charged. The optional score report is $0.01.

### Speed, timeout and limits

- The Actor is polite to the public registry: about 2 requests/second, so throughput is **about 7,000 rows per hour**. 1,000 rows ≈ 9 min; 5,000 (default `maxRows`) ≈ 45 min; **50,000 ≈ 7 hours**.
- Set the run timeout to fit `maxRows`: roughly `maxRows ÷ 7000` hours plus 10% buffer (e.g. 5,000 rows → 1 h; 50,000 → 8 h). Apify's default timeout may stop large runs early; rows already validated are kept in the dataset.
- `csvUrl` files are capped at **20 MB**; larger files fail with a clear error — split them, or pass `rows[]` / `datasetId`.

### More Actors by willed_nursery

- Healthcare credentialing pair: [NPI Roster Validator](https://apify.com/willed_nursery/npi-roster-validator) ↔ [OIG LEIE Screener](https://apify.com/willed_nursery/leie-exclusion-roster-screen) — screen the same roster for OIG exclusions next.
- KYB/lead: [Maps Lead Enricher (Domain Contact Enricher)](https://apify.com/willed_nursery/domain-contact-enricher)
- IP docket: [USPTO Trademark Deadlines](https://apify.com/willed_nursery/trademark-portfolio-deadline-scorer)
- Financial risk: [SEC Health Score](https://apify.com/willed_nursery/sec-financial-health-score)

# Actor input Schema

## `npis` (type: `array`):

List of 10-digit NPIs.

## `rows` (type: `array`):

Objects {npi, name?, state?, taxonomy?, zip?}. Provider fields only - no patient data.

## `csvUrl` (type: `string`):

CSV with header npi,name,state,taxonomy,zip

## `datasetId` (type: `string`):

Dataset with the same columns

## `maxRows` (type: `integer`):

Maximum number of roster rows to process (safety cap).

## `concurrency` (type: `integer`):

Global pace is capped at ~2 requests/s regardless.

## `includeContactFields` (type: `boolean`):

Ignored in v1: phone/fax/email are always stripped.

## `contactEmail` (type: `string`):

Contact email for User-Agent (optional).

## `scoreReport` (type: `boolean`):

Score report summary (+$0.01).

## Actor input object example

```json
{
  "npis": [
    "1003000126",
    "1234567890"
  ],
  "maxRows": 5000,
  "concurrency": 2,
  "includeContactFields": false,
  "scoreReport": false
}
```

# Actor output Schema

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

No description

# 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 = {
    "npis": [
        "1003000126",
        "1234567890"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("willed_nursery/npi-roster-validator").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 = { "npis": [
        "1003000126",
        "1234567890",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("willed_nursery/npi-roster-validator").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 '{
  "npis": [
    "1003000126",
    "1234567890"
  ]
}' |
apify call willed_nursery/npi-roster-validator --silent --output-dataset

```

## MCP server setup

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

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/wx12HMRQUU2lPZaWg/builds/US81sfJtHahnMbaRi/openapi.json
