# ⚕️ Doctor Directory Lead Finder (`nexgendata/doctor-directory-lead-finder`) Actor

NPI Registry-grounded US doctor leads + optional Healthgrades/Vitals enrichment. Specialty + state filter across all 50 states. HIPAA-safe public data only. Built for medical-device sales, pharma reps, EHR/PMS SaaS, telehealth recruiting.

- **URL**: https://apify.com/nexgendata/doctor-directory-lead-finder.md
- **Developed by:** [Stephan Corbeil](https://apify.com/nexgendata) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $30.00 / 1,000 provider record returneds

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## ⚕️ Doctor Directory Lead Finder — NPI + Healthgrades

**Pull qualified US healthcare-provider leads — name, NPI, specialty, practice address, phone, and (where available) email — by specialty and state. Built for medical-device sales, pharma reps, EHR/PMS SaaS prospecting, healthcare-marketing agencies, and telehealth recruiting teams who refuse to pay $30K/year for Definitive Healthcare.**

NPI Registry is the federal canonical spine (100% US coverage, zero cost, public-record data). We layer optional Healthgrades-style enrichment for accepting-new-patients status, ratings, and contact details — honestly disclosed at a ~30–35% email find rate.

---

### HIPAA-Safety Statement — read this first

This actor touches **zero patient data**. It exclusively uses:

1. **NPI Registry** — federal public registry published by CMS (Centers for Medicare & Medicaid Services) under the Health Insurance Portability and Accountability Act (HIPAA) Administrative Simplification rules. Every U.S. healthcare provider who bills any insurer is listed here. The data is explicitly designated as **public** and downloadable in bulk from cms.hhs.gov. We hit the public JSON API.
2. **Healthgrades / Vitals / Doctoralia** (optional, only when `enrichContact=true`) — consumer-facing provider directories. We read only the same fields a patient searching for a doctor would see in a browser: practice name, address, phone, rating, "accepting new patients" badge.

**We never collect, request, store, or transmit Protected Health Information (PHI).** No diagnoses, no treatments, no patient encounters, no insurance records, no anything that would trigger a HIPAA covered-entity obligation. Buyers in regulated industries can use this output for top-of-funnel B2B prospecting without HIPAA exposure, the same way they would use a LinkedIn export of physician profiles.

---

### Use cases

- **Medical device sales** — build a list of orthopedic surgeons in California for a knee-implant launch.
- **Pharma rep targeting** — segment endocrinologists by state for a new GLP-1 detail.
- **EHR / PMS SaaS prospecting** — pull every solo-proprietor family-medicine practice in Texas (sole-proprietor flag is in NPI itself).
- **Telehealth recruiting** — find psychiatrists in 5 states for a multi-state telehealth panel.
- **Healthcare-marketing agencies** — build segmented email lists by specialty + city for cold outreach campaigns.
- **M&A diligence** — count cardiology practices in a target MSA before underwriting a roll-up.
- **Clinical-research outreach** — recruit principal investigators by therapy area + region.

---

### How it works

````

┌─────────────────────────────┐
│  YOU: specialty + state     │
└─────────────┬───────────────┘
│
v
┌─────────────────────────────────────┐
│  Step 1 — NPI Registry API          │   ← 100% US, zero cost, public
│  taxonomy\_description + state filter│
│  Returns: name, NPI, address, taxonomy
└─────────────┬───────────────────────┘
│   provider-returned event ($0.03)
v
┌─────────────────────────────────────┐
│  Step 2 — Optional enrichment       │   ← only when enrichContact=true
│  Healthgrades search (Playwright)   │
│  Reads: rating, accepting status,   │
│         occasional contact email    │
└─────────────┬───────────────────────┘
│   contact-enriched ($0.05)
│   email-found      ($0.10)  ← only if found
v
┌─────────────────────────────────────┐
│  Dataset: one row per provider      │
└─────────────────────────────────────┘

````

**Honest find rates** — we have no incentive to overpromise. Across recent test runs:

| Field                     | Find rate                                          |
| ------------------------- | -------------------------------------------------- |
| Name / NPI / address      | 100% (NPI is canonical)                            |
| Practice phone            | ~95% (in NPI; ~98% with directory enrichment)     |
| Specialty / sub-specialty | 100% (NUCC taxonomy)                               |
| Accepting new patients    | ~60% (when directory match exists)                 |
| Provider rating           | ~55% (Healthgrades-dependent)                      |
| Email                     | **~30–35%** (practice site contact-page scrapes)   |

If a directory blocks the request, the actor still returns the provider's NPI record — it never crashes on enrichment failure. You pay for `provider-returned` either way; `contact-enriched` only fires when enrichment actually produced data.

---

### Supported specialties (50+)

Specialty input is case-insensitive and mapped to NUCC Health Care Provider Taxonomy codes (24.0). Unmapped strings fall through to NPI Registry's free-text taxonomy filter.

**Physicians (allopathic + osteopathic):** Anesthesiology, Cardiology, Cardiovascular Disease, Dermatology, Diagnostic Radiology, Emergency Medicine, Endocrinology, Family Medicine, Gastroenterology, General Surgery, Geriatrics, Hematology, Hospitalist, Infectious Disease, Internal Medicine, Interventional Radiology, Medical Oncology, Nephrology, Neurology, Neurosurgery, Ob-Gyn, Oncology, Ophthalmology, Orthopedic Surgery, Otolaryngology (ENT), Pain Medicine, Pathology, Pediatrics, Physical Medicine, Plastic Surgery, Psychiatry, Pulmonology, Radiology, Rheumatology, Sleep Medicine, Thoracic Surgery, Urology, Vascular Surgery.

**Dentistry:** Dentistry, Orthodontics, Endodontics, Periodontics, Oral Surgery.

**Mental / behavioural health:** Psychology, Clinical Social Work.

**Mid-level providers:** Nurse Practitioner, Physician Assistant, Midwife.

**Other:** Chiropractic, Optometry, Podiatry, Pharmacy.

For specialties or sub-specialties not in this list, type the NUCC classification name verbatim (e.g. `"Pediatric Cardiology"`) and the actor will pass it through to the NPI Registry taxonomy filter.

---

### Output schema (one object per provider)

| Field                     | Type    | Example                                  |
| ------------------------- | ------- | ---------------------------------------- |
| `npi`                     | string  | `"1234567890"` (10-digit federal ID)     |
| `enumerationType`         | string  | `"NPI-1"` (individual) or `"NPI-2"` (org)|
| `firstName`               | string  | `"Sarah"`                                |
| `lastName`                | string  | `"Chen"`                                 |
| `middleName`              | string? | `"J"`                                    |
| `credentials`             | string? | `"MD"`, `"DO"`, `"DDS"`, `"NP"`, `"PA-C"` |
| `organizationName`        | string? | only on NPI-2 records                    |
| `gender`                  | string? | `"M"`, `"F"`                             |
| `specialty`               | string  | `"Cardiovascular Disease"`               |
| `primaryTaxonomyCode`     | string  | `"207RC0000X"`                           |
| `licenseNumber`           | string? | `"A123456"`                              |
| `licenseState`            | string? | `"CA"`                                   |
| `subSpecialties`          | string[]| `["Interventional Cardiology"]`          |
| `soleProprietor`          | bool    | `true` = solo practice (different sales motion) |
| `practiceAddress`         | object  | `{street, city, state, zip, phone, fax}` |
| `mailingAddress`          | object  | same shape                               |
| `enumerationDate`         | string  | `"2008-04-12"` — proxy for years in practice |
| `lastUpdated`             | string  | `"2024-11-03"`                           |
| `status`                  | string  | `"A"` = active                           |
| `npiRegistryUrl`          | string  | direct link to public NPI profile        |
| `practiceWebsite`         | string? | enrichment only                          |
| `practicePhone`           | string  | preferred over NPI's listed phone        |
| `email`                   | string? | ~30–35% find rate (enrichment only)      |
| `acceptingNewPatients`    | bool?   | from directory                           |
| `rating`                  | number? | 0–5 from Healthgrades                    |
| `yearsOfExperience`       | int?    | from directory bio                       |
| `enrichmentSource`        | string? | `"healthgrades"` when enrichment hit     |
| `source`                  | string  | `"npiregistry.cms.hhs.gov"`              |

---

### JSON examples

**Cardiologists in California, 50 providers, no enrichment:**

```json
{
  "specialty": "cardiology",
  "state": "CA",
  "maxProviders": 50,
  "enrichContact": false
}
````

**Pediatricians in Austin, TX accepting new patients, with enrichment:**

```json
{
  "specialty": "pediatrics",
  "state": "TX",
  "city": "Austin",
  "maxProviders": 100,
  "enrichContact": true,
  "acceptingNewPatients": true
}
```

**Dental group practices (organizations) in Florida:**

```json
{
  "specialty": "dentistry",
  "state": "FL",
  "npiType": "Organization",
  "maxProviders": 200,
  "enrichContact": false
}
```

***

### Run it from Python (Apify SDK)

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("nexgendata/doctor-directory-lead-finder").call(run_input={
    "specialty": "orthopedic surgery",
    "state": "NY",
    "maxProviders": 250,
    "enrichContact": True,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["npi"], item["firstName"], item["lastName"], item.get("email"))
```

### Run it from cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/nexgendata~doctor-directory-lead-finder/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"specialty":"dermatology","state":"IL","maxProviders":25,"enrichContact":true}'
```

***

### FAQ

**1. How fresh is NPI Registry data?**
CMS updates the public NPI Registry weekly. `lastUpdated` on each record shows the most recent provider self-attestation. NPI numbers themselves never change once issued.

**2. Why are you honest about a 30–35% email find rate?**
Because the alternative is lying. Most directory sources don't publish a clean email — we extract from practice contact pages when discoverable. Vendors who promise "95% email coverage" are either selling stale appended data or guessing patterns like `firstname.lastname@gmail.com` — both of which will get your domain blocklisted within a week.

**3. Is this HIPAA-compliant?**
The actor returns only publicly-listed provider information — no PHI ever touches it. NPI Registry is a federal public record. Healthgrades shows what any patient searching for a doctor would see. Using this output for B2B prospecting is the same regulatory category as buying a LinkedIn list — fully fine.

**4. Can I bulk-query an entire state?**
Yes. `maxProviders` caps at 1000 per run. For multi-state or full-specialty pulls, run the actor multiple times — the NPI Registry rate limit is generous (we throttle to ~4 req/sec to be a good citizen).

**5. Do you cover NPs, PAs, DOs, dentists?**
Yes — anyone with an NPI. NPs, PAs, midwives, psychologists, chiropractors, optometrists, podiatrists, pharmacists are all supported.

**6. What about international providers?**
US only — NPI Registry is by definition a U.S. federal system. For Canada, UK, Australia, Germany providers, use country-specific medical-council registries (Linear request: tell us which countries you need and we'll spin up sister actors).

**7. What's the refund policy when directory enrichment blocks?**
We charge `contact-enriched` ($0.05) only when enrichment actually produced data. If Healthgrades returns nothing for a provider, you pay only the base $0.03 `provider-returned` fee. No charge fired for nothing returned.

**8. How does this compare to buying a list from ZoomInfo / Definitive Healthcare?**
See the comparison table below. Short answer: 1/100th the cost, equivalent NPI-level accuracy, honestly lower email coverage. For 80% of medtech / pharma / SaaS use cases, that trade-off is worth it.

**9. Can I filter to providers who opened a new practice recently?**
Yes — sort the dataset by `enumerationDate` descending. Providers with recent NPI enumeration dates are likely newer practitioners or have just changed practice settings, both strong buying signals.

***

### How we stack up

| Feature                          | This actor          | Doximity         | Definitive Healthcare | IQVIA Onekey      | NPI Registry direct | Healthgrades  |
| -------------------------------- | ------------------- | ---------------- | --------------------- | ----------------- | ------------------- | ------------- |
| Cost                             | $0.03–$0.18/provider| $300+/mo seat    | $30K+/yr enterprise   | enterprise license| free                | consumer site |
| US coverage                      | 100% (all NPI)      | ~80% physicians  | 100%                  | 100%              | 100%                | partial       |
| NUCC specialty taxonomy          | yes                 | yes              | yes                   | yes               | yes                 | no            |
| Email enrichment                 | ~30–35% honest      | ~70% (paid)      | 60–80%                | 80%+              | none                | none          |
| Bulk export                      | yes (any size)      | per-seat limits  | yes                   | yes               | bulk file only      | no            |
| HIPAA-safe scope                 | yes — public only   | yes              | yes                   | yes               | yes                 | yes           |
| API access                       | yes                 | limited          | yes                   | yes               | yes (no enrichment) | no            |
| Update frequency                 | weekly (NPI)        | quarterly        | quarterly             | monthly           | weekly              | rolling       |
| Time to first lead               | 5 seconds           | sales cycle      | sales cycle           | sales cycle       | DIY weeks           | manual        |

***

### Sister actors (NexGenData fleet)

Build full B2B lead-gen workflows:

- **[nexgendata/b2b-leads-finder](https://apify.com/nexgendata/b2b-leads-finder)** — multi-source B2B prospecting beyond healthcare.
- **[nexgendata/company-data-aggregator](https://apify.com/nexgendata/company-data-aggregator)** — enrich practice records with firmographics (employees, revenue, NAICS).
- **[nexgendata/lead-list-enricher](https://apify.com/nexgendata/lead-list-enricher)** — append phone, email, LinkedIn to an existing CSV.
- **[nexgendata/email-validator](https://apify.com/nexgendata/email-validator)** — SMTP-validate enriched emails before sending to keep your sender reputation clean.
- **[nexgendata/court-records-search](https://apify.com/nexgendata/court-records-search)** — cross-reference providers against federal/state court records for medical-malpractice diligence.

***

### Don't have an Apify account?

[Sign up free](https://www.apify.com/sign-up?fpr=2ayu9b) — $5 free credits, no card required. That's enough to pull ~150 enriched providers and validate the data quality before you commit to a paid plan.

***

*Built by NexGenData. Questions, custom specialties, or international coverage requests: open an issue on the actor's GitHub or reach scrapers@thenextgennexus.com.*

# Actor input Schema

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

Medical specialty (e.g. 'cardiology', 'dermatology', 'pediatrics', 'orthopedic surgery', 'psychiatry', 'dentistry', 'ob-gyn'). 50+ canonical specialties are mapped to NUCC taxonomy codes; unmapped strings are passed through to NPI Registry's free-text taxonomy filter.

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

US state code (e.g. 'CA', 'NY', 'TX'). NPI Registry filters on the provider's primary practice address state.

## `city` (type: `string`):

Refine results to a specific city. Case-insensitive; matches the practice-location city in NPI.

## `maxProviders` (type: `integer`):

Maximum number of provider records to return (1–1000). Each provider is one dataset row. NPI Registry paginates 200 per page.

## `enrichContact` (type: `boolean`):

When true, attempt directory enrichment (Healthgrades/Vitals) to add practice phone, accepting-new-patients status, rating, and occasionally an email. Honest find rate: ~30–35% for email. Adds latency (~8s per provider budget) and incurs the contact-enriched event charge.

## `npiType` (type: `string`):

Individual = NPI-1 (most lead-gen use cases). Organization = NPI-2 (clinics, hospitals, group practices).

## `acceptingNewPatients` (type: `boolean`):

Filter to providers explicitly marked as accepting new patients by Healthgrades. Requires enrichContact=true. Leave unset to skip the filter.

## `proxyConfiguration` (type: `object`):

Apify proxy configuration used for directory enrichment. Default: residential proxies (recommended to reduce blocking).

## Actor input object example

```json
{
  "specialty": "cardiology",
  "state": "CA",
  "maxProviders": 50,
  "enrichContact": true,
  "npiType": "Individual",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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 = {
    "specialty": "cardiology",
    "state": "CA",
    "city": "",
    "maxProviders": 50,
    "enrichContact": true,
    "npiType": "Individual",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nexgendata/doctor-directory-lead-finder").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 = {
    "specialty": "cardiology",
    "state": "CA",
    "city": "",
    "maxProviders": 50,
    "enrichContact": True,
    "npiType": "Individual",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("nexgendata/doctor-directory-lead-finder").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "specialty": "cardiology",
  "state": "CA",
  "city": "",
  "maxProviders": 50,
  "enrichContact": true,
  "npiType": "Individual",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call nexgendata/doctor-directory-lead-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=nexgendata/doctor-directory-lead-finder",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "⚕️ Doctor Directory Lead Finder",
        "description": "NPI Registry-grounded US doctor leads + optional Healthgrades/Vitals enrichment. Specialty + state filter across all 50 states. HIPAA-safe public data only. Built for medical-device sales, pharma reps, EHR/PMS SaaS, telehealth recruiting.",
        "version": "0.0",
        "x-build-id": "ZA3b71SX7LOoqitYF"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/nexgendata~doctor-directory-lead-finder/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-nexgendata-doctor-directory-lead-finder",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/nexgendata~doctor-directory-lead-finder/runs": {
            "post": {
                "operationId": "runs-sync-nexgendata-doctor-directory-lead-finder",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/nexgendata~doctor-directory-lead-finder/run-sync": {
            "post": {
                "operationId": "run-sync-nexgendata-doctor-directory-lead-finder",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "specialty",
                    "state"
                ],
                "properties": {
                    "specialty": {
                        "title": "Specialty",
                        "type": "string",
                        "description": "Medical specialty (e.g. 'cardiology', 'dermatology', 'pediatrics', 'orthopedic surgery', 'psychiatry', 'dentistry', 'ob-gyn'). 50+ canonical specialties are mapped to NUCC taxonomy codes; unmapped strings are passed through to NPI Registry's free-text taxonomy filter."
                    },
                    "state": {
                        "title": "US State (2-letter code)",
                        "pattern": "^[A-Za-z]{2}$",
                        "type": "string",
                        "description": "US state code (e.g. 'CA', 'NY', 'TX'). NPI Registry filters on the provider's primary practice address state."
                    },
                    "city": {
                        "title": "City (optional)",
                        "type": "string",
                        "description": "Refine results to a specific city. Case-insensitive; matches the practice-location city in NPI."
                    },
                    "maxProviders": {
                        "title": "Max providers",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Maximum number of provider records to return (1–1000). Each provider is one dataset row. NPI Registry paginates 200 per page.",
                        "default": 50
                    },
                    "enrichContact": {
                        "title": "Enrich contact info",
                        "type": "boolean",
                        "description": "When true, attempt directory enrichment (Healthgrades/Vitals) to add practice phone, accepting-new-patients status, rating, and occasionally an email. Honest find rate: ~30–35% for email. Adds latency (~8s per provider budget) and incurs the contact-enriched event charge.",
                        "default": true
                    },
                    "npiType": {
                        "title": "NPI type",
                        "enum": [
                            "Individual",
                            "Organization"
                        ],
                        "type": "string",
                        "description": "Individual = NPI-1 (most lead-gen use cases). Organization = NPI-2 (clinics, hospitals, group practices).",
                        "default": "Individual"
                    },
                    "acceptingNewPatients": {
                        "title": "Accepting new patients (optional filter)",
                        "type": "boolean",
                        "description": "Filter to providers explicitly marked as accepting new patients by Healthgrades. Requires enrichContact=true. Leave unset to skip the filter."
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Apify proxy configuration used for directory enrichment. Default: residential proxies (recommended to reduce blocking).",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ]
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
