# Storm Hail Damage Leads — NOAA Reports to Affected Addresses (`industrious_emphasis/storm-hail-lead-finder`) Actor

Turns NOAA SPC hail reports into a deduplicated list of street addresses inside each hail swath buffer. Built for roofing lead gen, storm-marketing agencies, and AI agents.

- **URL**: https://apify.com/industrious\_emphasis/storm-hail-lead-finder.md
- **Developed by:** [Brock Bangasser](https://apify.com/industrious_emphasis) (community)
- **Categories:** Lead generation, Real estate
- **Stats:** 4 total users, 2 monthly users, 85.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $15.00 / 1,000 affected address returneds

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

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

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

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

## Storm Hail Damage Leads — NOAA Hail Reports → Affected Street Addresses

Turn yesterday's hailstorm into today's canvassing list. This Actor pulls official **NOAA Storm Prediction Center hail reports**, buffers each report point, and returns a **deduplicated list of street addresses inside the impact zone** — with hail size, distance from the report, county, and timestamps on every row. JSON, CSV, or Excel out; run it on a schedule or call it from your CRM, workflow tool, or AI agent.

Built for **roofing contractors, storm-restoration marketers, exterior-cleaning and auto-hail (PDR) companies, direct-mail houses, and proptech/insurtech developers** who need raw, programmatic storm-impact data — not another $100+/month dashboard subscription.

### Why this instead of a hail-map subscription?

| | Hail map SaaS (HailTrace, HailWatch, Hail Recon…) | This Actor |
|---|---|---|
| Pricing | $65–$119+/month subscriptions; single storm maps sold for ~$230 | Pay per use — a typical full run costs a few dollars |
| Access | Dashboard + sales call for data exports | API-first: schedule it, pipe it to Sheets/CRM/webhooks, call it from code or AI agents |
| Output | Maps you look at | Structured address rows you act on |
| Commitment | Annual/monthly plans | None. Run it after a storm, skip quiet weeks |

Those platforms are excellent at what they do (meteorologist-verified swath maps). This Actor is the **unbundled, programmatic slice**: official public data, straight to rows, priced per result.

### Coverage — United States (for now)

Hail events come from NOAA's Storm Prediction Center, so this Actor covers the **contiguous United States**. Filter with US state codes (`TX`, `MN`, …); a storm outside the US won't appear, because it isn't in the SPC feed.

Only the **hail-report source** is US-bound — the address lookup is global. Adding a country means bolting its severe-weather feed onto the same buffer/dedup/address pipeline: Canada (Environment and Climate Change Canada), Europe (ESWD), Australia (Bureau of Meteorology). On the roadmap; paid demand moves a region up the list.

### What you get

Each **address row**:

```json
{
  "type": "address",
  "address": "1234 Main Street, Example City 75001",
  "house_number": "1234",
  "street": "Main Street",
  "city": "Example City",
  "postcode": "75001",
  "address_lat": 32.7810,
  "address_lon": -96.8010,
  "distance_miles": 0.42,
  "hail_size_in": 1.75,
  "event_id": "20260706-2005-32.78--96.80",
  "event_date": "2026-07-06",
  "event_time_utc": "2005",
  "event_location": "4 W EXAMPLE CITY",
  "county": "EXAMPLE",
  "state": "TX",
  "event_lat": 32.78,
  "event_lon": -96.80,
  "event_comments": "Golf ball sized hail reported by trained spotter. (XXX)",
  "address_source": "osm"
}
````

Plus one **event\_summary row per hail report** (size, location, time, how many addresses were found) — so `addressSource: "none"` gives you a cheap storm-monitoring feed on its own. Every run also ends with a single free **run\_summary row**: a receipt of what was checked and found, so "no hail matched your filter" is an explicit answer, never an empty table.

Addresses are **deduplicated across overlapping reports**: each address appears once, tagged with the largest hail size that hit it and the shortest distance. Results are sorted biggest-hail-first, so caps keep the highest-value leads.

### How to use it

1. Pick the day(s): `today` (live-updating), `yesterday` (most recent complete day — the default), `last3days`, or a custom `dateRange`.
2. Filter: `states` (e.g. `["TX","OK"]`), `minHailSizeInches` (default 1.0 — quarter-size, the usual roof-damage threshold), `radiusMiles` buffer (default 1.5).
3. Control spend: `maxReports` and `maxAddresses` hard-cap what a run can bill.
4. Run once from the console, or **schedule it daily during storm season** and connect the dataset to Google Sheets, your CRM, Make/Zapier/n8n, or a webhook.

#### Common recipes

- **"Who got hit in my state yesterday?"** — `dateMode: yesterday`, `states: ["TX"]` (swap in your own), defaults elsewhere.
- **Daily storm-season monitor (cheap):** schedule with `addressSource: "none"`; alert your team when `event_summary` rows appear, then re-run with addresses for the events you care about.
- **Direct-mail batch:** `minHailSizeInches: 1.25`, `radiusMiles: 2`, `maxAddresses: 5000`, export CSV to your mail house.
- **Storm-day damage sweep for a metro:** `dateRange` over the event, one state, `maxReports: 100`.

### Address sources — pick your tradeoff

- **`osm` (default, zero setup):** queries OpenStreetMap's Overpass API around each report. Works instantly, no keys. Coverage is strong in most metros and suburbs, thinner in some rural counties — where OSM lacks address points, you'll get fewer rows (you're never billed for rows you don't get).
- **`openaddresses_grid` (scale mode):** near-complete government-sourced address coverage. One-time setup: shard a free OpenAddresses export with the included script and host the shards on S3/any static host, then set `openAddressesBaseUrl`. Runs then fetch only the few grid cells intersecting the storm buffer.
- **`none`:** events only — the monitoring feed.

### Input reference & common mistakes

You don't need to get this perfect. Wrong-but-unambiguous values are fixed for you (and noted in the log); genuinely ambiguous ones make the run finish with a **receipt that tells you what to change** — never a blank failure. Every run ends with a `run_summary` row, so "nothing happened" is always explained.

| Field | Accepts | If you get it wrong |
|---|---|---|
| `dateMode` | `today`, `yesterday`, `last3days`, `dateRange` | Unknown/misspelled → receipt lists the valid options |
| `startDate`, `endDate` | `YYYY-MM-DD`, and only with `dateRange` | Missing, impossible (`2026-02-30`), reversed, or range >31 days → receipt explains the fix. Reversed dates are auto-swapped |
| `states` | 2-letter US codes: `TX`, `FL`. A list `["TX","OK"]` or a string `"tx, ok"` | Lowercase is auto-uppercased; full names (`Texas`) and typos (`ZZ`) are dropped with a warning; **empty = all states** |
| `minHailSizeInches` | `0.25`–`6.0` (1.0 = quarter, 1.75 = golf ball) | Out of range is clamped; non-numeric falls back to `1.0` — both logged |
| `radiusMiles` | `0.1`–`10` | Clamped / defaulted to `1.5`, logged |
| `maxReports` | `1`–`500` | Clamped / defaulted to `25`, logged |
| `maxAddresses` | `1`–`100000` | Clamped / defaulted to `500`, logged |
| `maxRuntimeSeconds` | `0`–`3600` (`0` = no limit) | If the budget is hit, the run returns partial results plus a note telling you to raise it |
| `addressSource` | `osm`, `openaddresses_grid`, `none` | Unknown/misspelled (`OSM`, `openstreetmap`) → receipt lists valid options |
| `openAddressesBaseUrl` | public `http(s)` URL — required only for `openaddresses_grid` | Missing in grid mode, or an unsafe/internal/malformed URL → receipt explains |
| `overpassEndpoint` | public `http(s)` URL | Internal/loopback/malformed URLs are refused with a message (SSRF guard) |
| `overpassDelaySeconds` | `0`–`30` | Clamped / defaulted to `2`, logged |
| `contactEmail` | a plain email address | Control characters are stripped automatically; never fatal |

**Quickest correct first run:** set `dateMode` to `yesterday`, leave everything else at its default.

### Honest notes on the data (read this)

- **SPC reports are point observations** (spotters, trained observers, emergency management), not radar-derived swaths. The `radiusMiles` buffer approximates the damage area around each confirmed report; it will not trace the exact swath shape the way meteorologist-drawn maps do. Roadmap: NOAA MRMS **MESH** radar hail-size grids for true swath polygons.
- **"Today" fills in over hours** — reports trickle in during and after the storm. For complete data, run `yesterday`. SPC convective days run 12:00 UTC to 12:00 UTC.
- **No hit guarantee:** a report of 1.75" hail plus a 1.5-mile buffer means damage is *likely* nearby, not certain at any specific address.
- **No personal data.** Output is addresses and public storm data only — no owner names, phones, or emails. Pair with your own compliant enrichment/outreach stack and follow the laws that apply to you (e.g., TCPA for calls/texts, CAN-SPAM for email, local door-knocking rules).
- **Sources & terms:** NOAA/SPC data is US-government public domain. OpenStreetMap data © OpenStreetMap contributors, ODbL — if you redistribute OSM-derived rows, attribution applies. OpenAddresses data carries per-source licenses (most permissive; check your state's sources).
- **Hardened by design:** user-supplied endpoints are validated (http/https only, internal/metadata hosts refused), all downloads are size-capped with zip-bomb protection, URLs are redacted in logs, and every run's spend is bounded by `maxReports`/`maxAddresses`. No logins, no CAPTCHAs, no personal data — just public endpoints used as intended.

### Pricing

Pay-per-event: a flat actor start ($0.02) + per hail event analyzed ($0.002) + per address returned ($15/1,000). Worked example: 25 events, 500 addresses → **about $7.57 for a ready-to-work storm lead list.** One storm map from the leading SaaS costs ~$230; one retail roofing lead costs $80–$220. Failed runs aren't charged, and `maxAddresses` caps every run's spend.

### FAQ

**Is this legal?** The Actor reads official public government data (NOAA/SPC) and openly licensed address datasets via their intended public endpoints. No logins, no CAPTCHAs, no personal data.

**Why did an event return zero addresses?** Rural report with sparse OSM coverage, or the buffer landed on farmland. Try `openaddresses_grid` mode or a larger radius.

**Can my AI agent call this?** Yes — every published Apify Actor is callable via API and exposed through Apify's MCP server, so agents can run it and read the dataset directly.

**Can you add wind/tornado reports, MESH swaths, or owner-occupancy flags?** That's the roadmap. Open an issue on the Actor page — paid usage moves features up the list.

# Actor input Schema

## `dateMode` (type: `string`):

The only required choice. Pick a preset, or pick 'Custom date range' and fill in the two date fields below (they are ignored otherwise). Note: NOAA 'convective days' run 12:00 UTC to 12:00 UTC, and 'Today' is still filling in — 'Yesterday' is the most recent complete day.

## `startDate` (type: `string`):

Ignored unless 'Which storm day(s)' above is set to 'Custom date range'. Format YYYY-MM-DD. Max 31 days per run.

## `endDate` (type: `string`):

Ignored unless 'Which storm day(s)' above is set to 'Custom date range'. Format YYYY-MM-DD.

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

Optional. 2-letter US state codes like TX, FL, OK. Leave empty to include every state — recommended for a first run so you always see live data.

## `minHailSizeInches` (type: `number`):

Optional, default 1.0 (quarter size — the typical roof-damage threshold). 1.75 = golf ball. Lower it for more, weaker events.

## `radiusMiles` (type: `number`):

Optional, default 1.5. Addresses within this distance of each hail report are returned. 1-2 miles is sensible; max 10.

## `maxReports` (type: `integer`):

Optional, default 25. Biggest hail is processed first, so a low cap keeps the most damaging events. This is your cost control on big storm days.

## `maxAddresses` (type: `integer`):

Optional, default 500. Hard cap on billed address rows for the whole run.

## `addressSource` (type: `string`):

Default (OpenStreetMap) needs zero setup. 'OpenAddresses grid' is for operators hosting their own pre-sharded address data (see README). 'Events only' skips addresses entirely — cheap storm monitoring.

## `openAddressesBaseUrl` (type: `string`):

Required only when Address source is 'OpenAddresses grid'; ignored otherwise. Public base URL of shards produced by scripts/preprocess\_openaddresses.py (see README).

## `overpassEndpoint` (type: `string`):

Leave the default unless you run your own OpenStreetMap Overpass server or prefer a specific mirror.

## `overpassDelaySeconds` (type: `number`):

Politeness delay for the shared public endpoint, default 2. Only lower it on a private endpoint.

## `maxRuntimeSeconds` (type: `integer`):

Optional, default 270. Address lookups stop after this many seconds and the run returns what it has (a partial list beats a timed-out, failed run). Raise it — or set 0 for no limit — for large multi-state runs where you want every address.

## `contactEmail` (type: `string`):

Added to the HTTP User-Agent per OpenStreetMap etiquette so operators can reach you instead of blocking you. Recommended if you schedule frequent runs.

## Actor input object example

```json
{
  "dateMode": "yesterday",
  "states": [],
  "minHailSizeInches": 1,
  "radiusMiles": 1.5,
  "maxReports": 5,
  "maxAddresses": 100,
  "addressSource": "osm",
  "overpassEndpoint": "https://overpass-api.de/api/interpreter",
  "overpassDelaySeconds": 1,
  "maxRuntimeSeconds": 270
}
```

# Actor output Schema

## `leads` (type: `string`):

No description

## `leadsCsv` (type: `string`):

No description

# API

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

## JavaScript example

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

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

// Prepare Actor input
const input = {
    "dateMode": "yesterday",
    "maxReports": 5,
    "maxAddresses": 100,
    "overpassDelaySeconds": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("industrious_emphasis/storm-hail-lead-finder").call(input);

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

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

```

## Python example

```python
from apify_client import ApifyClient

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

# Prepare the Actor input
run_input = {
    "dateMode": "yesterday",
    "maxReports": 5,
    "maxAddresses": 100,
    "overpassDelaySeconds": 1,
}

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

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

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

```

## CLI example

```bash
echo '{
  "dateMode": "yesterday",
  "maxReports": 5,
  "maxAddresses": 100,
  "overpassDelaySeconds": 1
}' |
apify call industrious_emphasis/storm-hail-lead-finder --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Storm Hail Damage Leads — NOAA Reports to Affected Addresses",
        "description": "Turns NOAA SPC hail reports into a deduplicated list of street addresses inside each hail swath buffer. Built for roofing lead gen, storm-marketing agencies, and AI agents.",
        "version": "0.1",
        "x-build-id": "VfaSwA9E5xB6hqeUI"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/industrious_emphasis~storm-hail-lead-finder/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-industrious_emphasis-storm-hail-lead-finder",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/industrious_emphasis~storm-hail-lead-finder/runs": {
            "post": {
                "operationId": "runs-sync-industrious_emphasis-storm-hail-lead-finder",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/industrious_emphasis~storm-hail-lead-finder/run-sync": {
            "post": {
                "operationId": "run-sync-industrious_emphasis-storm-hail-lead-finder",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "dateMode"
                ],
                "properties": {
                    "dateMode": {
                        "title": "Which storm day(s)",
                        "enum": [
                            "today",
                            "yesterday",
                            "last3days",
                            "dateRange"
                        ],
                        "type": "string",
                        "description": "The only required choice. Pick a preset, or pick 'Custom date range' and fill in the two date fields below (they are ignored otherwise). Note: NOAA 'convective days' run 12:00 UTC to 12:00 UTC, and 'Today' is still filling in — 'Yesterday' is the most recent complete day.",
                        "default": "yesterday"
                    },
                    "startDate": {
                        "title": "Start date — only used with 'Custom date range'",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                        "type": "string",
                        "description": "Ignored unless 'Which storm day(s)' above is set to 'Custom date range'. Format YYYY-MM-DD. Max 31 days per run."
                    },
                    "endDate": {
                        "title": "End date — only used with 'Custom date range'",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                        "type": "string",
                        "description": "Ignored unless 'Which storm day(s)' above is set to 'Custom date range'. Format YYYY-MM-DD."
                    },
                    "states": {
                        "title": "States filter (optional)",
                        "type": "array",
                        "description": "Optional. 2-letter US state codes like TX, FL, OK. Leave empty to include every state — recommended for a first run so you always see live data.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "minHailSizeInches": {
                        "title": "Minimum hail size (inches)",
                        "minimum": 0.25,
                        "maximum": 6,
                        "type": "number",
                        "description": "Optional, default 1.0 (quarter size — the typical roof-damage threshold). 1.75 = golf ball. Lower it for more, weaker events.",
                        "default": 1
                    },
                    "radiusMiles": {
                        "title": "Address search radius around each hail report (miles)",
                        "minimum": 0.1,
                        "maximum": 10,
                        "type": "number",
                        "description": "Optional, default 1.5. Addresses within this distance of each hail report are returned. 1-2 miles is sensible; max 10.",
                        "default": 1.5
                    },
                    "maxReports": {
                        "title": "Spend cap: max hail events to process",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Optional, default 25. Biggest hail is processed first, so a low cap keeps the most damaging events. This is your cost control on big storm days.",
                        "default": 25
                    },
                    "maxAddresses": {
                        "title": "Spend cap: max addresses to return",
                        "minimum": 1,
                        "maximum": 100000,
                        "type": "integer",
                        "description": "Optional, default 500. Hard cap on billed address rows for the whole run.",
                        "default": 500
                    },
                    "addressSource": {
                        "title": "Address source",
                        "enum": [
                            "osm",
                            "openaddresses_grid",
                            "none"
                        ],
                        "type": "string",
                        "description": "Default (OpenStreetMap) needs zero setup. 'OpenAddresses grid' is for operators hosting their own pre-sharded address data (see README). 'Events only' skips addresses entirely — cheap storm monitoring.",
                        "default": "osm"
                    },
                    "openAddressesBaseUrl": {
                        "title": "OpenAddresses shard base URL — only for 'OpenAddresses grid'",
                        "type": "string",
                        "description": "Required only when Address source is 'OpenAddresses grid'; ignored otherwise. Public base URL of shards produced by scripts/preprocess_openaddresses.py (see README)."
                    },
                    "overpassEndpoint": {
                        "title": "Overpass endpoint (optional)",
                        "type": "string",
                        "description": "Leave the default unless you run your own OpenStreetMap Overpass server or prefer a specific mirror.",
                        "default": "https://overpass-api.de/api/interpreter"
                    },
                    "overpassDelaySeconds": {
                        "title": "Delay between Overpass queries in seconds (optional)",
                        "minimum": 0,
                        "maximum": 30,
                        "type": "number",
                        "description": "Politeness delay for the shared public endpoint, default 2. Only lower it on a private endpoint.",
                        "default": 2
                    },
                    "maxRuntimeSeconds": {
                        "title": "Runtime budget for address lookups (seconds)",
                        "minimum": 0,
                        "maximum": 3600,
                        "type": "integer",
                        "description": "Optional, default 270. Address lookups stop after this many seconds and the run returns what it has (a partial list beats a timed-out, failed run). Raise it — or set 0 for no limit — for large multi-state runs where you want every address.",
                        "default": 270
                    },
                    "contactEmail": {
                        "title": "Contact email (optional)",
                        "type": "string",
                        "description": "Added to the HTTP User-Agent per OpenStreetMap etiquette so operators can reach you instead of blocking you. Recommended if you schedule frequent runs."
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
