# LEIE Exclusion Evidence API (OIG + NPI + SAM) (`civicdataforge/leie-exclusion-screening`) Actor

Source-linked OIG LEIE screening with valid-NPI exact matches, state-bound name review candidates, optional NPPES/SAM checks, and evidence hashes. No eligibility decisions.

- **URL**: https://apify.com/civicdataforge/leie-exclusion-screening.md
- **Developed by:** [Bryan](https://apify.com/civicdataforge) (community)
- **Categories:** Automation, MCP servers, Other
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Healthcare Exclusion Screening Evidence — LEIE + NPI + optional SAM.gov

Screen provider and entity records against the official HHS-OIG List of Excluded Individuals/Entities
(LEIE), correlate valid returned NPIs with the official CMS NPPES registry, and
optionally check active SAM.gov exclusions using the caller's own API key.

This Actor is designed to produce **reviewable evidence**, not a black-box eligibility verdict.
Every screening row records which sources were checked, which were skipped or failed, when the
source was fetched, the LEIE source-file hash, deterministic identity signals, limitations, and a
SHA-256 evidence fingerprint.

HHS-OIG says healthcare entities should routinely check the LEIE to reduce civil-monetary-penalty
risk. The Actor supports that workflow; it is not legal advice and does not replace identity
verification, licensure checks, or a compliance professional's review.

### Screening decisions

| `screening_decision` | Meaning |
|---|---|
| `confirmed_identifier_match` | A checked exclusion source matched the caller's exact NPI. Confirm identity and review the source record before acting. |
| `potential_match_review_required` | A normalized name matched, or SAM.gov returned a name candidate, without an exact NPI confirmation. Do not treat this as identity proof. |
| `no_match_on_sources_checked` | No match was found on every source that the result says was successfully checked at that time. This is not a universal “clear.” |
| `incomplete_source_check` | A requested source failed, was unavailable, or was skipped because a configured query limit was reached. |

The old `matched`, `match_type`, and `matches` fields remain for compatibility. New integrations
should make decisions from `screening_decision`, `sources`, and `source_errors`.

### Screen a batch

```json
{
  "mode": "screen",
  "screenList": [
    { "name": "ACME HOME HEALTH", "npi": "1234567893", "state": "NC", "ref": "vendor-118" },
    { "name": "JANE DOE", "state": "TX", "ref": "provider-4471" }
  ],
  "enrichNpi": true,
  "maxNpiLookups": 10,
  "includeSam": false
}
```

Exact NPI checks are strongest. Name-only LEIE matches use normalized exact-name comparison and are
always labeled for review; the Actor does not pretend an opaque fuzzy score is an identity decision.
Supplied NPIs must be ten digits and pass the standard NPI check-digit test. Invalid NPIs, empty identity
objects, and malformed state codes are rejected instead of being laundered into a misleading no-match.

### Add SAM.gov active exclusions

SAM.gov's official Exclusions API v4 requires an API key and has role-dependent rate limits. Supply
your own key in the secret `samApiKey` input and opt in explicitly:

```json
{
  "mode": "screen",
  "screenList": [{ "name": "ACME HOME HEALTH", "npi": "1234567893" }],
  "includeSam": true,
  "samApiKey": "YOUR_KEY",
  "maxSamQueries": 10
}
```

The key is sent only to the official `api.sam.gov` endpoint and is never returned in dataset rows or
status messages. Rows beyond `maxSamQueries` are marked incomplete instead of silently omitting SAM.

### Filter the LEIE source

```json
{
  "mode": "filter",
  "state": "TX",
  "specialty": "PHARMACY",
  "maxRecords": 100
}
```

Filter rows include `source_url`, `source_fetched_at`, `source_sha256`, and a stable
`record_fingerprint` so scheduled runs can be compared without guessing whether a row changed.

### Monitoring pattern

Save a bounded screening input as an Apify Task, schedule it at the cadence your compliance program
requires, and deliver each run through an Apify integration or webhook. Compare `evidence_hash` for a
query reference across runs. Do not persist customer screening lists in a developer-owned shared store;
the caller controls their Task input, run retention, and downstream system.

### Portable review cases and signed webhooks

Set `caseWorkflow` to `true` in screen mode to write a `CASE-BUNDLE` alongside the ordinary
dataset. Each case binds a hashed caller reference to the screening evidence hash, an evidence
class, a disposition state, and a hash-chained transition history. The case file deliberately does
not retain the submitted name, NPI, or raw caller reference. Keep the bundle in your own system and
return the applicable `priorCases` on the next run; CivicDataForge does not use a shared developer-
owned customer-population store.

Human actions use optimistic locking. A `caseActions` item must supply the current `case_id`,
`expected_case_receipt`, `expected_version`, `to_status`, `actor_ref`, `reason`, and ISO `at`
timestamp. Stale, forged, invalid, or unaudited transitions fail closed. When the evidence hash
changes, a resolved disposition is reopened automatically with a source-monitor transition.

Optional `webhookUrl` and secret `webhookSecret` inputs send the exact bundle to a public HTTPS
endpoint. Every retry preserves one event ID and one HMAC-SHA256 signature. Private/internal targets,
redirects, embedded credentials, non-HTTPS URLs, and nonstandard ports are rejected. `WEBHOOK-DELIVERY`
records accepted/rejected attempts without storing the signing secret or raw transport errors.

This is a review workflow, not a legal eligibility engine. `resolved_clear` means a named reviewer
resolved the case for the customer-defined purpose and reason recorded in its audit chain; it never
changes the narrower meaning of `no_match_on_sources_checked`.

### Official sources and limits

- HHS-OIG LEIE download: `https://oig.hhs.gov/exclusions/downloadables/UPDATED.csv`
- CMS NPPES API 2.1: `https://npiregistry.cms.hhs.gov/api-page`
- GSA SAM.gov Exclusions API v4: `https://open.gsa.gov/api/exclusions-api/`

NPPES returns registry identity data but does not establish licensure or good standing. SAM.gov v4
returns active exclusions through the documented API. Source availability, publication cadence, and
API rate limits remain controlled by the respective agencies.

# Actor input Schema

## `mode` (type: `string`):

screen checks people/entities and returns evidence records; filter pulls source LEIE records with provenance.

## `screenList` (type: `array`):

For screen mode. Each item: { "name": "JOHN SMITH" or "ACME HOME HEALTH", "npi": "1234567893" (optional valid test NPI), "state": "NC" (optional), "ref": "your-id" (optional) }. Name-only matches are normalized exact-name candidates, constrained by state when supplied, and require human review.

## `enrichNpi` (type: `boolean`):

Look up matched LEIE NPIs or a caller-supplied NPI in the official CMS registry and return explainable correlation signals. NPI status is not licensure or eligibility.

## `maxNpiLookups` (type: `integer`):

Caps NPPES calls per run. Remaining rows still receive LEIE results and show that enrichment was skipped.

## `includeSam` (type: `boolean`):

Opt in to the official GSA SAM.gov Exclusions API. Requires your own public SAM.gov API key.

## `samApiKey` (type: `string`):

Caller-supplied SAM.gov public API key. Required only when includeSam is enabled; never returned in output.

## `maxSamQueries` (type: `integer`):

Caps SAM.gov calls per run to respect the official API's role-dependent rate limits.

## `caseWorkflow` (type: `boolean`):

Screen mode only. Writes a CASE-BUNDLE record whose evidence references, dispositions, and hash-chained transitions can be verified outside CivicDataForge. Raw subject keys are hashed in the case file.

## `priorCases` (type: `array`):

Optional prior CASE-BUNDLE cases for continuity. Receipts are verified; changed evidence reopens a resolved case. Keep this state in your own system and send back only the cases in the current batch.

## `caseActions` (type: `array`):

Optional optimistic-lock transitions. Each action requires case\_id, expected\_case\_receipt, expected\_version, to\_status, actor\_ref, reason, and at. Stale or forged writes fail closed.

## `webhookUrl` (type: `string`):

Optional public HTTPS endpoint. Delivery uses a stable event ID, an HMAC signature, up to three attempts, and a redacted WEBHOOK-DELIVERY receipt.

## `webhookSecret` (type: `string`):

At least 16 characters. Used only to sign the exact webhook body and never written to output.

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

Two-letter state code, for example TX.

## `specialty` (type: `string`):

Substring match on specialty, such as NURSING, PHARMACY, or HOME HEALTH.

## `exclusionType` (type: `string`):

OIG exclusion authority code, such as 1128a1 or 1128b5.

## `maxRecords` (type: `integer`):

Caps LEIE records returned in filter mode.

## Actor input object example

```json
{
  "mode": "filter",
  "screenList": [],
  "enrichNpi": true,
  "maxNpiLookups": 10,
  "includeSam": false,
  "maxSamQueries": 10,
  "caseWorkflow": false,
  "priorCases": [],
  "caseActions": [],
  "state": "FL",
  "maxRecords": 50
}
```

# Actor output Schema

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

API URL for the default dataset items produced by this run.

## `caseBundle` (type: `string`):

Customer-owned, hash-bound cases and disposition audit trails when caseWorkflow is enabled.

## `webhookDelivery` (type: `string`):

Redacted downstream delivery attempts when a case webhook is configured.

# 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 = {
    "mode": "filter",
    "state": "FL",
    "maxRecords": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("civicdataforge/leie-exclusion-screening").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 = {
    "mode": "filter",
    "state": "FL",
    "maxRecords": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("civicdataforge/leie-exclusion-screening").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 '{
  "mode": "filter",
  "state": "FL",
  "maxRecords": 50
}' |
apify call civicdataforge/leie-exclusion-screening --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,civicdataforge/leie-exclusion-screening"
        }
    }
}

```

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/tjDCKBrcuGaVcf62A/builds/yI0sldWRiOKWngxny/openapi.json
