How to Verify Healthcare Provider NPI Numbers in Your Application
Every healthcare provider in the United States has a National Provider Identifier -- a unique 10-digit number issued by CMS through the National Plan and Provider Enumeration System (NPPES). If you are building a credentialing platform, an insurance verification system, a provider directory, or a telehealth application, you need to verify NPI numbers against the live registry. An invalid or mismatched NPI can delay claims, trigger audits, and in the worst case indicate fraud.
This article covers why NPI verification matters, the three main use cases, and how to integrate it into your application.
Why NPI verification matters
Credentialing
When a healthcare organization onboards a new provider, they must verify the provider's NPI, confirm their specialty taxonomy, and check their practice address. Manual verification through the NPPES website is slow and error-prone. Automating NPI lookups during the credentialing workflow reduces onboarding time from days to minutes.
Insurance and claims
Every claim submitted to a payer includes the rendering provider's NPI. If the NPI does not match the provider's name and taxonomy in the NPPES registry, the claim gets rejected. Pre-validating NPI data before claim submission catches these mismatches early.
Fraud prevention
Fraudulent providers use fabricated or stolen NPI numbers. Verifying that an NPI is active, belongs to the claimed individual, and has the expected specialty is a basic fraud control. Some states now require NPI verification as part of Medicaid enrollment.
Looking up an NPI by number
The simplest use case: you have a 10-digit NPI and need to verify it is real and get the provider's details.
curl "https://npi-lookup.up.railway.app/lookup?number=1629067153"
Response:
{
"npi": "1629067153",
"type": "individual",
"firstName": "John",
"lastName": "Smith",
"credential": "M.D.",
"gender": "Male",
"status": "Active",
"addresses": [
{
"type": "practice",
"line1": "123 Medical Center Dr",
"city": "Dallas",
"state": "TX",
"zip": "752301234",
"phone": "2145551234"
}
],
"taxonomies": [
{
"code": "207R00000X",
"description": "Internal Medicine",
"primary": true,
"state": "TX",
"license": "MD12345"
}
]
}
This gives you everything you need: the provider's name, credential, practice address, specialty, and license number -- all from the live NPPES registry.
Searching for providers
When you need to find providers by name, specialty, or location rather than by NPI number:
curl "https://npi-lookup.up.railway.app/search?last_name=Smith&state=TX&taxonomy_description=Cardiology&limit=5"
This queries the live CMS NPPES API and returns formatted results. Useful for provider directory searches, referral lookups, and network adequacy reporting.
Integrating NPI verification into your credentialing flow
Here is a JavaScript implementation for verifying a provider during onboarding:
const verifyProvider = async (npiNumber, expectedName, expectedTaxonomy) => {
const res = await fetch(
`https://npi-lookup.up.railway.app/lookup?number=${npiNumber}`
);
const provider = await res.json();
if (provider.error) {
return { verified: false, reason: 'NPI not found in NPPES registry' };
}
// Check name match
const nameMatch =
provider.lastName?.toLowerCase() === expectedName.lastName.toLowerCase() &&
provider.firstName?.toLowerCase() === expectedName.firstName.toLowerCase();
if (!nameMatch) {
return {
verified: false,
reason: `Name mismatch: NPI belongs to ${provider.firstName} ${provider.lastName}`,
};
}
// Check specialty
const taxonomyMatch = provider.taxonomies?.some(
(t) => t.description.toLowerCase().includes(expectedTaxonomy.toLowerCase())
);
if (!taxonomyMatch) {
return {
verified: false,
reason: `Specialty mismatch: provider taxonomies are ${provider.taxonomies.map((t) => t.description).join(', ')}`,
};
}
return {
verified: true,
provider: {
npi: provider.npi,
name: `${provider.firstName} ${provider.lastName}, ${provider.credential}`,
specialty: provider.taxonomies.find((t) => t.primary)?.description,
address: provider.addresses.find((a) => a.type === 'practice'),
license: provider.taxonomies.find((t) => t.primary)?.license,
},
};
};
// During credentialing
const result = await verifyProvider(
'1629067153',
{ firstName: 'John', lastName: 'Smith' },
'Internal Medicine'
);
if (!result.verified) {
console.log(`Verification failed: ${result.reason}`);
await flagForManualReview(applicationId, result.reason);
} else {
console.log(`Verified: ${result.provider.name}`);
await approveCredentials(applicationId, result.provider);
}
Pre-claim NPI validation
Before submitting a batch of claims, verify all rendering provider NPIs:
const validateClaimNPIs = async (claims) => {
const results = await Promise.all(
claims.map(async (claim) => {
const res = await fetch(
`https://npi-lookup.up.railway.app/lookup?number=${claim.renderingProviderNPI}`
);
const provider = await res.json();
return {
claimId: claim.id,
npi: claim.renderingProviderNPI,
valid: !provider.error,
providerName: provider.error
? null
: `${provider.firstName} ${provider.lastName}`,
};
})
);
const invalid = results.filter((r) => !r.valid);
if (invalid.length > 0) {
console.log(`${invalid.length} claims have invalid NPIs:`);
invalid.forEach((r) => console.log(` Claim ${r.claimId}: NPI ${r.npi}`));
}
return results;
};
Using the MCP server for ad-hoc lookups
The healthcare MCP server includes NPI lookup alongside ICD-10, NDC, and DEA tools. Install for Claude Desktop:
{
"mcpServers": {
"healthcare": {
"command": "npx",
"args": ["-y", "@easysolutions906/mcp-healthcare"]
}
}
}
Ask Claude: "Look up NPI 1629067153 and tell me the provider's specialty and practice address." This is useful for credentialing staff who need quick lookups without navigating the NPPES website.
Compared to the NPPES API directly
You can query https://npiregistry.cms.hhs.gov/api/ directly. The NPI Lookup API wraps it with a cleaner response format, consistent error handling, and formatted address and taxonomy structures. If you are already calling NPPES directly and are happy with the raw response format, you may not need this. But if you want a cleaner interface that normalizes the messy NPPES response into a predictable structure, this saves you from writing that parsing layer yourself.
Getting started
- Look up by NPI:
GET /lookup?number=1629067153 - Search by name:
GET /search?last_name=Smith&state=TX - Search by specialty:
GET /search?taxonomy_description=Cardiology&state=CA - MCP server:
npx @easysolutions906/mcp-healthcare
No API key required. The API queries the live NPPES registry in real-time.
Top comments (0)