# US Building Permits Scraper - Contractor Leads, Verified Cities (`permitdata/us-building-permits-scraper`) Actor

Contractor leads from building permits: roofing, HVAC, solar, electrical, plumbing, remodel & new construction, classified by trade and lead-scored. 16 verified city feeds checked daily; contractor names, owner names, valuations, phones where published. From $3/1,000, source-direct government data.

- **URL**: https://apify.com/permitdata/us-building-permits-scraper.md
- **Developed by:** [PermitData](https://apify.com/permitdata) (community)
- **Categories:** Lead generation, Real estate, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 permits

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

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

## What's an Apify Actor?

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

## How to integrate an Actor?

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

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

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

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


# README

## US Building Permits Scraper: Contractor Leads from 16 Verified Cities

Turn building permits into **contractor leads**. Every permit comes straight from 16
cities' official open-data APIs, normalized to one schema, classified by trade (roofing,
HVAC, solar, electrical, plumbing, pool & spa, demolition, remodel, new construction) and
lead-scored so sales teams work the hottest jobs first. Monitor mode turns it into a daily
permit alert feed for schedules and webhooks. No proxies, no fragile HTML scraping, no
reseller feed. Government APIs only.

### Which lead list do you want?

| Lead list | How to get it |
| --- | --- |
| **Roofing leads** (storm chasers, re-roof jobs) | `trades: ["roofing"]` |
| **HVAC leads** | `trades: ["hvac"]` |
| **Solar leads** (who's installing, which contractors win) | `trades: ["solar"]` |
| **Electrical / plumbing job feed** | `trades: ["electrical", "plumbing"]` |
| **Pool & outdoor-living prospects** | `trades: ["pool_spa", "fence_deck"]` |
| **New construction & remodel activity** (investors, suppliers) | `trades: ["new_construction", "remodel_addition"]` |
| **High-value projects only** | `minValuation: 50000` |
| **Daily new-permit alert feed** | `monitor` mode on an Apify schedule + webhook |

Who uses it: building-product suppliers and distributors selling to contractors (permits
show who's pulling jobs right now), subcontractors prospecting GCs, home-services
companies (a remodel permit predicts follow-on purchases), real-estate investors tracking
construction activity by block, and market researchers measuring construction trends from
primary data.

### Why this one

- **Verified coverage, not claimed coverage.** Every listed city passes an automated
  daily canary check. If a source breaks, it gets flagged here and in your run's health
  report, so you never pay for a silently broken city. Each city shows its last-verified
  date below.
- **One honest schema.** A field that a city doesn't publish is `null`, never guessed.
  The per-city availability matrix below tells you exactly what you'll get before you
  run.
- **Contractor names where cities publish them.** In Austin you also get the
  contractor's phone number, straight from the permit record.
- **Monitor mode.** Run it on a schedule and get only new permits since your last run:
  watermarked, deduplicated, webhook-ready. Ideal for lead-gen pipelines.
- **Health report with every run.** Per-source status, record counts, freshness, and
  latency in the `HEALTH_REPORT` key-value record.
- **Works with AI agents.** Call it via MCP from Claude, Cursor, or any MCP client.

### Coverage

| City | Status | Last verified | Contractor name | Valuation | Geo |
|---|---|---|---|---|---|
| Chicago, IL | ✅ verified | 2026-07-02 | ✅ (by contact type) | ✅ reported cost | ✅ |
| Detroit, MI | ✅ verified | 2026-07-02 | ❌ not published by city | ✅ estimated cost | ✅ |
| Austin, TX | ✅ verified | 2026-07-03 | ✅ **company + name + phone** | ✅ (often null on trade permits) | ✅ |
| New York City, NY | ✅ verified | 2026-07-03 | ⚠️ permittee business (varies) | ✅ estimated cost | ✅ |
| San Francisco, CA | ✅ verified | 2026-07-03 | ❌ not published by city | ✅ revised cost | ❌ (v1) |
| New Orleans, LA | ✅ verified | 2026-07-03 | ❌ not published by city | ✅ est. project cost | ❌ (v1) |
| Cincinnati, OH | ✅ verified | 2026-07-03 | ✅ company name | ✅ est. project cost | ✅ |
| Baton Rouge, LA | ✅ verified | 2026-07-03 | ✅ **contractor + owner** | ✅ project value | ✅ |
| Buffalo, NY | ✅ verified | 2026-07-03 | ✅ applicant/contractor | ✅ value of work | ✅ |
| Montgomery County, MD | ✅ verified | 2026-07-03 | ❌ not published | ✅ declared valuation | ❌ (v1) |
| Seattle, WA | ✅ verified | 2026-07-03 | ❌ not published | ✅ est. project cost | ✅ |
| San Jose, CA | ✅ verified | 2026-07-04 | ✅ **contractor + owner name** | ✅ permit valuation + sq ft | ❌ (address string) |
| Philadelphia, PA (L&I) | ✅ verified | 2026-07-04 | ✅ **contractor + address, owner name** | ❌ not published | ✅ |
| Columbus, OH | ✅ verified | 2026-07-04 | ✅ applicant business name | ✅ total value + sq ft | ❌ (parcel number) |
| Washington, DC | ✅ verified | 2026-07-04 | ✅ **applicant + owner name** | ❌ (fees only) | ✅ |
| Nashville, TN (Metro) | ✅ verified | 2026-07-04 | ✅ permit contact | ✅ construction cost | ✅ |
| More cities | 🔜 rolling out weekly | — | varies | varies | varies |

New cities ship weekly. Want a specific city or county? Open an issue and it goes to
the top of the queue.

### Dodge / ConstructConnect / Construction Monitor alternative?

If you're paying an enterprise construction-data subscription just to see who pulled
permits this week, this Actor covers that slice for pennies:

| | This Actor | Dodge / ConstructConnect / Construction Monitor |
| --- | --- | --- |
| Access | **API-first** (Apify, schedules, webhooks, MCP) | Web portals, sales-led contracts |
| Price | **$0.003/permit, $0.02/scored lead**, no subscription | $100s–$1,000s per month |
| Data path | **Source-direct** city open data, same-day | Aggregated, often delayed |
| Coverage honesty | Per-city matrix + daily verified badge | Opaque |
| Plan rooms, bid docs | ❌ permits only | Included at enterprise prices |

Honest trade-off: this is a permit data feed, not a plan room. If you need bid
documents and project managers' cell numbers, keep the enterprise tool. If you need
fresh permit activity classified by trade, with contractor names where published, this
does it at commodity prices.

### Output schema (one row per permit)

```json
{
  "permit_id": "chicago:B200471904",
  "permit_number": "B200471904",
  "source": "chicago",
  "source_label": "Chicago, IL",
  "state": "IL",
  "issued_date": "2026-05-25",
  "applied_date": "2026-05-25",
  "status_raw": "ACTIVE",
  "permit_type_raw": "PERMIT – EXPRESS PERMIT PROGRAM",
  "work_class_raw": "Electrical Work",
  "trade": "electrical",
  "trades_all": ["electrical"],
  "description": "LINE VOLTAGE ELECTRICAL WORK. ...",
  "address": "77 W WACKER DR",
  "latitude": 41.8867,
  "longitude": -87.6308,
  "valuation": 21200.0,
  "permit_fee": 75.0,
  "contractor_name": "LOMBARDI ELECTRIC, INC.",
  "owner_name": "CORONADO MYRNA",
  "lead_score": 80,
  "scoring_reasons": ["trade:electrical", "valuation:$21,200", "age:5d", "contractor-known"],
  "dedupe_key": "…",
  "first_seen_at": "2026-07-02T14:00:00Z"
}
````

Trades classified: roofing, HVAC/mechanical, electrical, plumbing, solar, demolition,
pool & spa, fence/deck, new construction, remodel/addition, fire systems, signs.
Classification is deterministic keyword matching on the permit type + description.
Reproducible, no LLM randomness.

### Modes

- **Scrape**: pull a date range (`sinceDays` or explicit `sinceDate`/`untilDate`).
- **Monitor**: stateful, emits only permits you haven't seen, with a 3-day overlap
  re-check for late-published records. Point a schedule + webhook at it and you have
  a permit alert feed.
- **Canary**: free self-test of all sources; optionally posts the health summary to
  a Discord webhook. I run it daily myself, you can too.

### How to use

1. Click **Try for free** (first 25 permits are free).
2. Pick `sources` (e.g. `["chicago", "austin"]`) and `trades` (e.g. `["roofing", "hvac"]`).
3. Set `sinceDays: 14` and optionally `minValuation` + `leadScoring: true`.
4. **Save & Start**, then export JSON/CSV/Excel from the Output tab, ready for your CRM.

From Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("permitdata/us-building-permits-scraper").call(run_input={
    "mode": "scrape",
    "sources": ["chicago", "austin"],
    "trades": ["roofing", "hvac", "solar"],
    "sinceDays": 14,
    "leadScoring": True,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(row["lead_score"], row["trade"], row["address"], row.get("contractor_name"))
```

### Pricing

- First **25 permits free** (per account, ever). Try before you buy.
- **$0.003 per permit** (raw normalized record), $3.00 per 1,000.
- **$0.02 per scored lead** when `leadScoring` is on. Replaces the per-permit charge,
  so you're never double-billed for the same row.
- Lead scoring is a documented deterministic heuristic (trade match, valuation bucket,
  recency, contractor identified); see `scoring_reasons` on every row.

Example: a weekly two-city roofing + HVAC pull of ~300 scored leads costs about **$6**.

### FAQ

#### How do I get building permit leads for my city?

If your city is in the coverage table, select it in `sources` and run. If it isn't, open
an issue; cities with open data get added quickly.

#### Which cities include contractor names or phone numbers?

See the coverage matrix. Austin publishes company + name + phone; Chicago, Cincinnati,
Baton Rouge, and Buffalo publish contractor/applicant names. Cities that don't publish
contractor data are marked ❌ so you know before you run.

#### Can I get a daily feed of new roofing permits?

Yes: `monitor` mode with `trades: ["roofing"]` on a daily Apify schedule + webhook emits
only permits you haven't seen.

#### Is this legal to use?

Yes. The data comes from official government open-data portals published for public use
under open/public-domain licenses. No login-walled sources are used.

#### Does it work with AI agents?

Yes, callable via MCP from Claude, Cursor, or any MCP client.

### Fair use & data provenance

All data comes from official government open-data portals published for public use.
No login-walled sources, no personal-data enrichment, no skip-tracing. Owner names
appear only where the government source itself publishes them.

### Support

Issues tab, or the contact form on my profile. Broken-source reports are typically
fixed within 24-48h; my own daily canary usually catches breakage before users hit it.

If this Actor saves you time, a quick review on this page helps other contractors and
suppliers find it, and city requests from reviewers get built first.

# Actor input Schema

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

scrape = pull a date range once. monitor = only NEW permits since your last run (stateful, deduped - ideal for schedules/webhooks). canary = coverage self-test, no charges.

## `sources` (type: `array`):

Which verified sources to pull. Leave empty for ALL verified cities.

## `sinceDays` (type: `integer`):

Scrape mode: how many days back from today. Ignored if 'Since date' is set.

## `sinceDate` (type: `string`):

Scrape mode: explicit start date. Overrides look-back window.

## `untilDate` (type: `string`):

Scrape mode: explicit end date (inclusive). Default: today.

## `maxResultsPerSource` (type: `integer`):

Safety cap per source per run.

## `trades` (type: `array`):

Only return permits classified into these trades. Empty = all permits.

## `minValuation` (type: `integer`):

Only return permits with reported/estimated cost at or above this. Permits with no valuation are kept unless this is set above 0 and 'dropUnknownValuation' is on.

## `dropUnknownValuation` (type: `boolean`):

Only applies when a minimum valuation is set.

## `leadScoring` (type: `boolean`):

Adds lead\_score (0-100) + scoring\_reasons to every permit. Items are then billed as 'scored lead' events instead of raw 'permit' events - see pricing.

## `monitorStateName` (type: `string`):

Monitor mode: name of the key-value store holding watermarks. Change it to run independent monitors (e.g. one per client).

## `includeUnverified` (type: `boolean`):

Also run sources still marked pending verification. Off by default - we only ship what the daily canary proves works.

## `discordWebhookUrl` (type: `string`):

Canary mode: post the health summary to this Discord webhook.

## `socrataAppToken` (type: `string`):

Raises Socrata rate limits for very large backfills. Not needed for normal use.

## `accelaAppId` (type: `string`):

Only needed for Accela-backed cities (e.g. Grand Rapids). Register a free app at developer.accela.com to get an App ID + Secret.

## `accelaAppSecret` (type: `string`):

Paired secret for the Accela App ID above.

## Actor input object example

```json
{
  "mode": "scrape",
  "sources": [],
  "sinceDays": 7,
  "maxResultsPerSource": 5000,
  "trades": [],
  "dropUnknownValuation": false,
  "leadScoring": false,
  "monitorStateName": "building-permits-monitor",
  "includeUnverified": false
}
```

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("permitdata/us-building-permits-scraper").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("permitdata/us-building-permits-scraper").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 '{}' |
apify call permitdata/us-building-permits-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=permitdata/us-building-permits-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "US Building Permits Scraper - Contractor Leads, Verified Cities",
        "description": "Contractor leads from building permits: roofing, HVAC, solar, electrical, plumbing, remodel & new construction, classified by trade and lead-scored. 16 verified city feeds checked daily; contractor names, owner names, valuations, phones where published. From $3/1,000, source-direct government data.",
        "version": "0.1",
        "x-build-id": "ycMuiMcmIf9IeLOnt"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/permitdata~us-building-permits-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-permitdata-us-building-permits-scraper",
                "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/permitdata~us-building-permits-scraper/runs": {
            "post": {
                "operationId": "runs-sync-permitdata-us-building-permits-scraper",
                "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/permitdata~us-building-permits-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-permitdata-us-building-permits-scraper",
                "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": [
                            "scrape",
                            "monitor",
                            "canary"
                        ],
                        "type": "string",
                        "description": "scrape = pull a date range once. monitor = only NEW permits since your last run (stateful, deduped - ideal for schedules/webhooks). canary = coverage self-test, no charges.",
                        "default": "scrape"
                    },
                    "sources": {
                        "title": "Cities",
                        "type": "array",
                        "description": "Which verified sources to pull. Leave empty for ALL verified cities.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "chicago",
                                "detroit",
                                "nyc",
                                "san_francisco",
                                "austin",
                                "new_orleans",
                                "cincinnati",
                                "baton_rouge",
                                "buffalo",
                                "montgomery_county_md",
                                "seattle",
                                "san_jose",
                                "philadelphia",
                                "columbus",
                                "dc",
                                "nashville"
                            ],
                            "enumTitles": [
                                "Chicago, IL",
                                "Detroit, MI",
                                "New York City, NY",
                                "San Francisco, CA",
                                "Austin, TX (contractor + phone)",
                                "New Orleans, LA",
                                "Cincinnati, OH",
                                "Baton Rouge, LA",
                                "Buffalo, NY",
                                "Montgomery County, MD",
                                "Seattle, WA",
                                "San Jose, CA (contractor + owner)",
                                "Philadelphia, PA (contractor + owner)",
                                "Columbus, OH (applicant + valuation)",
                                "Washington, DC (applicant + owner)",
                                "Nashville, TN (contact + valuation)"
                            ]
                        },
                        "default": []
                    },
                    "sinceDays": {
                        "title": "Look-back window (days)",
                        "minimum": 1,
                        "maximum": 3650,
                        "type": "integer",
                        "description": "Scrape mode: how many days back from today. Ignored if 'Since date' is set.",
                        "default": 7
                    },
                    "sinceDate": {
                        "title": "Since date (YYYY-MM-DD)",
                        "type": "string",
                        "description": "Scrape mode: explicit start date. Overrides look-back window."
                    },
                    "untilDate": {
                        "title": "Until date (YYYY-MM-DD)",
                        "type": "string",
                        "description": "Scrape mode: explicit end date (inclusive). Default: today."
                    },
                    "maxResultsPerSource": {
                        "title": "Max results per city",
                        "minimum": 1,
                        "maximum": 200000,
                        "type": "integer",
                        "description": "Safety cap per source per run.",
                        "default": 5000
                    },
                    "trades": {
                        "title": "Trade filter",
                        "type": "array",
                        "description": "Only return permits classified into these trades. Empty = all permits.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "roofing",
                                "hvac",
                                "electrical",
                                "plumbing",
                                "solar",
                                "demolition",
                                "pool_spa",
                                "fence_deck",
                                "new_construction",
                                "remodel_addition",
                                "fire_systems",
                                "sign",
                                "other"
                            ],
                            "enumTitles": [
                                "Roofing",
                                "HVAC/Mechanical",
                                "Electrical",
                                "Plumbing",
                                "Solar",
                                "Demolition",
                                "Pool & Spa",
                                "Fence/Deck/Porch",
                                "New construction",
                                "Remodel/Addition",
                                "Fire systems",
                                "Signs",
                                "Other/Unclassified"
                            ]
                        },
                        "default": []
                    },
                    "minValuation": {
                        "title": "Minimum project valuation (USD)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Only return permits with reported/estimated cost at or above this. Permits with no valuation are kept unless this is set above 0 and 'dropUnknownValuation' is on."
                    },
                    "dropUnknownValuation": {
                        "title": "Drop permits with unknown valuation",
                        "type": "boolean",
                        "description": "Only applies when a minimum valuation is set.",
                        "default": false
                    },
                    "leadScoring": {
                        "title": "Lead scoring",
                        "type": "boolean",
                        "description": "Adds lead_score (0-100) + scoring_reasons to every permit. Items are then billed as 'scored lead' events instead of raw 'permit' events - see pricing.",
                        "default": false
                    },
                    "monitorStateName": {
                        "title": "Monitor state namespace",
                        "type": "string",
                        "description": "Monitor mode: name of the key-value store holding watermarks. Change it to run independent monitors (e.g. one per client).",
                        "default": "building-permits-monitor"
                    },
                    "includeUnverified": {
                        "title": "Include unverified sources (testing)",
                        "type": "boolean",
                        "description": "Also run sources still marked pending verification. Off by default - we only ship what the daily canary proves works.",
                        "default": false
                    },
                    "discordWebhookUrl": {
                        "title": "Discord webhook (canary alerts)",
                        "type": "string",
                        "description": "Canary mode: post the health summary to this Discord webhook."
                    },
                    "socrataAppToken": {
                        "title": "Socrata app token (optional)",
                        "type": "string",
                        "description": "Raises Socrata rate limits for very large backfills. Not needed for normal use."
                    },
                    "accelaAppId": {
                        "title": "Accela App ID (optional)",
                        "type": "string",
                        "description": "Only needed for Accela-backed cities (e.g. Grand Rapids). Register a free app at developer.accela.com to get an App ID + Secret."
                    },
                    "accelaAppSecret": {
                        "title": "Accela App Secret (optional)",
                        "type": "string",
                        "description": "Paired secret for the Accela App ID above."
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
