Provider Credentialing Workflow
Automate healthcare provider credentialing and ongoing monitoring using DEA registration lookup, OIG LEIE exclusion screening, SAM.gov checks, and FDA drug verification — all via the ComplianceGrid API.
Regulatory Context
Healthcare organizations participating in federal programs (Medicare, Medicaid, TRICARE) are required to screen providers against the OIG LEIE and SAM.gov exclusion lists. Failure to do so can result in Civil Monetary Penalties (CMPs) of up to $100,000 per occurrence, plus treble damages.
OIG Mandate
42 CFR 1001 — must screen all employees, contractors, and providers monthly.
CMS Requirements
State Medicaid agencies must check both OIG LEIE and SAM.gov.
DEA Compliance
21 CFR 1301 — verify DEA registration before allowing controlled substance handling.
Workflow Steps
Step 1: DEA Number Validation
Check that the provider's DEA number is well formed (format and checksum). The DEA registrant database is not public and no registry is connected, so schedules and active status must be confirmed with the DEA or the state board.
Step 2: OIG LEIE Exclusion Check
Check the provider against the OIG List of Excluded Individuals and Entities (LEIE). An NPI check is exact; a name search returns leads that you confirm with date of birth, address or NPI. Excluded providers cannot participate in federal healthcare programs.
Step 3: SAM.gov Exclusion Check
Check the provider or organization against the SAM.gov public exclusions list (about 169,000 active exclusions). UEI, CAGE and NPI matches are exact; name matches need confirming.
Step 4: FDA Drug & NDC Verification
Look up drug products in the openFDA NDC directory (brand, generic, labeler, schedule of marketing) and check openFDA drug shortage and recall records.
Step 5: OFAC Sanctions Screening
Screen providers and associated entities against OFAC SDN and other federal watchlists.
Step 1: DEA Number Validation
const API = "https://api.compliancegrid.ai";
const headers = { "x-api-key": process.env.CG_API_KEY! };
const get = (path: string) => fetch(API + path, { headers }).then((r) => r.json());
// Check a DEA number's format and checksum
const dea = await get("/v1/pharma/dea/validate/AB1234563");
console.log("Valid DEA number:", dea.valid); // true; AB1234564 returns false with a reason
// A valid checksum does NOT prove the registration exists or is active. The DEA registrant database
// is not public and no registry is connected: /v1/pharma/dea/lookup always answers found: false.
// Confirm schedules and status with the DEA (or the state board) before relying on a registration.
if (!dea.valid) {
console.error("Not a valid DEA number: " + dea.reason);
}Step 2: OIG LEIE Exclusion Screening
// 1. An NPI check is exact. It returns 400 INVALID_NPI for a mistyped number (bad check digit).
const npi = "1234567893";
const byNpi = await get("/v1/legal/oig/check/" + npi);
console.log("Excluded by NPI:", byNpi.excluded); // true or false
if (byNpi.excluded) console.error("EXCLUDED:", byNpi.exclusion.exclusionType, byNpi.exclusion.exclusionDate);
// 2. A name search returns LEADS. It matches names that contain the text ("Smith" also finds "Smither"),
// so confirm a lead with date of birth, address or NPI before acting on it.
const leads = await get("/v1/legal/oig/search?lastName=Smith&firstName=John&state=CA&limit=10");
console.log(leads.totalResults + " name matches to review");
for (const m of leads.results) {
console.log(" " + m.lastName + ", " + m.firstName + " " + m.middleName + " | DOB " + m.dob + " | " + m.city + ", " + m.state);
console.log(" Exclusion type " + m.exclusionType + " on " + m.exclusionDate + " | NPI " + m.npi + " | " + m.specialty);
}Step 3: SAM.gov Exclusion Check
// Check the SAM.gov public exclusions list. Pass the exact identifiers you have.
const ex = await get("/v1/legal/exclusions/check?name=" + encodeURIComponent("Smith Medical Group LLC") + "&npi=" + npi);
console.log(ex.totalMatches + " matches");
for (const m of ex.matches) {
// matchType is UEI, CAGE or NPI (exact) or NAME (weaker: confirm before acting)
console.log(m.matchType, m.entityName, m.reason, "by", m.agency, "since", m.activeDate);
}
const exactHit = ex.matches.some((m: any) => m.matchType !== "NAME");
// Registration details for an entity are in the SAM search (also: uei, cage, state)
const sam = await get("/v1/business/sam/search?q=" + encodeURIComponent("Smith Medical Group") + "&limit=3");
for (const e of sam.results) console.log(e.legalBusinessName, e.ueiSAM, e.registrationStatus, "exclusion:", e.exclusionStatus);Step 4: FDA Drug & NDC Verification
// Search the FDA NDC directory (q matches brand, generic and labeler names)
const drugs = await get("/v1/pharma/fda/drug/search?q=Lipitor&limit=3");
const d0 = drugs.results[0];
console.log("Drug:", d0.brandName, "| Generic:", d0.genericName);
console.log("NDC:", d0.productNdc, "| Labeler:", d0.labelerName);
console.log("Form:", d0.dosageForm, "| Marketing category:", d0.marketingCategory);
// Drug shortage records (openFDA) by generic name
const shortage = await get("/v1/pharma/fda/shortages?q=" + encodeURIComponent(d0.genericName));
console.log(shortage.totalResults + " shortage records for " + d0.genericName);
// Recall records by drug name (classification is optional, for example Class I)
const recalls = await get("/v1/pharma/fda/recalls?drug=" + encodeURIComponent(d0.genericName) + "&limit=3");
console.log(recalls.totalResults + " recalls");Complete Credentialing Function
interface CredentialingResult {
provider: string;
timestamp: string;
deaNumberValid: boolean | null; // checksum only: not proof of an active registration
oigExcludedByNpi: boolean | null; // exact; null when no NPI was given
oigNameLeads: number; // name matches to confirm by hand
samExactMatch: boolean;
sanctionsPotentialMatch: boolean;
overallStatus: "APPROVED" | "REVIEW_REQUIRED" | "DENIED";
reasons: string[];
}
async function credentialProvider(
firstName: string,
lastName: string,
deaNumber?: string,
npi?: string,
orgName?: string
): Promise<CredentialingResult> {
const result: CredentialingResult = {
provider: firstName + " " + lastName,
timestamp: new Date().toISOString(),
deaNumberValid: null,
oigExcludedByNpi: null,
oigNameLeads: 0,
samExactMatch: false,
sanctionsPotentialMatch: false,
overallStatus: "APPROVED",
reasons: [],
};
const review = (reason: string) => {
result.reasons.push(reason);
if (result.overallStatus === "APPROVED") result.overallStatus = "REVIEW_REQUIRED";
};
// Run all checks in parallel; a failed call must not read as a clean result
const [dea, oigNpi, oigName, ex, screening] = await Promise.all([
deaNumber ? get("/v1/pharma/dea/validate/" + deaNumber).catch(() => null) : null,
npi ? get("/v1/legal/oig/check/" + npi).catch(() => null) : null,
get("/v1/legal/oig/search?lastName=" + encodeURIComponent(lastName) + "&firstName=" + encodeURIComponent(firstName) + "&limit=25").catch(() => null),
get("/v1/legal/exclusions/check?name=" + encodeURIComponent(orgName ?? firstName + " " + lastName) + (npi ? "&npi=" + npi : "")).catch(() => null),
fetch(API + "/v1/compliance/restricted-party-screening", {
method: "POST",
headers: { ...headers, "Content-Type": "application/json" },
body: JSON.stringify({ parties: [{ name: firstName + " " + lastName, country: "US", type: "INDIVIDUAL" }] }),
}).then((r) => r.json()).catch(() => null),
]);
if (deaNumber) {
if (!dea) review("DEA validation unavailable");
else { result.deaNumberValid = dea.valid; if (!dea.valid) review("DEA number is not valid"); }
}
if (npi) {
if (!oigNpi?.success) review("OIG NPI check unavailable or NPI invalid");
else { result.oigExcludedByNpi = oigNpi.excluded; if (oigNpi.excluded) { result.overallStatus = "DENIED"; result.reasons.push("Excluded by NPI (OIG LEIE)"); } }
}
if (!oigName?.success) review("OIG name search unavailable");
else if (oigName.totalResults > 0) { result.oigNameLeads = oigName.totalResults; review(oigName.totalResults + " OIG name matches to confirm by date of birth or address"); }
if (!ex?.success) review("SAM.gov exclusions check unavailable");
else if (ex.matches.some((m: any) => m.matchType !== "NAME")) { result.samExactMatch = true; result.overallStatus = "DENIED"; result.reasons.push("Exact SAM.gov exclusion match"); }
else if (ex.totalMatches > 0) review("SAM.gov name match to confirm");
if (screening?.data?.overallResult === "POTENTIAL_MATCH") { result.sanctionsPotentialMatch = true; review("Possible restricted-party list match"); }
else if (!screening?.data) review("Restricted-party screening unavailable");
return result;
}
// Usage
const cred = await credentialProvider("John", "Smith", "AB1234563", "1234567893", "Smith Medical Group");
console.log("Status: " + cred.overallStatus);
if (cred.reasons.length > 0) console.log("Reasons:", cred.reasons.join("; "));Ongoing Monitoring Schedule
| Check | Frequency | Requirement |
|---|---|---|
| OIG LEIE | Monthly | OIG guidance — monthly screening of all individuals |
| SAM.gov Exclusions | Monthly | CMS State Medicaid requirement |
| OFAC SDN | Monthly or on transaction | OFAC compliance for all entities |
| DEA Registration | Before credential renewal | 21 CFR 1301: confirm active status with the DEA (this API validates the number only) |
| State License | Before credential renewal | State-specific requirements |
ATF FFL lookup workflow
SEC + FDIC + FINRA workflows