# Nonprofit Formation Radar: New 501(c)(3) Prospect Alerts (`yungstentech/nonprofit-formation-radar`) Actor

Watch state(s), IRS subsection (default 501(c)(3)) and NTEE mission codes; each monthly run diffs the IRS EO Business Master File and delivers newly-recognized organizations as deduped prospect rows (EIN, name, mailing address, mission, ruling month). Address-only; report mode for cohorts.

- **URL**: https://apify.com/yungstentech/nonprofit-formation-radar.md
- **Developed by:** [Paul Mikulskis](https://apify.com/yungstentech) (community)
- **Categories:** Lead generation, Automation, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $9.00 / filter watch-month

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

Nonprofit Formation Radar turns the public **IRS Exempt Organizations Business Master File** into a monthly **new-501(c)(3) prospecting** feed. Name the **state(s)**, IRS **subsection** (default 501(c)(3)), and **NTEE mission** codes you care about, put the actor on a monthly Apify Schedule, and each run delivers only the organizations **newly recognized** in your territory and mission since you enrolled, as deduplicated **prospect rows** (EIN, name, mailing address, NTEE mission, ruling month, foundation type), never re-showing one you have already seen. It also produces a one-shot **new-determination cohort report** for a chosen state, period, and mission. It runs inside your own Apify account, so you get API access, scheduling, integrations, and monitoring built in, with nothing to log into and no key to manage. It is MCP-ready for AI agents.

### Address-only prospect list (read this first)

The IRS Business Master File carries each organization's **name and mailing address but NOT a phone number or email address**. So this actor delivers a mission-and-geo-targeted **prospect list, not a contact list**: it tells you which nonprofits were just recognized in your territory and mission, with a mailing address to reach them, and it earns its value on targeting quality (correct mission, correct geography, freshly recognized, never a repeat), not on already having a way to reach them. If you need a phone number or email address for an organization, you source that separately.

### What does Nonprofit Formation Radar do?

When the IRS grants an **IRS determination letter** recognizing a **new exempt organization**, a brand-new nonprofit exists that within its first months needs banking, bookkeeping and 990 preparation, directors-and-officers and general-liability insurance, a donor CRM, and grant-readiness help. The IRS publishes every recognized organization in its Business Master File and refreshes it monthly, but sends no alert: no "notify me when a new 501(c)(3) is recognized in my state working in youth services." Other 990 and nonprofit actors on the store search the *existing* universe of nonprofits; this one delivers the monthly stream of **newly-recognized** ones, which is the signal behind **nonprofit formation** monitoring.

You define a filter once and every scheduled run:

1. Streams the four IRS regional extracts (eo1.csv through eo4.csv) on your schedule.
2. Keeps only rows matching your subsection, active recognition status, state(s), and NTEE mission whose RULING (determination) month is on or after the month you enrolled.
3. Diffs them against your filter's memory on EIN and delivers one **prospect row** per **newly-recognized** organization, plus an optional webhook POST.

Two modes carry the value:

- **watch** (the recurring feed): the standing monthly filter above. The first run seeds a baseline of what is already on file (uncharged) and watches forward, so you never get a wall of back-catalog.
- **report** (one-off): every organization recognized in a chosen state, subsection, mission, and period, as a cohort you can paste into a territory review. This is the forwardable artifact and the deterministic demo.

### Why use Nonprofit Formation Radar?

- **Reach new nonprofits early.** See an organization the month the IRS publishes its recognition, so **new nonprofit leads** reach you while founders are often still choosing vendors.
- **Mission and geo targeting.** Filter by state and by **NTEE mission** (a single letter like `P` = Human Services or `E` = Health Care matches a whole major group; a longer prefix like `B82` narrows), so the list stays narrow, not a national dump.
- **Deduplicated and forward-looking.** You see each organization once, from the day you start watching, never a repeat and never old back-catalog.
- **Verifiable.** Every row carries a per-EIN ProPublica Nonprofit Explorer link so you can confirm any record against a public source.
- **Built for nonprofit-serving vendors.** Donor-CRM implementation partners, nonprofit D&O insurance brokers, nonprofit-specialized CPA and bookkeeping firms, and mission-focused banks can use it for **nonprofit prospecting**: a targeting layer for **donor CRM leads** and **nonprofit insurance leads** built on the fresh-determination signal.

### How to use Nonprofit Formation Radar

1. Open the **Input** tab. Pick your **States**, your **IRS subsection** (default 501(c)(3)), and optional **NTEE mission codes**.
2. Set a **Filter name** (for example `tx-humanservices-health`) so the deduplication memory persists across your scheduled runs.
3. Set the run's **max total charge** (see Pricing). The $9 watch fee lands on a single run, so set the per-run max total charge to at least $9 plus any expected overage. If it is too low the run fails closed: it delivers nothing, advances no memory, and writes a single uncharged `billing-blocked` row telling you to raise the cap and rerun.
4. Run it once. The first run establishes a **baseline** and charges nothing; it watches forward from that month.
5. Put it on a monthly **Schedule**. The IRS refreshes the extract monthly, so a monthly schedule keeps pace with the source.
6. Each later run delivers only the organizations newly recognized since your last run.

#### Worked example (watch mode)

Input (also the store default):

```json
{ "mode": "watch", "states": ["TX"], "subsection": "03", "nteeCodes": ["P", "E"], "filterName": "tx-humanservices-health" }
````

This watches Texas 501(c)(3) organizations in Human Services (NTEE `P`) and Health Care (NTEE `E`). The values in the rows below are illustrative of the row shape, not a live pull.

The **first run** returns a single uncharged baseline row and watches forward:

```json
{ "event_type": "baseline", "filterName": "tx-humanservices-health", "billing": "uncharged",
  "note": "Baseline established: 312 in-window organization(s) on file for this filter; watching forward from today. No back-catalog was charged." }
```

A **later run**, once new organizations are recognized, returns one prospect row each (the first 500 per filter-month bill at the $0.00001 platform minimum, half a cent per 500 rows):

```json
{ "event_type": "new-org", "ein": "993312047", "name": "LONE STAR YOUTH REFUGE",
  "ico": null, "street": "4210 MEDICAL PKWY", "city": "AUSTIN", "state": "TX", "zip": "78756",
  "subsection": "501(c)(3)", "ntee_cd": "P30", "ntee_label": "Human Services",
  "ruling": "2026-05", "foundation_type": "Publicly supported organization 170(b)(1)(A)(vi)",
  "deductibility": "Contributions are deductible", "classification": "1700",
  "source_url": "https://projects.propublica.org/nonprofits/organizations/993312047",
  "checked_at": "2026-06-03T09:00:00.000Z", "filterName": "tx-humanservices-health",
  "billing": "included-tier", "note": null }
```

A month with no new organization returns an uncharged `digest-no-new` row, so you always get a run receipt.

#### Report mode and the demo cohort

Report mode produces a one-shot **new-determination cohort**. This public demo input is deterministic (the same inputs return the same rows):

```json
{ "mode": "report", "states": ["TX"], "subsection": "03", "nteeCodes": ["P"], "period": "2026-05" }
```

It returns every Texas 501(c)(3) Human-Services organization whose IRS determination (RULING) month is May 2026 as flat prospect rows, plus a one-line cohort summary written to the run's OUTPUT (the total, a tally by NTEE major group, and a tally by state). `period` accepts a single `YYYY-MM` or an inclusive `YYYY-MM..YYYY-MM` range.

### Demo dataset

The public demo dataset is at https://api.apify.com/v2/datasets/7mduUnF1ehII8S6af/items?format=json\&clean=true. It was generated by a live report-mode run using the Texas 501(c)(3) Human Services input above and contains 76 real prospect rows. Each row shows EIN, organization name, mailing address, subsection, NTEE mission, ruling month, foundation type, deductibility, source URL, billing marker, and checked timestamp.

### Output data

Every prospect row is flat JSON keyed on EIN, mapped straight from the IRS Business Master File with no enrichment:

| Field | Meaning |
|---|---|
| `ein` | Employer Identification Number (also the dedupe key). |
| `name`, `ico` | Organization name and in-care-of name. |
| `street`, `city`, `state`, `zip` | Mailing address (address-only; see the note above). |
| `subsection` | Decoded IRS subsection label (for example `501(c)(3)`). |
| `ntee_cd`, `ntee_label` | NTEE mission code and its decoded major-group label (for example `Human Services`). |
| `ruling` | The IRS determination month, normalized to `YYYY-MM`. |
| `foundation_type`, `deductibility`, `classification` | Decoded IRS foundation type, deductibility status, and raw classification code. |
| `source_url` | Per-EIN ProPublica Nonprofit Explorer link to re-verify the record. |
| `checked_at`, `filterName` | When the run checked, and which saved filter produced the row. |
| `event_type` | `new-org` for a prospect; `baseline`, `digest-no-new`, `truncation-marker`, `billing-blocked`, or `unwatched` for the uncharged status rows. |
| `billing` | How the row was billed (`included-tier`, `volume-tier`, `cohort-report`, `dry-run`, or `uncharged`). |

Status rows (`baseline`, `digest-no-new`, `truncation-marker`, `billing-blocked`, `unwatched`) carry null payload columns and an explanatory `note`. You can download the dataset in JSON, CSV, Excel, or HTML.

### Pricing

This actor is pay-per-event. Actor start is free.

- **Filter watch-month, $9.00** per named filter per calendar month, charged once on the first run of the month that completes a successful stream over a fresh feed. Your account's **first delivering month is free**: the free month is the first month that actually delivers new organizations, so the waived month is a real delivery and not an empty baseline (prospect rows still bill during it). A baseline or re-baseline run is never charged, and the fee is deferred while the feed is stale.
- **New-organization prospect, $0.00001** each for the first 500 delivered per filter-month (the Apify platform-minimum event price, half a cent per 500 rows, on top of the watch fee), then **$0.02** each beyond the 500th (the volume tier). Each row is pushed before it is charged.
- **Cohort report, $15.00** per successfully produced report; a stale feed or a failed run charges nothing.

**How big is a month (per-state math).** A mission-narrowed filter (one or two NTEE groups in one state) typically stays inside the 500 included tier, so it costs about **$9 per month**. A broad all-mission state filter can exceed it: measured 2026-07-06, a full all-mission month is roughly **1,178 new 501(c)(3) in California, 994 in Texas, 756 in Florida** (nationally about 10,390 per month). Rows past the 500 included tier bill at $0.02 each, so a broad all-mission state month costs roughly **$9 plus overage**, at the default caps at most about **$19** before the monthly ceiling switches to uncharged notice rows. To stay inside the $9 included tier, narrow with NTEE mission codes.

**Two monthly guards, so a broad filter cannot surprise-bill you.** `maxAlertRowsPerMonth` (default 1000) caps delivered prospects per filter-month, and `maxMonthlySpendUsd` (default 40) caps cumulative volume-tier charges; whichever trips first switches the run to uncharged notice rows. Anything withheld is not billed until delivered and redelivers next month.

**Set your per-run max total charge.** Because the $9 watch fee lands on a single run, set that run's **max total charge to at least $9 plus expected overage** (budget about $19 for a broad all-mission state). If the cap is too low the run fails closed: it delivers nothing, advances no filter memory, and writes one uncharged `billing-blocked` row telling you to raise the cap and rerun. Raise the cap and the next run delivers that month's prospects.

### Cadence and latency, stated plainly

The IRS refreshes the Business Master File on a **monthly** cadence, and what counts as new is the RULING (determination) **month**, not a day. So the honest latency is **the IRS monthly refresh after recognition**, not same-week: you see a new organization in the run after the IRS publishes the month that carries its determination. Schedule the actor monthly to match the source.

### Baseline-forward behavior

Alerts begin the month you start watching a filter. The first run seeds the organizations already on file (uncharged) and watches forward, so you are never billed for the historical back-catalog. If you **widen a saved filter** under the same name (add states or missions), the actor re-baselines it, again with no back-catalog charge. For the recent back-catalog, use **report mode**.

### Limitations

- **Address-only.** See the address-only note at the top: the deliverable is a prospect list built on mailing address, and the report earns its price on targeting quality.
- **Monthly, not real-time.** The source moves monthly by determination month, so this is a coverage-and-freshness feed, not an intraday alert.
- **US federal recognition only.** It reads the federal IRS extract, so it covers organizations the IRS has recognized; state-level charity registrations are a different record and are not included.
- **Single public source.** The actor reads one federal dataset. If the IRS pauses, truncates, or changes the extract, a freshness canary detects it and the run delivers nothing (and does not charge the watch fee) rather than shipping a partial or stale product.

### FAQ, disclaimer, and support

- **Where does the data come from?** The [IRS Exempt Organizations Business Master File Extract](https://www.irs.gov/charities-non-profits/exempt-organizations-business-master-file-extract-eo-bmf) (irs.gov/pub/irs-soi), a public federal record refreshed monthly. The actor reads it with no login and no key.
- **Is this legal and compliant?** The rows are public IRS exempt-organization records, and the actor redistributes public determination facts. It is registry information, not advice. You are responsible for ensuring your outreach complies with the rules that apply to you (for example fundraising, solicitation, and marketing regulations in your jurisdiction).
- **Can I preview before I schedule?** Yes. Set `dryRun: true` to stream, filter, and diff and return up to 5 preview rows tagged `billing: "dry-run"`. It charges no PPE event and writes no saved filter, billing, or event-history state, but the preview rows are still written to your dataset and OUTPUT, and the run still downloads and streams the full extract (about 343 MB, 327 MiB; measured at 342,745,263 bytes), so ordinary Apify platform compute, storage, and egress usage still applies.
- **AI agents and MCP.** The actor exposes its modes (watch, report, unwatch, list-events) through Apify's MCP integration, so an agent can enroll a filter and pull new determinations directly.
- **Request a change.** Use the **Issues** tab to report a problem or request a state, mission, or field.

# Actor input Schema

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

What this run does. watch: establish (first run) or advance a standing filter-watch and deliver newly-recognized organizations. unwatch: forget a saved filter's memory. list-events: replay this filter's prospect history. report: one-off new-determination cohort for a state/subsection/NTEE/period (billed once, $15).

## `states` (type: `array`):

US states/territories to watch, as 2-letter USPS codes matched against the IRS STATE column. At least one is required for a watch; report may be broad (leave empty for all states). Up to 10.

## `subsection` (type: `string`):

Which 501(c) subsection to watch, matched against the IRS SUBSECTION column. The default and primary use case is 501(c)(3). Choose 'all' to watch every subsection.

## `nteeCodes` (type: `array`):

NTEE prefixes matched against the IRS NTEE\_CD column. A single letter like P (Human Services) or E (Health Care) matches the whole major group; a longer prefix like B82 narrows further. Leave empty to watch all missions.

## `maxAlertRowsPerMonth` (type: `integer`):

Per-account monthly ceiling on delivered prospects. Past it the run withholds the rest and delivers an uncharged notice instead, so a broad all-mission state filter cannot surprise-bill you. Withheld prospects redeliver next month.

## `maxMonthlySpendUsd` (type: `integer`):

A money cap on cumulative volume-tier ($0.02) charges per filter-month. Whichever monthly cap trips first (this or Max prospects per month) stops charging. Does not include the $9 watch fee.

## `maxAlertsPerRun` (type: `integer`):

Hard cap on prospects delivered in a single run. Any overflow is not marked seen and redelivers on the next run, with a truncation notice naming how many were withheld. Bounds a long-gap catch-up run.

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

Optional https URL that receives a POST with the new prospects after each run. Best-effort alerting only: the dataset is the durable record. If you need to verify the caller, put a secret token in the URL yourself.

## `filterName` (type: `string`):

Names this filter within your account so its deduplication memory persists across scheduled runs. Lowercased, letters/digits/hyphens only (1 to 40 characters). Widening a saved filter under the same name re-baselines it (no back-catalog charge).

## `period` (type: `string`):

Report mode only. The RULING (determination) month window for the cohort, as YYYY-MM (a single month) or YYYY-MM..YYYY-MM (an inclusive range), for example 2026-04..2026-06.

## `dryRun` (type: `boolean`):

When true, stream, filter and diff but return at most 5 preview rows. It charges no PPE event and writes no saved filter, billing or event-history state, but the preview rows are still written to your dataset/OUTPUT. Use it to sanity check your filter before scheduling. A dry run still downloads and streams the full extract (about 343 MB, 327 MiB; measured at 342,745,263 bytes), so ordinary Apify platform compute, storage and egress usage still applies.

## Actor input object example

```json
{
  "mode": "watch",
  "states": [
    "TX"
  ],
  "subsection": "03",
  "nteeCodes": [
    "P",
    "E"
  ],
  "maxAlertRowsPerMonth": 1000,
  "maxMonthlySpendUsd": 40,
  "maxAlertsPerRun": 1000,
  "filterName": "tx-humanservices-health",
  "dryRun": false
}
```

# Actor output Schema

## `prospects` (type: `string`):

No description

## `runSummary` (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 = {
    "states": [
        "TX"
    ],
    "subsection": "03",
    "nteeCodes": [
        "P",
        "E"
    ],
    "maxAlertRowsPerMonth": 1000,
    "maxMonthlySpendUsd": 40,
    "maxAlertsPerRun": 1000,
    "filterName": "tx-humanservices-health"
};

// Run the Actor and wait for it to finish
const run = await client.actor("yungstentech/nonprofit-formation-radar").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 = {
    "states": ["TX"],
    "subsection": "03",
    "nteeCodes": [
        "P",
        "E",
    ],
    "maxAlertRowsPerMonth": 1000,
    "maxMonthlySpendUsd": 40,
    "maxAlertsPerRun": 1000,
    "filterName": "tx-humanservices-health",
}

# Run the Actor and wait for it to finish
run = client.actor("yungstentech/nonprofit-formation-radar").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 '{
  "states": [
    "TX"
  ],
  "subsection": "03",
  "nteeCodes": [
    "P",
    "E"
  ],
  "maxAlertRowsPerMonth": 1000,
  "maxMonthlySpendUsd": 40,
  "maxAlertsPerRun": 1000,
  "filterName": "tx-humanservices-health"
}' |
apify call yungstentech/nonprofit-formation-radar --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=yungstentech/nonprofit-formation-radar",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Nonprofit Formation Radar: New 501(c)(3) Prospect Alerts",
        "description": "Watch state(s), IRS subsection (default 501(c)(3)) and NTEE mission codes; each monthly run diffs the IRS EO Business Master File and delivers newly-recognized organizations as deduped prospect rows (EIN, name, mailing address, mission, ruling month). Address-only; report mode for cohorts.",
        "version": "0.0",
        "x-build-id": "qtZKSYgwLO25UN1kR"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/yungstentech~nonprofit-formation-radar/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-yungstentech-nonprofit-formation-radar",
                "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/yungstentech~nonprofit-formation-radar/runs": {
            "post": {
                "operationId": "runs-sync-yungstentech-nonprofit-formation-radar",
                "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/yungstentech~nonprofit-formation-radar/run-sync": {
            "post": {
                "operationId": "run-sync-yungstentech-nonprofit-formation-radar",
                "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",
                "properties": {
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "watch",
                            "unwatch",
                            "list-events",
                            "report"
                        ],
                        "type": "string",
                        "description": "What this run does. watch: establish (first run) or advance a standing filter-watch and deliver newly-recognized organizations. unwatch: forget a saved filter's memory. list-events: replay this filter's prospect history. report: one-off new-determination cohort for a state/subsection/NTEE/period (billed once, $15).",
                        "default": "watch"
                    },
                    "states": {
                        "title": "States",
                        "maxItems": 10,
                        "type": "array",
                        "description": "US states/territories to watch, as 2-letter USPS codes matched against the IRS STATE column. At least one is required for a watch; report may be broad (leave empty for all states). Up to 10.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "AL",
                                "AK",
                                "AZ",
                                "AR",
                                "CA",
                                "CO",
                                "CT",
                                "DE",
                                "DC",
                                "FL",
                                "GA",
                                "HI",
                                "ID",
                                "IL",
                                "IN",
                                "IA",
                                "KS",
                                "KY",
                                "LA",
                                "ME",
                                "MD",
                                "MA",
                                "MI",
                                "MN",
                                "MS",
                                "MO",
                                "MT",
                                "NE",
                                "NV",
                                "NH",
                                "NJ",
                                "NM",
                                "NY",
                                "NC",
                                "ND",
                                "OH",
                                "OK",
                                "OR",
                                "PA",
                                "RI",
                                "SC",
                                "SD",
                                "TN",
                                "TX",
                                "UT",
                                "VT",
                                "VA",
                                "WA",
                                "WV",
                                "WI",
                                "WY",
                                "PR",
                                "GU",
                                "VI",
                                "AS",
                                "MP"
                            ],
                            "enumTitles": [
                                "Alabama",
                                "Alaska",
                                "Arizona",
                                "Arkansas",
                                "California",
                                "Colorado",
                                "Connecticut",
                                "Delaware",
                                "District of Columbia",
                                "Florida",
                                "Georgia",
                                "Hawaii",
                                "Idaho",
                                "Illinois",
                                "Indiana",
                                "Iowa",
                                "Kansas",
                                "Kentucky",
                                "Louisiana",
                                "Maine",
                                "Maryland",
                                "Massachusetts",
                                "Michigan",
                                "Minnesota",
                                "Mississippi",
                                "Missouri",
                                "Montana",
                                "Nebraska",
                                "Nevada",
                                "New Hampshire",
                                "New Jersey",
                                "New Mexico",
                                "New York",
                                "North Carolina",
                                "North Dakota",
                                "Ohio",
                                "Oklahoma",
                                "Oregon",
                                "Pennsylvania",
                                "Rhode Island",
                                "South Carolina",
                                "South Dakota",
                                "Tennessee",
                                "Texas",
                                "Utah",
                                "Vermont",
                                "Virginia",
                                "Washington",
                                "West Virginia",
                                "Wisconsin",
                                "Wyoming",
                                "Puerto Rico",
                                "Guam",
                                "U.S. Virgin Islands",
                                "American Samoa",
                                "Northern Mariana Islands"
                            ]
                        }
                    },
                    "subsection": {
                        "title": "IRS subsection",
                        "enum": [
                            "03",
                            "04",
                            "06",
                            "19",
                            "all"
                        ],
                        "type": "string",
                        "description": "Which 501(c) subsection to watch, matched against the IRS SUBSECTION column. The default and primary use case is 501(c)(3). Choose 'all' to watch every subsection.",
                        "default": "03"
                    },
                    "nteeCodes": {
                        "title": "NTEE mission codes (optional)",
                        "type": "array",
                        "description": "NTEE prefixes matched against the IRS NTEE_CD column. A single letter like P (Human Services) or E (Health Care) matches the whole major group; a longer prefix like B82 narrows further. Leave empty to watch all missions.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxAlertRowsPerMonth": {
                        "title": "Max prospects per month",
                        "minimum": 500,
                        "maximum": 100000,
                        "type": "integer",
                        "description": "Per-account monthly ceiling on delivered prospects. Past it the run withholds the rest and delivers an uncharged notice instead, so a broad all-mission state filter cannot surprise-bill you. Withheld prospects redeliver next month.",
                        "default": 1000
                    },
                    "maxMonthlySpendUsd": {
                        "title": "Max monthly volume spend (USD)",
                        "minimum": 0,
                        "maximum": 100000,
                        "type": "integer",
                        "description": "A money cap on cumulative volume-tier ($0.02) charges per filter-month. Whichever monthly cap trips first (this or Max prospects per month) stops charging. Does not include the $9 watch fee.",
                        "default": 40
                    },
                    "maxAlertsPerRun": {
                        "title": "Max prospects per run",
                        "minimum": 1,
                        "maximum": 2000,
                        "type": "integer",
                        "description": "Hard cap on prospects delivered in a single run. Any overflow is not marked seen and redelivers on the next run, with a truncation notice naming how many were withheld. Bounds a long-gap catch-up run.",
                        "default": 1000
                    },
                    "webhookUrl": {
                        "title": "Webhook URL (optional)",
                        "type": "string",
                        "description": "Optional https URL that receives a POST with the new prospects after each run. Best-effort alerting only: the dataset is the durable record. If you need to verify the caller, put a secret token in the URL yourself."
                    },
                    "filterName": {
                        "title": "Filter name",
                        "type": "string",
                        "description": "Names this filter within your account so its deduplication memory persists across scheduled runs. Lowercased, letters/digits/hyphens only (1 to 40 characters). Widening a saved filter under the same name re-baselines it (no back-catalog charge).",
                        "default": "default"
                    },
                    "period": {
                        "title": "Report period (report mode)",
                        "type": "string",
                        "description": "Report mode only. The RULING (determination) month window for the cohort, as YYYY-MM (a single month) or YYYY-MM..YYYY-MM (an inclusive range), for example 2026-04..2026-06."
                    },
                    "dryRun": {
                        "title": "Dry run (preview, no PPE charge)",
                        "type": "boolean",
                        "description": "When true, stream, filter and diff but return at most 5 preview rows. It charges no PPE event and writes no saved filter, billing or event-history state, but the preview rows are still written to your dataset/OUTPUT. Use it to sanity check your filter before scheduling. A dry run still downloads and streams the full extract (about 343 MB, 327 MiB; measured at 342,745,263 bytes), so ordinary Apify platform compute, storage and egress usage still applies.",
                        "default": false
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
