# IRS Tax-Exempt Revocation Check — Auto-Revocation & Pub 78 (`malekh/irs-tax-exempt-revocation-check`) Actor

Bulk-check EINs against the IRS Automatic Revocation of Exemption List and Publication 78. Returns revocation, posting and reinstatement dates plus deductibility status codes — and never reports an unlisted church or group-ruling subordinate as revoked.

- **URL**: https://apify.com/malekh/irs-tax-exempt-revocation-check.md
- **Developed by:** [Malek H](https://apify.com/malekh) (community)
- **Categories:** Automation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.01 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

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

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

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

# README

## IRS Tax-Exempt Revocation Check

Bulk-check a list of EINs against the **IRS Automatic Revocation of Exemption
List** and **IRS Publication 78**, and get back a clear per-organization verdict
with the revocation, posting and reinstatement dates.

Built for the check a grantmaker has to make before money moves: *has this
organization lost its tax-exempt status, and are contributions to it still
deductible?*

### What it does

Give it EINs. For each one it returns:

| Field | Meaning |
|---|---|
| `status` | `eligible`, `revoked`, `reinstated`, `not_listed`, or `invalid_ein` |
| `autoRevoked` | appears on the IRS Automatic Revocation of Exemption List |
| `currentlyRevoked` | revoked with **no** reinstatement recorded |
| `revocationDate` | date the exemption was automatically revoked |
| `revocationPostingDate` | date the IRS posted the revocation |
| `reinstatementDate` | date exemption was reinstated, if it was |
| `pub78Listed` | currently listed in IRS Publication 78 |
| `contributionsDeductible` | `true` / `false` / `null` from the Pub 78 codes |
| `deductibilityCodes` | e.g. `["PC"]`, `["PF"]`, `["EO"]` |
| `advisory` | plain-English guidance on what the result does and does not prove |
| `revocationDetail`, `pub78Detail` | the full underlying records |

### Why exemption gets revoked

Under IRC §6033(j), an organization that fails to file a required annual return
or notice (Form 990, 990-EZ, 990-PF or the 990-N e-Postcard) for **three
consecutive years** loses its tax-exempt status automatically, by operation of
law. No IRS action or notice is required. Contributions made after the
revocation posting date are not deductible.

For a private foundation, a grant to a revoked organization is a non-qualifying
distribution and can trigger expenditure-responsibility obligations — which is
why this check is normally run over the whole grantee portfolio, not one EIN at
a time.

### It will not over-claim

**Absence from Publication 78 is not evidence of revocation.** Churches,
integrated auxiliaries, governmental units and most subordinates covered by a
group ruling are tax-exempt without ever appearing in Pub 78. A tool that
reported those as "not exempt" would block legitimate grants.

So the two lists are reported as the separate facts they are. An organization on
neither list comes back as `not_listed`, with an advisory saying exactly that —
never as `revoked`.

### It fails loudly rather than quietly clearing you

The dangerous failure mode for a compliance tool is not crashing — it is
returning "nothing found" because the source moved. If the IRS changes the
column layout of either file, every EIN would silently come back clean.

This Actor asserts a minimum row count **and** a minimum parse rate on each file
before it reports anything. If either check fails, the run **fails** with an
explanatory message. You will never get a clean bill of health this Actor could
not stand behind.

### Input

```json
{
  "records": [
    { "recordId": "GRANT-2026-014", "ein": "13-1837418" },
    { "recordId": "GRANT-2026-015", "ein": "530196605" }
  ],
  "checkPub78": true
}
```

A bare list of EIN strings also works:

```json
{ "records": ["13-1837418", "53-0196605"] }
```

- **`records`** — EINs, with or without the hyphen. Objects may carry a
  `recordId` (or `id`), which is echoed back so you can join the output to your
  own grants system. Any extra fields are returned untouched under `input`.
- **`checkPub78`** *(default `true`)* — set to `false` to check only the
  revocation list and skip the Publication 78 download. Faster, but you lose
  the deductibility status codes.

### Output

One dataset item per input record. Example:

```json
{
  "recordId": "GRANT-2026-014",
  "ein": "00-0003154",
  "organizationName": "OAKLEAF FOREST TENANT MANAGEMENT",
  "status": "revoked",
  "autoRevoked": true,
  "currentlyRevoked": true,
  "revocationDate": "2017-11-15",
  "revocationPostingDate": "2018-03-12",
  "reinstatementDate": null,
  "pub78Listed": false,
  "contributionsDeductible": null,
  "deductibilityCodes": [],
  "advisory": "Exemption automatically revoked for failing to file a return or notice for three consecutive years, with no reinstatement recorded. ...",
  "verifyUrl": "https://apps.irs.gov/app/eos/"
}
```

### Publication 78 deductibility codes

| Code | Meaning |
|---|---|
| `PC` | Public charity |
| `POF` | Private operating foundation |
| `PF` | Private foundation |
| `GROUP` | Subordinate in a group ruling; contributions deductible |
| `LODGE` | Domestic fraternal society under 170(c)(4) |
| `FORGN` | Foreign organization; deductible only under a tax treaty |
| `SO` / `SOUNK` | Supporting organization |
| `EO` | Exempt, but contributions are **not** deductible |
| `UNKWN` | Deductibility undetermined |

### Data sources

Both are US Government works in the public domain, published by the IRS
expressly for bulk download. No API key, no rate limit, no CAPTCHA.

- Automatic Revocation of Exemption List —
  `https://apps.irs.gov/pub/epostcard/data-download-revocation.zip`
- Publication 78 cumulative data —
  `https://apps.irs.gov/pub/epostcard/data-download-pub78.zip`

The IRS refreshes these monthly. Each output item carries `checkedAt` and
`sourceRowCounts` so you can evidence exactly what you checked and when.

### Not legal or tax advice

This Actor reports what the IRS files say. Final determinations belong to you
and your counsel. For a single organization, confirm against the IRS
[Tax Exempt Organization Search](https://apps.irs.gov/app/eos/).

# Actor input Schema

## `records` (type: `array`):

The organizations to check, as EINs. Hyphens are optional and leading zeros are added for you, so "13-1837418", "131837418" and "3154" all work. To carry your own identifier through to the output — a grantee ID, a row number — pass objects instead of strings: {"recordId": "G-1", "ein": "13-1837418"}. Your recordId is echoed on every result, including errors, so you can join the output straight back onto your list.

## `checkPub78` (type: `boolean`):

Cross-check each EIN against IRS Publication 78 as well as the revocation list, returning the deductibility status code (PC, POF, SO and so on). This is what distinguishes "currently eligible to receive deductible contributions" from merely "not revoked". It costs a second ~1.3M-record download; turn it off if you only need revocation status.

## Actor input object example

```json
{
  "records": [
    "13-1837418",
    {
      "recordId": "G-1",
      "ein": "000003154"
    }
  ],
  "checkPub78": true
}
```

# 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 = {
    "records": [
        "13-1837418",
        {
            "recordId": "G-1",
            "ein": "000003154"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("malekh/irs-tax-exempt-revocation-check").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 = { "records": [
        "13-1837418",
        {
            "recordId": "G-1",
            "ein": "000003154",
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("malekh/irs-tax-exempt-revocation-check").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 '{
  "records": [
    "13-1837418",
    {
      "recordId": "G-1",
      "ein": "000003154"
    }
  ]
}' |
apify call malekh/irs-tax-exempt-revocation-check --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=malekh/irs-tax-exempt-revocation-check",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/5EdLLMRfY36GPfH6V/builds/ufKfK9L9FJ1sFQ5wp/openapi.json
