# RCRA Corrective Action Cleanup Timeline & Overdue Milestones (`malonestar/epa-rcra-corrective-action-cleanup-monitor`) Actor

Track RCRA corrective-action cleanups from EPA RCRAInfo: milestone dates, scheduled vs actual, schedule slip, overdue milestones, remedy status, engineering and institutional controls, and confirmed release media per facility.

- **URL**: https://apify.com/malonestar/epa-rcra-corrective-action-cleanup-monitor.md
- **Developed by:** [Kyle Maloney](https://apify.com/malonestar) (community)
- **Categories:** Real estate, Developer tools, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.50 / 1,000 cleanup records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## RCRA Corrective Action Cleanup Timeline & Overdue Milestone Monitor

Turn EPA RCRAInfo's Corrective Action module into a **cleanup timeline you can act on**: where a
hazardous-waste cleanup actually stands, which milestones EPA scheduled and never recorded as finished,
how far a schedule has slipped, which media are contaminated, and which institutional and engineering
controls will bind a future owner.

Most RCRA products stop at a binary `CORRACTS` flag - "this facility has a corrective action". That tells
you a cleanup exists. It does not tell you whether the remedy was ever selected, whether construction was
ever completed, or that a remedy decision scheduled for 1998 still has no completion date on file.
This actor sells that record.

**Source:** EPA RCRAInfo bulk export, Corrective Action (CA) module - `CA_EVENT` (193,658 rows),
`CA_AREA` (30,310), `CA_AREA_EVENT` (266,397), `CA_AUTHORITY` (13,047), `CA_EVENT_AUTHORITY` (179,271)
and EPA's own 1,809-entry event-code dictionary, refreshed weekly. Facility names and addresses come from
the EPA Facility Registry Service. Keyless, and the sanctioned bulk path rather than EPA's robotic-query-
restricted search endpoints.

### Who it is for

- **Phase I / Phase II ESA consultants** - a RCRA corrective action next door is an ASTM E1527-21 line
  item, but "is it finished, and when" is what determines whether it is a recognised environmental
  condition today.
- **CRE lenders, acquirers and insurers** pricing remediation risk and timeline. `cleanup_stage`,
  `past_due_milestone_count` and `institutional_controls_established_count` are the three columns that
  move a number in a deal model.
- **Environmental counsel and consultants** tracking a client's or an adversary's cleanup schedule,
  including the legal authority the cleanup is being run under.
- **Redevelopment and brownfield teams** - EPA's `ready_for_anticipated_use` determination is the
  reuse signal, and it is published per facility.

### Example input

```json
{
  "state": "CO",
  "outputMode": "facility",
  "onlyWithPastDueMilestones": true,
  "includeFacilityDetails": true,
  "maxResults": 60
}
```

Look up named facilities anywhere in the country:

```json
{
  "state": "ANY",
  "handlerIds": [
    "COD007079478",
    "COD056828940"
  ],
  "outputMode": "both",
  "maxResults": 200
}
```

`state` is required, so a bare `{}` call is rejected before the run starts and can never begin a national
scan. `state: "ANY"` is accepted only together with `handlerIds`.

### What a row looks like

Eaton Aviation Corporation, 2501 Dallas St, Aurora CO (`COD007079478`), from the
`CSV-2026-08-16T03-00-00-0400` export:

- 67 corrective-action events on file, running 1988 to 2019
- a **CA400 REMEDY DECISION scheduled 1998-10-28 with no completion date in RCRAInfo** - past due by
  more than 10,000 days
- and, in the same record, a separate CA400 that *was* completed on 2001-02-22

Both facts ship on the row. Neither cancels the other, and the actor does not pick one.

### The stale-snapshot problem, and what this actor does about it

A superseded RCRAInfo bulk-export URL **does not 404**. Measured 2026-08-18: the previous week's path
answered HTTP 200 with 4,548,121 bytes, structurally identical to that week's 4,554,232-byte file. A
hard-coded path therefore keeps working forever while serving an ever-older snapshot, and every request
looks healthy.

So: the export run is resolved live on **every** run from EPA's own manifest, its age is asserted against
`maxSnapshotAgeDays`, the module URL is cross-checked against a second EPA endpoint, the downloaded byte
count is asserted equal to the size EPA declares, and `rcrainfo_run_id`, `rcrainfo_created_date` and
`data_as_of` ship on **every row**. Pinning a superseded run with `pinRunId` fails the run rather than
quietly serving it.

### Live drift gate

Ten probes run **before a single billable row is emitted**. Each has its own error boundary, and each
reports one of three outcomes - `pass`, `fail` (it completed and measured something wrong) or
`unavailable` (it could not complete at all).

| Probe | Role | What it asserts |
|---|---|---|
| `manifest_info` | load-bearing | EPA publishes a current export run, no older than `maxSnapshotAgeDays` |
| `snapshot_pin` | load-bearing | a pinned run is still the run EPA publishes |
| `manifest_modules` | load-bearing | the Corrective Action module exists and belongs to that run |
| `module_download` | load-bearing | bytes received equal the `fileSize` EPA declares |
| `archive_structure` | load-bearing | the zip-of-zips holds every required table plus `METADATA.txt` |
| `table_floors` | load-bearing | every table clears its row-count floor **and** parsed rows equal the count EPA declares in `METADATA.txt` |
| `header_contract` | load-bearing | no column was renamed or dropped |
| `dictionary_canary` | load-bearing | CA050, CA200, CA400, CA550RC, CA725YE, CA750YE, CA900CR and CA999NF still carry their recorded meanings |
| `positive_canary` | load-bearing | a known busy facility still returns its events, and a known past-due milestone is still on file |
| `negative_control` | corroborating | an impossible handler ID and an impossible location both return zero rows |

Any `fail`, or any load-bearing probe that could not complete, fails the run with **zero rows and zero
billing**. Only the corroborating probe may be lost while the run proceeds, and it is then disclosed in
`drift_gate_status`, `drift_probes_unavailable` and `drift_gate_note`.

### How this actor reads EPA's data honestly

- **The event-code dictionary is keyed on (owner, code), not code.** 212 of the 1,076 corrective-action
  codes carry more than one meaning depending on which agency filed them - CA103 is "ADMINISTRATIVE
  FINDING AGAINST FACILITY" under one owner and "CURRENT CONDITION REPORT RECD" under another. Decoding
  on the bare code publishes a different event than the one on file. With the composite key, 193,658 of
  193,658 national events resolve exactly; an unresolved pair keeps a `null` description rather than
  borrowing another owner's.
- **Release indicators are three-valued.** `AIR RELEASE IND` is blank on 89.4% of national areas. `null`
  and `not_reported` mean EPA published nothing; `false` and `no` mean EPA checked and recorded none.
  They are never collapsed.
- **Date sentinels are refused, and the raw value is kept.** The national export carries `19010101` as an
  actual-date sentinel, a `19350101`, and schedule pairs exactly a century apart (1952 original / 2052
  revised). Reading those as real produces a 36,525-day "schedule slip". Unusable dates become `null`
  with the raw value preserved in a `*_raw` column and the reason in `date_quality_flags`.
- **A missing value is never zero.** Acreage is published on 13% of areas, so `reported_acreage_total`
  is `null` where nothing was reported and always ships beside `reported_acreage_area_count`.
- **A completion that was never recorded is stated as such.** `past_due_milestone_count` means "EPA or
  the state records no completion for a milestone whose scheduled date has passed". That can mean the
  milestone is genuinely outstanding, or that a completion was never entered. The actor says which
  question it is answering rather than asserting the stronger claim.
- **`cleanup_stage` is gated on the ladder applying at all.** A facility whose events use only
  state-specific codes gets `cleanup_stage: null` and `cleanup_stage_basis: "state_specific_codes_only"`,
  with `cleanup_complete` and `corrective_action_open` both `null` - never a fabricated "earliest stage"
  and never a confident "still open".
- **Facility names come only from the RCRAINFO program record.** One EPA identifier can return several
  program rows with *different* names: `COD007079478` resolves to EATON AVIATION CORPORATION under
  RCRAINFO and STANLEY AVIATION LANDFILL SITE under SEMS. Taking the first row would publish the
  Superfund site name as the RCRA handler's. Every other program seen is listed in `frs_other_programs`.

### Pricing and failure behaviour

Billed on the automatic Result event - **one emitted row, one billable record**. `maxResults` is a hard
cap on both rows and cost, enforced identically in every output mode - including `both` - by a single
function every emitted row passes through. A run that cannot bound its own bill fails rather than
emitting. A run that cannot answer emits nothing and bills nothing:

- a missing or invalid `state` is rejected before the run starts (HTTP 400, nothing consumed);
- a failing drift gate fails the run with a message naming the probe that broke;
- a query that was well formed and simply matched nothing succeeds with zero rows and zero billing, and
  says so in the log.

### Use as an MCP tool

This actor is callable by AI agents over [mcp.apify.com](https://mcp.apify.com). Billing is unchanged when
it is called as a tool, and a run that cannot answer fails without billing.

```json
{
  "mcpServers": {
    "apify": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://mcp.apify.com/sse?actors=malonestar/epa-rcra-corrective-action-cleanup-monitor"
      ],
      "env": {
        "APIFY_TOKEN": "<your Apify token>"
      }
    }
  }
}
```

Worked agent prompt:

> For RCRA handler COD007079478, tell me what stage the corrective action has reached, whether any
> milestone is past due and by how long, and whether institutional controls are in place that would bind
> a buyer.

### Related actors

- **[EPA Contaminated Site Screener](https://apify.com/malonestar/epa-contaminated-site-screener)** -
  radius screening for Superfund, RCRA, ECHO enforcement and tanks around a coordinate. It answers
  *"is there a corrective action near this property"*; this actor answers *"how far along is it"*. The
  join key is the RCRA handler ID.
- **[EPA RCRA Hazardous Waste Generator Rollup](https://apify.com/malonestar/epa-rcra-hazwaste-generator-rollup)** -
  biennial-report waste generation and shipment volumes per handler.
- **[EPA Drinking Water Quality Screener](https://apify.com/malonestar/epa-drinking-water-quality-screener)** -
  SDWA violations and PFAS occurrence for the public water system serving a site.

### Output fields

The dataset declares **135 fields**. Facility rows and event rows share one schema;
`record_type` says which you are looking at, and fields that belong to only one mode are marked below.
Every field tolerates `null`.

#### Identity and provenance

| Field | Type | Description |
|---|---|---|
| `record_type` | string | null | facility for a per-handler cleanup rollup, event for a single decoded corrective-action event. One dataset can hold both when outputMode is "both". |
| `handler_id` | string | null | The 12-character RCRAInfo handler identifier this record belongs to. Joins to EPA ECHO, RCRAInfo and to the rcra\_ids field of epa-contaminated-site-screener. |
| `activity_location` | string | null | Two-character RCRAInfo activity location the event was filed under. Usually the state, but 94 national rows file under a location that differs from the handler-ID prefix, so this column is the authoritative one. |
| `activity_location_name` | string | null | Plain-English name of the activity location, including the non-state codes: Navajo Nation (NN), Trust Territories (TT) and the EPA administrative locations XH and XJ. |
| `rcrainfo_run_id` | string | null | The RCRAInfo bulk-export run this row was built from, resolved live on every run from EPA's manifest. A superseded export URL still answers HTTP 200 with the older snapshot instead of 404ing, so this is the only way to know which week you are reading. |
| `rcrainfo_created_date` | string | null | Timestamp EPA created this export run. |
| `rcrainfo_snapshot_age_days` | integer | null | How old the export run was when this row was produced. RCRAInfo refreshes weekly; the run fails rather than publishing anything older than maxSnapshotAgeDays. |
| `rcrainfo_snapshot_is_current` | boolean | null | True when the export used is the one EPA is currently publishing. False only when a caller deliberately pinned a different run, which this actor refuses to serve. |
| `ca_module_url` | string | null | The exact S3 URL the Corrective Action archive was downloaded from, resolved from EPA's module manifest rather than constructed. |
| `ca_module_bytes` | integer | null | Byte length of the downloaded archive, asserted equal to the fileSize EPA's manifest declares. A mismatch fails the run. |
| `ca_module_status` | string | null | Status of the RCRAInfo Corrective Action bulk module for this run. ok means the archive was downloaded, structurally verified and row-count reconciled against its own METADATA.txt. |
| `data_as_of` | string | null | Date portion of the export creation timestamp - the vintage of every corrective-action fact on this row. |
| `matched_facilities_total` | integer | null | How many facilities matched the query before the maxResults cap was applied. Compare with the row count to see what a capped run left behind. |
| `results_truncated` | boolean | null | True when the maxResults cap stopped rows being emitted. A capped answer is never presented as a complete one. |
| `drift_gate_status` | string | null | verified when every live drift probe passed, verified\_degraded when only a corroborating probe could not complete. A failing gate emits no rows at all, so these are the only two values that can appear on a row. |
| `drift_probes_verified` | string | null | Comma-separated names of the live probes that passed before any row was emitted. |
| `drift_probes_unavailable` | string | null | Comma-separated names of probes that could not complete. Empty on a fully verified run. |
| `drift_gate_note` | string | null | Human-readable disclosure when the run proceeded with a corroborating probe unavailable. null on a fully verified run. |

#### Facility identification (EPA Facility Registry Service)

| Field | Type | Description |
|---|---|---|
| `facility_name` | string | null | Facility name from the EPA Facility Registry Service RCRAINFO record. null when the lookup was not requested, capped or unavailable - see site\_lookup\_status. Never taken from another EPA program at the same address. |
| `facility_address` | string | null | Street address from the EPA Facility Registry Service RCRAINFO record. null rather than guessed when the lookup did not resolve. |
| `facility_city` | string | null | City from the EPA Facility Registry Service RCRAINFO record. |
| `facility_state` | string | null | State from the EPA Facility Registry Service. Can differ from activity\_location, which is where the corrective-action file is administered. |
| `facility_zip` | string | null | Postal code from the EPA Facility Registry Service RCRAINFO record. |
| `facility_county` | string | null | County name from the EPA Facility Registry Service RCRAINFO record. |
| `frs_registry_id` | string | null | EPA Facility Registry Service registry identifier, the cross-program key that joins this facility to Superfund, TRI, ECHO and air/water permitting records. |
| `epa_region_code` | string | null | EPA region code the facility sits in, from the Facility Registry Service. |
| `echo_facility_report_url` | string | null | Direct link to the EPA ECHO Detailed Facility Report for this facility, built from the FRS registry ID. null when no registry ID resolved. |
| `frs_other_programs` | array | null | Every EPA program acronym the Facility Registry Service returned for this identifier, e.g. SEMS or BR. Reported because one identifier can carry a DIFFERENT facility name under a different program, and only the RCRAINFO row is used for facility\_name. |
| `site_lookup_status` | string | null | ok, not\_found, no\_rcrainfo\_record, lookup\_truncated, filter\_not\_applied, unavailable, skipped\_lookup\_cap or not\_requested. This is the null-versus-false contract for every facility\_\* field: null here never means "no such facility". unavailable means the FRS request could not complete, which is not evidence the facility is absent - EPA FRS flaps under concurrency and the same handler ID usually resolves on a later run. lookup\_truncated means EPA FRS holds more program rows for this identifier than one request returns and none of the rows read was the RCRAINFO row, so absence could not be proven; no\_rcrainfo\_record is used only when the returned set is demonstrably complete, checked against efservice's own exact COUNT. |

#### Cleanup status (facility rows)

| Field | Type | Description |
|---|---|---|
| `cleanup_stage` | string | null | Furthest COMPLETED rung of EPA's national corrective-action sequence for this facility, e.g. investigation\_complete, remedy\_decision, remedy\_construction, process\_terminated. null when nothing on the national ladder has been completed - see cleanup\_stage\_basis. Facility rows only. |
| `cleanup_stage_rank` | integer | null | Ordinal position of cleanup\_stage, 1 to 18. Sortable measure of how far a cleanup has progressed. Facility rows only. |
| `cleanup_stage_label` | string | null | Human-readable label for cleanup\_stage. Facility rows only. |
| `cleanup_stage_date` | string | null | Completion date of the event that set cleanup\_stage. Facility rows only. |
| `cleanup_stage_basis` | string | null | national\_milestone\_ladder, ladder\_milestones\_scheduled\_none\_completed, or state\_specific\_codes\_only. The third value means the state files this cleanup entirely under its own codes, so progress cannot be placed on the national ladder - reported instead of guessed. Facility rows only. |
| `cleanup_complete` | boolean | null | True when EPA records performance standards attained (CA900) or the corrective-action process terminated (CA999). null - never false - when the facility uses only state-specific codes, because completion is then genuinely unknown. Facility rows only. |
| `corrective_action_open` | boolean | null | The inverse of cleanup\_complete, gated the same way: null when completion status is unknown rather than assumed open. Facility rows only. |
| `ca_event_count` | integer | null | Number of corrective-action events RCRAInfo carries for this facility. Facility rows only. |
| `ca_event_completed_count` | integer | null | Events with a usable completion date. Facility rows only. |
| `ladder_milestone_event_count` | integer | null | Events whose code is on EPA's national milestone ladder. Facility rows only. |
| `state_specific_event_count` | integer | null | Events whose (owner, code) pair is not in the dictionary slice used for the national ladder. Facility rows only. |
| `unresolved_event_code_count` | integer | null | Events whose (owner, code) pair could not be resolved in EPA's own dictionary. Should be zero; a non-zero value means EPA shipped a code it does not define. Facility rows only. |
| `first_recorded_event_date` | string | null | Earliest completion date across this facility's corrective-action events. null when nothing has been completed. Facility rows only. |
| `last_recorded_event_date` | string | null | Most recent completion date across this facility's events - the practical measure of whether a cleanup is still moving. Facility rows only. |
| `years_since_last_recorded_event` | number | null | Years between last\_recorded\_event\_date and today. A large value on an open cleanup is the dormancy signal. Facility rows only. |
| `events_with_date_quality_flags` | integer | null | How many of this facility's events carried a date EPA published that could not be used - a sentinel, a malformed value or a pre-RCRA year. Facility rows only. |

#### National milestone dates (facility rows)

| Field | Type | Description |
|---|---|---|
| `rfa_completed_date` | string | null | Date the RCRA Facility Assessment was completed (CA050). Facility rows only. |
| `investigation_needed` | string | null | EPA's CA070 determination: investigation\_necessary or investigation\_not\_necessary. null when no determination is on file. Facility rows only. |
| `investigation_imposed_date` | string | null | Date the RCRA Facility Investigation was imposed (CA100). Facility rows only. |
| `investigation_complete_date` | string | null | Date the facility investigation was completed (CA200). Facility rows only. |
| `cms_complete_date` | string | null | Date the corrective measures study was completed (CA350). Facility rows only. |
| `remedy_decision_date` | string | null | Date the remedy decision was issued (CA400). null when RCRAInfo records no completed remedy decision - which, paired with a past-due CA400 milestone, is the classic behind-schedule cleanup. Facility rows only. |
| `remedy_design_approved_date` | string | null | Earliest completion of corrective-measures design approval or CMI workplan approval (CA450 / CA500). Facility rows only. |
| `remedy_construction_status` | string | null | EPA's CA550 determination: remedy\_constructed, no\_remedy\_constructed, operating\_facility\_remedy\_deferral, or recorded\_without\_outcome\_code. null when no determination is on file. Facility rows only. |
| `remedy_construction_date` | string | null | Date of the latest CA550 remedy-construction determination. Facility rows only. |
| `stabilization_construction_date` | string | null | Date stabilization or interim-measure construction was completed (CA650). Facility rows only. |
| `human_exposures_controlled` | string | null | EPA environmental indicator CA725: yes\_human\_exposures\_controlled, more\_information\_needed, facility\_does\_not\_meet\_definition, no\_control\_measures\_needed or previous\_determination\_not\_applicable. null when EPA has made no determination. Facility rows only. |
| `human_exposures_controlled_date` | string | null | Date of the latest CA725 determination. Facility rows only. |
| `groundwater_migration_controlled` | string | null | EPA environmental indicator CA750: yes\_groundwater\_migration\_controlled, more\_information\_needed, no\_release\_to\_groundwater, facility\_does\_not\_meet\_definition or previous\_determination\_not\_applicable. null when no determination exists. Facility rows only. |
| `groundwater_migration_controlled_date` | string | null | Date of the latest CA750 determination. Facility rows only. |
| `ready_for_anticipated_use` | string | null | EPA's CA800 determination: ready\_for\_anticipated\_use or not\_ready\_for\_anticipated\_use. The redevelopment signal for a CRE buyer. null when no determination is on file. Facility rows only. |
| `ready_for_anticipated_use_date` | string | null | Date of the latest CA800 determination. Facility rows only. |
| `performance_standards_attained` | string | null | EPA's CA900 determination: attained\_controls\_required or attained\_no\_controls\_necessary. The first of the two ways a RCRA corrective action formally finishes. Facility rows only. |
| `performance_standards_attained_date` | string | null | Date performance standards were recorded as attained. Facility rows only. |
| `ca_process_terminated` | string | null | EPA's CA999 determination: no\_further\_action, remedial\_activities\_complete, or terminated. Facility rows only. |
| `ca_process_terminated_date` | string | null | Date the corrective-action process was recorded as terminated. Facility rows only. |

#### Schedule slip and overdue milestones (facility rows)

| Field | Type | Description |
|---|---|---|
| `past_due_milestone_count` | integer | null | How many corrective-action milestones have a scheduled date in the past and no completion recorded in RCRAInfo. Read honestly: that can mean the milestone is genuinely outstanding OR that a completion was never entered. Facility rows only. |
| `past_due_oldest_code` | string | null | Event code of the longest-outstanding milestone. Facility rows only. |
| `past_due_oldest_description` | string | null | EPA's description of the longest-outstanding milestone. Facility rows only. |
| `past_due_oldest_scheduled_date` | string | null | The effective scheduled date of the longest-outstanding milestone - revised date if one exists, otherwise the original. Facility rows only. |
| `past_due_oldest_days` | integer | null | How many days the longest-outstanding milestone has been past its scheduled date. Facility rows only. |
| `past_due_codes` | array | null | Distinct event codes with an outstanding scheduled milestone, up to 25. Facility rows only. |
| `rescheduled_milestone_count` | integer | null | How many milestones carry both an original and a revised schedule date that could be compared. Facility rows only. |
| `max_schedule_slip_days` | integer | null | Largest plausible outward schedule slip on this facility, in days. Implausible pairs are excluded and counted separately rather than published. Facility rows only. |
| `max_schedule_slip_code` | string | null | Event code carrying the largest plausible slip. Facility rows only. |
| `max_schedule_slip_description` | string | null | EPA description of the event carrying the largest plausible slip. Facility rows only. |
| `implausible_schedule_slip_count` | integer | null | Number of computed slips exceeding 20 years, excluded from max\_schedule\_slip\_days as data-entry artefacts. Reported so the exclusion is visible rather than silent. Facility rows only. |

#### Institutional and engineering controls (facility rows)

| Field | Type | Description |
|---|---|---|
| `engineering_controls_established_count` | integer | null | Number of CA770 engineering-control events on file - caps, barriers, groundwater controls. A property with engineering controls carries continuing obligations. Facility rows only. |
| `engineering_controls_types` | array | null | Outcome suffixes of the CA770 events: GW groundwater control, NG non-groundwater control. Facility rows only. |
| `engineering_controls_terminated_count` | integer | null | Number of CA780 events terminating an engineering control. Facility rows only. |
| `institutional_controls_established_count` | integer | null | Number of CA772 institutional-control events - deed restrictions, zoning, informational devices. These bind a future owner and are the single most consequential column for a CRE buyer. Facility rows only. |
| `institutional_controls_types` | array | null | Outcome suffixes of the CA772 events: PR proprietary control, GC governmental control, EP enforcement and permit tools, ID informational device. Facility rows only. |
| `institutional_controls_terminated_count` | integer | null | Number of CA782 events terminating an institutional control. Facility rows only. |

#### Contamination areas and release media (facility rows)

| Field | Type | Description |
|---|---|---|
| `area_count` | integer | null | Number of CA\_AREA records EPA carries for this facility - the distinct areas of concern or solid waste management units under corrective action. Facility rows only. |
| `area_names` | array | null | Names of the contamination areas, up to 25. Facility rows only. |
| `entire_facility_area_count` | integer | null | How many areas are flagged as covering the entire facility rather than a discrete unit. Facility rows only. |
| `regulated_unit_area_count` | integer | null | How many areas are RCRA regulated units. Facility rows only. |
| `reported_acreage_total` | number | null | Sum of AREA ACREAGE across the areas that actually report one. null when no area reports acreage - never zero, because 87% of national areas publish no acreage and a bare sum would present a fraction of the footprint as the whole. Facility rows only. |
| `reported_acreage_area_count` | integer | null | How many of this facility's areas contributed to reported\_acreage\_total. The denominator that makes the sum readable. Facility rows only. |
| `unparseable_acreage_count` | integer | null | Areas whose published acreage could not be read as a number. Counted rather than coerced to zero. Facility rows only. |
| `air_release` | string | null | yes, no or not\_reported. EPA's AIR RELEASE IND is three-valued and blank on 89% of national areas, so not\_reported is by far the most common answer and is NOT a clean bill. Facility rows only. |
| `air_release_confirmed` | boolean | null | True only where EPA affirmatively records an air release, false where EPA records none, null where nothing was reported. Facility rows only. |
| `groundwater_release` | string | null | yes, no or not\_reported, rolled up across the facility's areas. Facility rows only. |
| `groundwater_release_confirmed` | boolean | null | True/false/null form of groundwater\_release. null means not reported, never "no release". Facility rows only. |
| `soil_release` | string | null | yes, no or not\_reported, rolled up across the facility's areas. Facility rows only. |
| `soil_release_confirmed` | boolean | null | True/false/null form of soil\_release. Facility rows only. |
| `surface_water_release` | string | null | yes, no or not\_reported, rolled up across the facility's areas. Facility rows only. |
| `surface_water_release_confirmed` | boolean | null | True/false/null form of surface\_water\_release. Facility rows only. |
| `confirmed_release_media` | array | null | The media EPA affirmatively records a release to: air, groundwater, soil, surface\_water. An empty array means none was affirmatively recorded, which is not the same as none exists. Facility rows only. |

#### Legal authority (facility rows)

| Field | Type | Description |
|---|---|---|
| `authority_count` | integer | null | Number of legal authorities RCRAInfo records for this facility's corrective action. Facility rows only. |
| `authority_types` | array | null | RCRAInfo authority-type codes, e.g. C consent decree, O operating permit, V voluntary corrective action. Facility rows only. |
| `authority_type_labels` | array | null | Decoded authority names from EPA's CA\_LU\_AUTHORITY table. An unmapped code is surfaced as unmapped\_authority\_type:<code> rather than dropped. Facility rows only. |
| `earliest_authority_date` | string | null | Earliest authority effective date on file - roughly when the cleanup obligation attached. Facility rows only. |
| `under_enforcement_authority` | boolean | null | True when at least one authority is an order or decree rather than a permit or policy. null when EPA records no authority at all, never false. Facility rows only. |

#### Event timeline (event rows)

| Field | Type | Description |
|---|---|---|
| `event_seq` | string | null | RCRAInfo event sequence number within the handler. Part of the composite key that joins an event to its areas and authorities. Event rows only. |
| `event_agency` | string | null | RCRAInfo agency code that recorded the event: S state, E EPA, J joint, P other. Event rows only. |
| `event_owner` | string | null | RCRAInfo owner of the event record. Load-bearing: the event-code dictionary is keyed on (owner, code), and 212 codes mean different things under different owners. Event rows only. |
| `event_code` | string | null | The full RCRAInfo corrective-action event code, e.g. CA400 or CA550RC. Event rows only. |
| `event_base_code` | string | null | First five characters of the event code, which identify the milestone. Event rows only. |
| `event_code_suffix` | string | null | Trailing characters of the event code, which carry the OUTCOME of the milestone, e.g. RC remedy constructed, NR no remedy constructed, YE yes, NO no. null when the code has no suffix. Event rows only. |
| `event_description` | string | null | Verbatim description from EPA's CA\_LU\_EVENT\_CODE dictionary, resolved on the (owner, code) composite key. null when the pair is not in the dictionary - never borrowed from another owner's entry for the same code. Event rows only. |
| `event_code_active_status` | string | null | Y if the code is still in EPA's active vocabulary, N if retired. Retired codes are still decoded, because historical events use them. Event rows only. |
| `event_code_decode_basis` | string | null | owner\_code\_exact when the (owner, code) pair resolved in EPA's dictionary, unresolved when it did not. An unresolved event keeps a null description rather than being guessed. Event rows only. |
| `event_code_ambiguous_across_owners` | boolean | null | True when this event code carries more than one meaning across RCRAInfo owners. 212 of the 1,076 codes do. Disclosed so a downstream consumer never keys on the bare code. Event rows only. |
| `ladder_stage` | string | null | Which rung of EPA's national corrective-action sequence this event belongs to, or null for a state-specific code that is not on the national ladder. Event rows only. |
| `ladder_rank` | integer | null | Ordinal position of ladder\_stage, 1 (RFA initiated) to 18 (process terminated). null for state-specific codes. Event rows only. |
| `schedule_date_original` | string | null | ISO date the milestone was originally scheduled for, or null when RCRAInfo published nothing usable. Event rows only. |
| `schedule_date_original_raw` | string | null | The raw eight-digit value EPA published, preserved even when it was rejected as a sentinel or an implausible date, so nothing is silently discarded. Event rows only. |
| `schedule_date_revised` | string | null | ISO date the milestone was rescheduled to, or null when it was never rescheduled or the value was unusable. Event rows only. |
| `schedule_date_revised_raw` | string | null | The raw eight-digit revised schedule value EPA published. Event rows only. |
| `actual_date` | string | null | ISO date the milestone was actually completed. null means RCRAInfo records no completion, which is NOT the same as the milestone being incomplete in the real world. Event rows only. |
| `actual_date_raw` | string | null | The raw eight-digit completion value. Preserved when the value was a sentinel such as 19010101, which appears in the national export and is not a 1901 completion. Event rows only. |
| `best_date` | string | null | EPA's own derived "best" date for the event, published in the export. Event rows only. |
| `schedule_slip_days` | integer | null | Revised schedule date minus original schedule date, in days. Positive means the deadline moved later. null when either date was unusable - the national export contains pairs a century apart that would otherwise publish a 36,525-day slip. Event rows only. |
| `schedule_slip_status` | string | null | computed, not\_rescheduled, revised\_without\_original, or undeterminable\_bad\_date. Distinguishes "was never rescheduled" from "was rescheduled but the dates cannot be trusted". Event rows only. |
| `schedule_slip_implausible` | boolean | null | True when a computed slip exceeds 20 years, which in this dataset indicates a data-entry artefact rather than a regulatory decision. null when there is no slip to judge. Event rows only. |
| `milestone_completed` | boolean | null | True when RCRAInfo carries a usable completion date for this event. Event rows only. |
| `milestone_past_due` | boolean | null | True when the effective scheduled date has passed and RCRAInfo records no completion. False when it is completed or the date is in the future. null when no schedule was ever recorded, because "past due" is then not a question that can be asked. Event rows only. |
| `days_past_due` | integer | null | Days between the effective scheduled date and today, for a milestone with no recorded completion. null otherwise. Event rows only. |
| `responsible_person` | string | null | RCRAInfo responsible-person code recorded against the event. Event rows only. |
| `suborganization` | string | null | RCRAInfo suborganization code recorded against the event. Event rows only. |
| `public_notes` | string | null | Free-text public note EPA or the state attached to the event. Populated on roughly 1.6% of national events. Event rows only. |
| `date_quality_flags` | array | null | Which date columns on this event were rejected and why, e.g. actual\_date\_sentinel or schedule\_date\_original\_implausible. Empty when every published date was usable. Event rows only. |
| `linked_area_seqs` | array | null | CA\_AREA sequence numbers this event is linked to through CA\_AREA\_EVENT. Empty when EPA links the event to no area - 4.6% of national events are unlinked. Event rows only. |
| `linked_area_names` | array | null | Names of the contamination areas this event is linked to, e.g. ENTIRE FACILITY or a named solid waste management unit. Event rows only. |
| `linked_authority_types` | array | null | RCRAInfo authority-type codes the event was taken under, from CA\_EVENT\_AUTHORITY. Event rows only. |

### FAQ

**Is this the same as the CORRACTS flag on a Phase I database report?**
No. CORRACTS is a yes/no. This is the underlying event record: which milestones exist, when each was
scheduled, when each was actually completed, and which are still outstanding.

**Does "past due" mean the facility is in violation?**
No, and the actor never says so. It means RCRAInfo records no completion date for a milestone whose
scheduled date has passed. Compliance and enforcement are a different RCRAInfo module and are
deliberately out of scope here.

**How fresh is the data?**
EPA refreshes the bulk export weekly. `data_as_of` and `rcrainfo_snapshot_age_days` are on every row, and
the run fails rather than serving anything older than `maxSnapshotAgeDays` (default 21).

**Why is `cleanup_stage` null on some facilities?**
Because that state files its corrective-action events entirely under its own codes, which are not on
EPA's national milestone ladder. `cleanup_stage_basis` says so explicitly rather than guessing a stage.

**Can I get the raw event timeline instead of a rollup?**
Yes - set `outputMode` to `event` for one row per corrective-action event, or `both` for rollups followed
by the events of those same facilities. `both` shares one `maxResults` budget: at most half of it (rounded
up) goes to rollups and the rest to their events, and whichever side cannot fill its share hands the
remainder to the other, so a `both` run always returns both kinds when both exist.

**Where do the facility names and addresses come from?**
The EPA Facility Registry Service, filtered to the RCRAINFO program record. Set
`includeFacilityDetails: false` to skip those lookups entirely; the `facility_*` fields then stay `null`
with `site_lookup_status: "not_requested"`.

# Actor input Schema

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

Two-letter RCRAInfo activity location to screen, e.g. CO, TX, CA. RCRAInfo uses 59 location codes, which are the 50 states plus DC, AS, GU, PR, VI, NN (Navajo Nation), TT (Trust Territories) and the EPA administrative codes XH and XJ. Required, so an empty call can never start a national run. Pass the literal value ANY to look facilities up nationally - ANY is only accepted together with a non-empty Handler IDs list.

## `handlerIds` (type: `array`):

Specific 12-character RCRAInfo handler IDs, e.g. COD007079478. When supplied these are matched nationally and the activity location above is ignored, so this is the right input for looking up a named facility. Leave empty to screen the whole activity location.

## `outputMode` (type: `string`):

facility = one rollup row per RCRA handler with the cleanup stage, every national milestone date and the past-due summary. event = one row per corrective-action event, the raw decoded timeline. both = facility rollups followed by the events of those same facilities, sharing one maximum-results budget: at most half of it (rounded up) goes to rollups and the rest to their events, and whichever side cannot fill its share hands the remainder to the other, so both always returns both kinds when both exist.

## `onlyWithPastDueMilestones` (type: `boolean`):

Keep only facilities where at least one corrective-action milestone has a scheduled date in the past and no completion date on file in RCRAInfo. Note the honest reading: that means EPA or the state records no completion, which can mean the milestone is genuinely outstanding OR that a completion was never entered.

## `onlyOpenCleanups` (type: `boolean`):

Keep only facilities whose corrective action is still open - no CA900 performance-standards-attained event and no CA999 process-terminated event. Facilities whose events use only state-specific codes are excluded by this filter because their completion status is genuinely unknown rather than open.

## `includeFacilityDetails` (type: `boolean`):

Resolve each emitted handler's facility name, street address, city, county and FRS registry ID from the EPA Facility Registry Service. One small request per facility. Turn off for a faster run; the facility\_\* fields then stay null with site\_lookup\_status set to not\_requested rather than being guessed.

## `maxResults` (type: `integer`):

Hard cap on emitted rows, which is also the hard cap on what this run can bill. It is enforced identically in every output mode, including both, by one function every emitted row passes through - a run that cannot bound its own bill fails instead of emitting. Rows are ordered worst-overdue first, so a capped run keeps the most consequential facilities. matched\_facilities\_total and results\_truncated on every row report what the cap left behind.

## `maxFacilityLookups` (type: `integer`):

Cap on EPA Facility Registry Service lookups per run. Facilities beyond the cap are still emitted with their full cleanup timeline; their facility\_\* fields stay null and site\_lookup\_status reads skipped\_lookup\_cap.

## `maxSnapshotAgeDays` (type: `integer`):

The run fails if the newest RCRAInfo bulk export EPA publishes is older than this. RCRAInfo refreshes weekly, and a superseded export URL keeps answering HTTP 200 with the older snapshot instead of 404ing, so this freshness assertion is what stops stale cleanup milestones being sold as current.

## `pinRunId` (type: `string`):

Reproduce an earlier answer by naming a RCRAInfo export run, e.g. CSV-2026-08-16T03-00-00-0400. If the pinned run is no longer the one EPA publishes, the run fails loudly rather than quietly serving a superseded snapshot. Leave blank for the current export.

## `simulateOutage` (type: `string`):

Diagnostic seam that forces one drift probe to be unable to complete, so the failure path can be re-proved on demand instead of only during a real outage. none runs normally.

## Actor input object example

```json
{
  "state": "CO",
  "handlerIds": [],
  "outputMode": "facility",
  "onlyWithPastDueMilestones": true,
  "includeFacilityDetails": true,
  "maxResults": 60,
  "maxFacilityLookups": 150,
  "maxSnapshotAgeDays": 21,
  "simulateOutage": "none"
}
```

# Actor output Schema

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

The default dataset.

# 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 = {
    "state": "CO",
    "handlerIds": [],
    "outputMode": "facility",
    "onlyWithPastDueMilestones": true,
    "onlyOpenCleanups": false,
    "includeFacilityDetails": true,
    "maxResults": 60,
    "simulateOutage": "none"
};

// Run the Actor and wait for it to finish
const run = await client.actor("malonestar/epa-rcra-corrective-action-cleanup-monitor").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 = {
    "state": "CO",
    "handlerIds": [],
    "outputMode": "facility",
    "onlyWithPastDueMilestones": True,
    "onlyOpenCleanups": False,
    "includeFacilityDetails": True,
    "maxResults": 60,
    "simulateOutage": "none",
}

# Run the Actor and wait for it to finish
run = client.actor("malonestar/epa-rcra-corrective-action-cleanup-monitor").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "state": "CO",
  "handlerIds": [],
  "outputMode": "facility",
  "onlyWithPastDueMilestones": true,
  "onlyOpenCleanups": false,
  "includeFacilityDetails": true,
  "maxResults": 60,
  "simulateOutage": "none"
}' |
apify call malonestar/epa-rcra-corrective-action-cleanup-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,malonestar/epa-rcra-corrective-action-cleanup-monitor"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/OEkbIrWqSdPkhXuF3/builds/EqJWlsaHLHthTIBOF/openapi.json
