# EPA Contaminated Site Screener — Superfund/NPL Proximity Check (`malonestar/epa-contaminated-site-screener`) Actor

Multi-database Phase I ESA regulatory-records screen. Screen a US address or coordinate for nearby EPA sites across Superfund/NPL, RCRA, TRI, UST, LUST, Brownfields, plus optional ASTM E1527-21 search-distance verdicts. Keyless EPA Envirofacts + ECHO + ArcGIS + Census geocoder.

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

## Pricing

from $5.50 / 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.
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 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/docs.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.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/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

## EPA Contaminated Site Screener — Phase I ESA Multi-Database Records Search

Screens a US address or coordinate against six EPA regulatory databases for nearby contaminated and regulated sites — the multi-database records search that sits at the core of a Phase I Environmental Site Assessment (ASTM E1527). Built for Phase I consultants, CRE buyers and lenders, environmental attorneys, and underwriters who need to triage a property or a portfolio before ordering the full report. Optional `astmMode` adds an ASTM E1527-21 standard search-distance verdict per database. No API key.

### Programs covered

Each nearby site becomes one row, tagged with its `program`:

| `program` | EPA database | Source |
|---|---|---|
| `SUPERFUND` | NPL / Superfund (SEMS) | EPA Envirofacts `data.epa.gov/efservice/ENVIROFACTS_SITE` |
| `RCRA` | Hazardous-waste handlers / corrective action | EPA ECHO |
| `TRI` | Toxic Release Inventory reporters | EPA ECHO |
| `UST` | Underground storage tank facilities | EPA UST Finder (ArcGIS) |
| `LUST` | Leaking underground storage tank releases | EPA UST Finder (ArcGIS) |
| `BROWNFIELD` | Brownfields / ACRES | EPA FRS (ArcGIS) |

Addresses are geocoded with the free US Census geocoder. Per-program fetch failures warn and continue, so one database being down never fails the run — you get the hits from the programs that answered.

### Two modes

**`assets` mode (default)** — screen your properties. For each asset, the actor queries every selected program within your radius and returns one row per nearby site, carrying `program`, `list`, `site_name`, `distance_miles`, `status`, and an `on_npl` flag. An asset with no hits still returns one `clear` row; a bad input returns one `error` row. Each asset item is either `{ "address": "...", "label": "..." }` or `{ "lat": <n>, "lon": <n>, "state": "<2-letter>", "label": "..." }`. The `state` field is required with lat/lon because Superfund/SEMS is fetched per state. Leave `programs` empty to screen all six; `maxHitsPerProgram` (default 50) caps the nearest hits kept per program per asset. Set `astmMode: true` to add one extra ASTM E1527-21 search-distance summary row per asset (see below); it's off by default so existing integrations see no change.

```json
{
  "mode": "assets",
  "assets": [
    { "lat": 39.8037, "lon": -104.9986, "state": "CO", "label": "Denver warehouse" },
    { "address": "5980 Lipan St, Denver, CO 80221", "label": "Denver warehouse (by address)" }
  ],
  "radiusMiles": 1,
  "programs": ["SUPERFUND", "RCRA", "TRI", "UST", "LUST", "BROWNFIELD"],
  "maxHitsPerProgram": 50,
  "astmMode": true
}
````

**`inventory` mode** — list the raw EPA SEMS/Superfund site roster for the states you name (Superfund only; the other five programs don't apply here).

```json
{ "mode": "inventory", "states": ["CO", "NJ"], "onlyNpl": true }
```

### Key output fields (assets mode)

- `result_type` — `listing` (a hit), `clear` (screened, nothing within radius), or `error`.
- `program`, `list` — the EPA program and its readable database name.
- `site_name`, `site_address`, `site_city`, `site_state`, `site_zip` — the listed site; `site_id`, `registry_id` its identifiers.
- `distance_miles` — great-circle distance from the asset to the site.
- `status`, `status_detail` — program-specific (NPL status, open/closed UST counts, LUST substance/date, brownfield type).
- `on_npl` — true only for an active NPL/Superfund hit, the highest-concern signal.
- `phase1_flag` — true on any listing row.
- `asset_*`, `radius_miles`, `checked_at`, `error`, `disclaimer`, `source_url`.

#### NPL/Superfund proximity rollup (per asset)

Classic Phase I ESA metrics, one set of values repeated on every row for that asset (same pattern as `asset_label`/`asset_lat`):

- `nearest_npl_site_name`, `nearest_npl_distance_miles`, `nearest_npl_status` — the closest NPL-lifecycle SEMS site (Final NPL, part-of-listed-site, Proposed, Deleted, or Removed-from-proposed) to the asset. Computed against the asset's **entire state SEMS inventory** (already fetched for the SUPERFUND program — no extra API calls), so it's **not bounded by `radiusMiles`**: a Phase I report conventionally states the nearest NPL site and its distance even when that distance exceeds the search radius. Null when the state has no coordinate-mapped NPL-lifecycle site, or when `SUPERFUND` isn't in `programs`.
- `npl_sites_within_radius` — count of coordinate-mapped NPL-lifecycle sites actually within `radiusMiles`.
- `phase1_esa_flag` — per-asset rollup: true when the asset has any program hit within radius OR any NPL-lifecycle site within radius. Check any one row for this asset to know if it needs a closer look.
- `phase1_summary` — one-line plain-English rollup, e.g. `1 EPA-listed site(s) within 1 mi (SUPERFUND); 1 NPL-track site(s) within 1 mi; nearest NPL-track site: "BRODERICK WOOD PRODUCTS" 0.05 mi (Final NPL).`

Caveat: only ~10–15% of SEMS/Superfund records nationwide carry coordinates, so `nearest_npl_*` and `npl_sites_within_radius` can only rank/count the coordinate-mapped subset — an un-geocoded NPL site in the same county won't surface here.

#### ASTM E1527-21 search distances (`astmMode`, assets mode)

Built for **Phase I ESA consultants** who need a quick pre-check against the ASTM E1527-21 "Standard Environmental Record Sources & Search Distances" table (Sec. 8.2.1) before ordering (or while scoping) the formal records review. Set `astmMode: true` and the actor emits **one extra row per asset**, after its normal listing/clear rows, with `row_type: "astm_summary"`:

```json
{
  "mode": "assets",
  "assets": [{ "lat": 39.8037, "lon": -104.9986, "state": "CO", "label": "Denver warehouse" }],
  "radiusMiles": 1,
  "astmMode": true
}
```

The summary row carries:

- `row_type` — `"astm_summary"` (null on every other row type).
- `astm_effective_radius_miles` — the radius actually fetched for the summary: `max(radiusMiles, 1.0)`, since ASTM's widest standard search distance (NPL) is 1 mile. This only widens what's fetched for the summary — your normal hit/clear rows still respect `radiusMiles` exactly as before.
- `astm_databases` — an object keyed by database, one entry per program you screened (this actor's programs mapped to the ASTM table below), each with `required_radius_mi`, `hits_within_required_radius`, `nearest_distance_mi`, and `astm_flag`.
- `astm_overall_verdict` — `"REC potential — hits within ASTM search distances"` if any database has a hit inside its required radius, else `"No mapped hits within ASTM search distances"`.
- `astm_disclaimer` — the standard advisory (see FAQ below).

**The mapping used** (this actor's programs -> ASTM E1527-21 Sec. 8.2.1 search distances):

| ASTM database (`astm_databases` key) | Required search radius | This actor's program |
|---|---|---|
| NPL (Superfund, Final) | 1.0 mi | `SUPERFUND` (on\_npl = true) |
| Delisted NPL / SEMS-CERCLIS (non-NPL) | 0.5 mi | `SUPERFUND` (on\_npl = false) |
| RCRA CORRACTS/TSD & LQG/SQG generators | 1.0 mi (conservative) | `RCRA` |
| LUST | 0.5 mi | `LUST` |
| UST (registered) | 0.25 mi | `UST` |
| Brownfields / institutional controls | 0.5 mi | `BROWNFIELD` |

`TRI` is not one of ASTM's standard regulatory record sources, so it never gets an `astm_databases` entry even if you screen it. RCRA's ASTM table actually has two line items (CORRACTS/TSD facilities at 1.0 mi vs. LQG/SQG generators at 0.25 mi) — EPA ECHO's `RCRAFlag` doesn't expose which one applies to a given facility, so this actor conservatively uses the wider 1.0 mi radius for every RCRA hit rather than guess.

Inventory-mode rows use a separate field set (`epa_id`, `npl_status_code`/`npl_status_name`, `is_superfund`, `federal_facility`, `archived`, `lat`/`lon`, etc.).

### Caveats worth knowing

- This is a screening aid, not a Phase I ESA. It does not replace a licensed environmental professional's records search — use it to triage, then order the real report on flagged properties.
- Coverage and geocoding vary by program. Roughly 85–90% of SEMS/Superfund records nationwide have no coordinates (old archived/NFRAP sites) and can't be distance-screened, so a `clear` result means "no geocoded listing within radius," not a guarantee of no history. Use inventory mode with `onlyWithCoords: false` to see the full raw SEMS roster.
- `distance_miles` is measured to a database point (often a parcel centroid or address match), not a property boundary, so treat it as approximate.
- `nearest_npl_*` is the closest coordinate-mapped NPL-lifecycle SEMS site state-wide, not capped by `radiusMiles` — that's intentional (matches how a Phase I report states the nearest NPL site even beyond the search radius), but it means a very "far" nearest-NPL distance in a low-density state is normal, not a bug.

### Pair it with state tank & spill registries

Federal EPA data is only half a Phase I records search. The companion [State UST, LUST & Spill Registry Screener](https://apify.com/malonestar/state-tank-spill-registry-screener) screens the same coordinates against state-level registries — NY DEC Spills and California GeoTracker cleanup cases (LUST, military UST, land disposal) — with case status, contaminant, and an open-case flag. Run both on a portfolio for federal + state coverage in one pass.

### Use as an MCP tool

A Pay-Per-Result API discoverable to AI agents through mcp.apify.com. Hand an agent an address or a list of properties and it gets back structured multi-program environmental-risk hits, with no scraping or manual EPA lookups.

### FAQ

**Which databases does it search?** Superfund/NPL, RCRA, TRI, UST, LUST, and Brownfields/ACRES — pick a subset via `programs` or leave it empty for all six.

**Does this replace a Phase I ESA?** No. It is a pre-screen; order a licensed Phase I ESA for anything flagged.

**Can I screen a whole portfolio at once?** Yes — pass as many items as you want in `assets`; each site hit is one row.

**What are the ASTM E1527 search distances?** ASTM E1527-21 (Sec. 8.2.1) sets a standard minimum radius per regulatory database that a Phase I ESA records review must cover — e.g. 1.0 mile for NPL/Superfund, 0.5 mile for LUST, 0.25 mile for UST. Set `astmMode: true` to get a per-asset summary row scoring this actor's databases against those distances.

**Does this satisfy an ASTM E1527 records review?** No. `astmMode` is a screening aid that approximates the standard's search-distance table against this actor's six EPA databases — it is not an ASTM E1527-21 Phase I Environmental Site Assessment and does not by itself satisfy the standard's records-review requirement. Order a licensed Phase I ESA from an Environmental Professional for anything flagged.

**How is billing calculated?** One dataset row per site hit (assets mode, including the optional `astm_summary` row when `astmMode` is on) or per SEMS site (inventory mode).

# Actor input Schema

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

"assets" (default) runs a multi-database Phase I ESA-style regulatory-records screen on your addresses/coordinates — one billable row per nearby EPA-listed site (across Superfund, RCRA, TRI, UST, LUST and Brownfields). "inventory" instead dumps the raw list of EPA SEMS/Superfund sites for the states you pick — one billable row per site.

## `assets` (type: `array`):

Locations to screen against EPA contaminated-site databases. Each item is EITHER {"address": "...", "label": "..."} (geocoded via the free Census geocoder) OR {"lat": <number>, "lon": <number>, "state": "<2-letter, required with lat/lon>", "label": "..."}. One dataset row (one billable check) is produced per site hit found within the radius; assets with no hits still return a single "clear" row. Bad input (unreadable address, missing state, out-of-range coordinates) yields an "error" row instead of failing the run.

## `radiusMiles` (type: `integer`):

Distance from each asset within which EPA-listed sites are counted and reported across all selected programs. Default 1 mile follows the ASTM E1527 Phase I ESA approximate minimum search-distance convention for NPL/Superfund sites (nearer thresholds apply to RCRA/UST/LUST in a full report). Console accepts 1-50 whole miles; fractional radii down to 0.1 are accepted via the API.

## `programs` (type: `array`):

Which EPA program databases to include. Any of: SUPERFUND (NPL/SEMS), RCRA (hazardous-waste handlers/corrective action), TRI (Toxic Release Inventory), UST (underground storage tanks), LUST (leaking USTs), BROWNFIELD (ACRES/FRS). Leave empty to screen ALL six. Ignored in inventory mode (which is SEMS/Superfund only).

## `maxHitsPerProgram` (type: `integer`):

Assets mode only: cap on the number of nearest site hits reported per program per asset (keeps output and billing bounded near dense industrial areas). The nearest sites are kept. Default 50. Range 1-1000.

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

2-letter US state codes (e.g. \["CO", "NJ"]) whose EPA SEMS/Superfund site records to list. Required when Mode = inventory. Ignored in assets mode (state is derived automatically per-asset).

## `onlyNpl` (type: `boolean`):

Inventory mode only: when true, keep only sites currently on (or part of) the National Priorities List — the actual Superfund program sites. When false, include all SEMS site statuses. Default false.

## `onlyWithCoords` (type: `boolean`):

Inventory mode only: when true (recommended, default), drop SEMS records with no latitude/longitude — roughly 85-90% of records nationwide, mostly old archived/NFRAP sites never geocoded. Set false to see the full raw roster including un-mappable rows.

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

Safety cap on total dataset rows produced across the run: max site hits emitted (assets mode) or max SEMS site rows (inventory mode).

## `astmMode` (type: `boolean`):

Assets mode only. When true, adds ONE extra 'astm\_summary' row after each asset's normal listing/clear rows, applying the ASTM E1527-21 standard search distances (NPL 1.0 mi, delisted-NPL/SEMS-CERCLIS 0.5 mi, RCRA 1.0 mi, LUST 0.5 mi, UST 0.25 mi, Brownfields 0.5 mi — TRI has no ASTM search distance and is excluded) per selected program, with a nearest-distance and REC-potential verdict. Automatically widens the underlying data fetch to 1 mile so the summary sees hits beyond a smaller radiusMiles; your normal per-hit rows still respect radiusMiles unchanged. Screening aid only — not a substitute for an ASTM E1527-21 Phase I ESA. Default false (no summary rows, output unchanged).

## Actor input object example

```json
{
  "mode": "assets",
  "assets": [
    {
      "lat": 39.8037,
      "lon": -104.9986,
      "state": "CO",
      "label": "Denver industrial parcel (lat/lon input)"
    },
    {
      "address": "5980 Lipan St, Denver, CO 80221",
      "label": "Denver industrial parcel (address input)"
    }
  ],
  "radiusMiles": 1,
  "programs": [
    "SUPERFUND",
    "RCRA",
    "TRI",
    "UST",
    "LUST",
    "BROWNFIELD"
  ],
  "maxHitsPerProgram": 50,
  "onlyNpl": false,
  "onlyWithCoords": true,
  "maxResults": 1000,
  "astmMode": true
}
```

# Actor output Schema

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

The default dataset with one row per site hit or SEMS site.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "assets",
    "assets": [
        {
            "lat": 39.8037,
            "lon": -104.9986,
            "state": "CO",
            "label": "Denver industrial parcel (lat/lon input)"
        },
        {
            "address": "5980 Lipan St, Denver, CO 80221",
            "label": "Denver industrial parcel (address input)"
        }
    ],
    "radiusMiles": 1,
    "programs": [
        "SUPERFUND",
        "RCRA",
        "TRI",
        "UST",
        "LUST",
        "BROWNFIELD"
    ],
    "maxHitsPerProgram": 50,
    "onlyWithCoords": true,
    "astmMode": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("malonestar/epa-contaminated-site-screener").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "assets",
    "assets": [
        {
            "lat": 39.8037,
            "lon": -104.9986,
            "state": "CO",
            "label": "Denver industrial parcel (lat/lon input)",
        },
        {
            "address": "5980 Lipan St, Denver, CO 80221",
            "label": "Denver industrial parcel (address input)",
        },
    ],
    "radiusMiles": 1,
    "programs": [
        "SUPERFUND",
        "RCRA",
        "TRI",
        "UST",
        "LUST",
        "BROWNFIELD",
    ],
    "maxHitsPerProgram": 50,
    "onlyWithCoords": True,
    "astmMode": True,
}

# Run the Actor and wait for it to finish
run = client.actor("malonestar/epa-contaminated-site-screener").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 '{
  "mode": "assets",
  "assets": [
    {
      "lat": 39.8037,
      "lon": -104.9986,
      "state": "CO",
      "label": "Denver industrial parcel (lat/lon input)"
    },
    {
      "address": "5980 Lipan St, Denver, CO 80221",
      "label": "Denver industrial parcel (address input)"
    }
  ],
  "radiusMiles": 1,
  "programs": [
    "SUPERFUND",
    "RCRA",
    "TRI",
    "UST",
    "LUST",
    "BROWNFIELD"
  ],
  "maxHitsPerProgram": 50,
  "onlyWithCoords": true,
  "astmMode": true
}' |
apify call malonestar/epa-contaminated-site-screener --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=malonestar/epa-contaminated-site-screener",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "EPA Contaminated Site Screener — Superfund/NPL Proximity Check",
        "description": "Multi-database Phase I ESA regulatory-records screen. Screen a US address or coordinate for nearby EPA sites across Superfund/NPL, RCRA, TRI, UST, LUST, Brownfields, plus optional ASTM E1527-21 search-distance verdicts. Keyless EPA Envirofacts + ECHO + ArcGIS + Census geocoder.",
        "version": "1.0",
        "x-build-id": "4maG5FC1xkwzJc0Le"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/malonestar~epa-contaminated-site-screener/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-malonestar-epa-contaminated-site-screener",
                "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/malonestar~epa-contaminated-site-screener/runs": {
            "post": {
                "operationId": "runs-sync-malonestar-epa-contaminated-site-screener",
                "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/malonestar~epa-contaminated-site-screener/run-sync": {
            "post": {
                "operationId": "run-sync-malonestar-epa-contaminated-site-screener",
                "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": [
                            "assets",
                            "inventory"
                        ],
                        "type": "string",
                        "description": "\"assets\" (default) runs a multi-database Phase I ESA-style regulatory-records screen on your addresses/coordinates — one billable row per nearby EPA-listed site (across Superfund, RCRA, TRI, UST, LUST and Brownfields). \"inventory\" instead dumps the raw list of EPA SEMS/Superfund sites for the states you pick — one billable row per site.",
                        "default": "assets"
                    },
                    "assets": {
                        "title": "Assets to screen (assets mode)",
                        "type": "array",
                        "description": "Locations to screen against EPA contaminated-site databases. Each item is EITHER {\"address\": \"...\", \"label\": \"...\"} (geocoded via the free Census geocoder) OR {\"lat\": <number>, \"lon\": <number>, \"state\": \"<2-letter, required with lat/lon>\", \"label\": \"...\"}. One dataset row (one billable check) is produced per site hit found within the radius; assets with no hits still return a single \"clear\" row. Bad input (unreadable address, missing state, out-of-range coordinates) yields an \"error\" row instead of failing the run."
                    },
                    "radiusMiles": {
                        "title": "Screening radius (miles)",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Distance from each asset within which EPA-listed sites are counted and reported across all selected programs. Default 1 mile follows the ASTM E1527 Phase I ESA approximate minimum search-distance convention for NPL/Superfund sites (nearer thresholds apply to RCRA/UST/LUST in a full report). Console accepts 1-50 whole miles; fractional radii down to 0.1 are accepted via the API.",
                        "default": 1
                    },
                    "programs": {
                        "title": "Programs / databases to screen (assets mode)",
                        "type": "array",
                        "description": "Which EPA program databases to include. Any of: SUPERFUND (NPL/SEMS), RCRA (hazardous-waste handlers/corrective action), TRI (Toxic Release Inventory), UST (underground storage tanks), LUST (leaking USTs), BROWNFIELD (ACRES/FRS). Leave empty to screen ALL six. Ignored in inventory mode (which is SEMS/Superfund only).",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxHitsPerProgram": {
                        "title": "Max hits per program per asset",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Assets mode only: cap on the number of nearest site hits reported per program per asset (keeps output and billing bounded near dense industrial areas). The nearest sites are kept. Default 50. Range 1-1000.",
                        "default": 50
                    },
                    "states": {
                        "title": "States (inventory mode)",
                        "type": "array",
                        "description": "2-letter US state codes (e.g. [\"CO\", \"NJ\"]) whose EPA SEMS/Superfund site records to list. Required when Mode = inventory. Ignored in assets mode (state is derived automatically per-asset).",
                        "items": {
                            "type": "string"
                        }
                    },
                    "onlyNpl": {
                        "title": "Only NPL/Superfund sites (inventory mode)",
                        "type": "boolean",
                        "description": "Inventory mode only: when true, keep only sites currently on (or part of) the National Priorities List — the actual Superfund program sites. When false, include all SEMS site statuses. Default false.",
                        "default": false
                    },
                    "onlyWithCoords": {
                        "title": "Only sites with coordinates (inventory mode)",
                        "type": "boolean",
                        "description": "Inventory mode only: when true (recommended, default), drop SEMS records with no latitude/longitude — roughly 85-90% of records nationwide, mostly old archived/NFRAP sites never geocoded. Set false to see the full raw roster including un-mappable rows.",
                        "default": true
                    },
                    "maxResults": {
                        "title": "Max results",
                        "minimum": 1,
                        "maximum": 20000,
                        "type": "integer",
                        "description": "Safety cap on total dataset rows produced across the run: max site hits emitted (assets mode) or max SEMS site rows (inventory mode).",
                        "default": 1000
                    },
                    "astmMode": {
                        "title": "ASTM E1527-21 search-distance summary (assets mode)",
                        "type": "boolean",
                        "description": "Assets mode only. When true, adds ONE extra 'astm_summary' row after each asset's normal listing/clear rows, applying the ASTM E1527-21 standard search distances (NPL 1.0 mi, delisted-NPL/SEMS-CERCLIS 0.5 mi, RCRA 1.0 mi, LUST 0.5 mi, UST 0.25 mi, Brownfields 0.5 mi — TRI has no ASTM search distance and is excluded) per selected program, with a nearest-distance and REC-potential verdict. Automatically widens the underlying data fetch to 1 mile so the summary sees hits beyond a smaller radiusMiles; your normal per-hit rows still respect radiusMiles unchanged. Screening aid only — not a substitute for an ASTM E1527-21 Phase I ESA. Default false (no summary rows, output unchanged).",
                        "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
