# Multi City Building Permit Aggregator (`george.the.developer/multi-city-building-permit-aggregator`) Actor

Normalize public building permit data from NYC Open Data and the Chicago Data Portal into one JSON schema.

- **URL**: https://apify.com/george.the.developer/multi-city-building-permit-aggregator.md
- **Developed by:** [George Kioko](https://apify.com/george.the.developer) (community)
- **Categories:** Real estate
- **Stats:** 1 total users, 1 monthly users, 0.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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

## Multi City Building Permit Aggregator

Each US city publishes its building permit dataset in its own JSON shape. Normalizing them is the work nobody wants to maintain.

This Actor wraps public city open data feeds and returns a consistent permit schema for real estate researchers, market analysts, supply distributors, builder intelligence teams, and local service businesses. v1 covers NYC Open Data and the Chicago Data Portal. Both sources are public Socrata datasets published by city governments under their open data programs.

The Actor does not use browser automation, XML, screenshots, or private data sources. It calls the public JSON APIs directly, normalizes the field names, and excludes individual personal name fields from output. Builder and property fields are limited to public business-name fields.

### Quick Start

Fetch recent Chicago permits:

```bash
curl "https://api.apify.com/v2/acts/YOUR_ACTOR_ID/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"city":"chicago","since":"2026-04-01","limit":10}'
````

Use Standby mode for an instant API response:

```bash
curl "https://YOUR_STANDBY_URL/permits?city=chicago&since=2026-04-01&min_cost=25000&limit=5"
```

### Standby Endpoints

| Endpoint | Purpose | PPE event |
|---|---|---|
| `GET /` and `GET /health` | Service info and readiness | none |
| `GET /permits?city=<nyc\|chicago>&since=<YYYY-MM-DD>&permit_type=<>&min_cost=<>&limit=<N>` | Filtered normalized permits | `permit-row` per row |
| `GET /permit?city=<>&permit_id=<>` | One permit detail | `permit-row` x 1 |
| `GET /builder?city=<>&business_name=<>` | Builder activity summary | `contractor-roundup` x 1 |
| `GET /properties?city=<>&since=<YYYY-MM-DD>&min_permit_count=<N>&limit=<N>` | Active property addresses by permit count | `permit-row` per property row |
| `POST /permits/bulk` | Multi-city pull with `{ "cities": [...], "since": "...", "limit_per_city": N }` | `permit-row` per row |

Bulk requests accept up to 4 cities and 200 rows per city. v1 intentionally supports NYC and Chicago only.

### Permit Schema

| Field | Type | Notes |
|---|---|---|
| `permit_id` | string | City permit/job identifier |
| `city` | string | `nyc` or `chicago` |
| `permit_type` | string | City permit type code or label |
| `permit_status` | string | Normalized to `issued`, `filed`, `in-process`, `approved`, `signed-off`, or `inactive` |
| `filing_date` | ISO8601/null | Parsed defensively from city date formats |
| `issuance_date` | ISO8601/null | Permit issue date when available |
| `expiration_date` | ISO8601/null | Expiration date when available |
| `work_type` | string | Work category or description |
| `estimated_cost_usd` | number/null | Reported cost where the city provides it |
| `address` | string | Normalized street address |
| `borough_or_ward` | string/null | NYC borough or Chicago ward |
| `zip_code` | string/null | Source zip where available |
| `block_lot` | string/null | NYC block/lot or source equivalent |
| `gis_latitude`, `gis_longitude` | number/null | Coordinates from source dataset |
| `builder_business` | string/null | Public permittee or contractor business field |
| `builder_license_number` | string/null | Public license field where available |
| `property_business` | string/null | Public owner business field where available |
| `property_business_type` | string/null | `individual`, `corporation`, `llc`, `partnership`, or null |
| `source_url` | string | Public city dataset URL |
| `fetched_at` | ISO8601 | Fetch timestamp |

### Builder Roundup Schema

| Field | Type | Notes |
|---|---|---|
| `roundup_id` | string | Stable city plus business identifier |
| `city` | string | City key |
| `builder_business` | string | Builder business used for lookup |
| `permit_count_3y` | number | Permit count in the last 3 years |
| `permit_count_1y` | number | Permit count in the last year |
| `total_value_3y_usd` | number | Sum of reported permit values |
| `top_permit_types` | string\[] | Most frequent permit types |
| `top_property_businesses_served` | object\[] | Top public owner business fields |
| `top_zip_codes` | string\[] | Top zip codes where available |
| `first_permit_date` | ISO8601/null | Earliest permit in window |
| `last_permit_date` | ISO8601/null | Latest permit in window |
| `activity_tier` | string | `low`, `active`, or `high-volume` |
| `fetched_at` | ISO8601 | Fetch timestamp |

Activity tier is deterministic: under 5 permits is `low`, 5 to 49 is `active`, and 50 or more is `high-volume`.

### Flow

```mermaid
flowchart LR
  A[Input] --> B[City router]
  B --> C[NYC Open Data]
  B --> D[Chicago Data Portal]
  C --> E[Normalize permit schema]
  D --> E
  E --> F{Builder endpoint?}
  F -->|yes| G[Builder roundup aggregation]
  F -->|no| H[Dataset output]
  G --> H
```

### Pricing

| Event | Price | When charged |
|---|---:|---|
| `actor-start` | $1.00 | Once per paid Standby request or batch run |
| `permit-row` | $0.05 | Each normalized permit or property activity row returned |
| `contractor-roundup` | $0.30 | Each builder activity summary returned |

Healthcheck and mock probe payloads short-circuit without fetching city data.

### Comparison

| Option | What you get | Tradeoff |
|---|---|---|
| City open data portals | Free public datasets | No shared schema, different field names, separate parser per city |
| BuildZoom or similar SaaS | Polished contractor and permit intelligence | Higher cost and less direct API control |
| This Actor | Normalized JSON API over public city permit datasets | v1 city coverage is narrow, but output is direct and automation-friendly |

### Use Cases

Use this Actor for market research, builder activity tracking, real estate research, neighborhood permit volume monitoring, and supply distributor regional planning. It is also useful for analysts who already trust city open data but do not want to keep rewriting field maps for every local portal.

### FAQ

**Which cities are covered?** v1 covers NYC and Chicago only.

**How fresh is the data?** The Actor reads live public Socrata APIs. Freshness depends on each city dataset’s publishing cadence.

**Where does the business name come from?** NYC uses the public permittee business field. Chicago uses public contractor contact fields when they identify a business.

**Are personal names included?** No. The normalized output deliberately excludes personal name fields.

**What about Socrata rate limits?** Keep limits small for interactive use and use bulk mode responsibly. Socrata may throttle very large repeated pulls.

**Refunds or issues?** Contact the Actor owner through Apify with the run ID and endpoint used.

# Actor input Schema

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

Batch mode to run.

## `city` (type: `string`):

City key.

## `since` (type: `string`):

YYYY-MM-DD lower bound for filing or application date.

## `permit_type` (type: `string`):

Optional permit type filter.

## `min_cost` (type: `integer`):

Optional minimum reported project cost filter where supported.

## `limit` (type: `integer`):

Maximum rows to return.

## `permit_id` (type: `string`):

Permit identifier for mode=permit.

## `business_name` (type: `string`):

Builder business name for mode=builder.

## `cities` (type: `array`):

City keys for bulk mode.

## `limit_per_city` (type: `integer`):

Maximum permits per city for bulk mode.

## Actor input object example

```json
{
  "mode": "permits",
  "city": "nyc",
  "limit": 25,
  "limit_per_city": 25
}
```

# 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("george.the.developer/multi-city-building-permit-aggregator").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("george.the.developer/multi-city-building-permit-aggregator").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 george.the.developer/multi-city-building-permit-aggregator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=george.the.developer/multi-city-building-permit-aggregator",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Multi City Building Permit Aggregator",
        "description": "Normalize public building permit data from NYC Open Data and the Chicago Data Portal into one JSON schema.",
        "version": "1.0",
        "x-build-id": "iyo4kwBaZH7j95SC0"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/george.the.developer~multi-city-building-permit-aggregator/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-george.the.developer-multi-city-building-permit-aggregator",
                "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/george.the.developer~multi-city-building-permit-aggregator/runs": {
            "post": {
                "operationId": "runs-sync-george.the.developer-multi-city-building-permit-aggregator",
                "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/george.the.developer~multi-city-building-permit-aggregator/run-sync": {
            "post": {
                "operationId": "run-sync-george.the.developer-multi-city-building-permit-aggregator",
                "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": [
                            "permits",
                            "permit",
                            "builder",
                            "bulk"
                        ],
                        "type": "string",
                        "description": "Batch mode to run.",
                        "default": "permits"
                    },
                    "city": {
                        "title": "City",
                        "enum": [
                            "nyc",
                            "chicago"
                        ],
                        "type": "string",
                        "description": "City key.",
                        "default": "nyc"
                    },
                    "since": {
                        "title": "Since date",
                        "type": "string",
                        "description": "YYYY-MM-DD lower bound for filing or application date."
                    },
                    "permit_type": {
                        "title": "Permit type",
                        "type": "string",
                        "description": "Optional permit type filter."
                    },
                    "min_cost": {
                        "title": "Minimum cost",
                        "type": "integer",
                        "description": "Optional minimum reported project cost filter where supported."
                    },
                    "limit": {
                        "title": "Limit",
                        "minimum": 1,
                        "maximum": 200,
                        "type": "integer",
                        "description": "Maximum rows to return.",
                        "default": 25
                    },
                    "permit_id": {
                        "title": "Permit ID",
                        "type": "string",
                        "description": "Permit identifier for mode=permit."
                    },
                    "business_name": {
                        "title": "Builder business name",
                        "type": "string",
                        "description": "Builder business name for mode=builder."
                    },
                    "cities": {
                        "title": "Cities",
                        "type": "array",
                        "description": "City keys for bulk mode.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "limit_per_city": {
                        "title": "Limit per city",
                        "minimum": 1,
                        "maximum": 200,
                        "type": "integer",
                        "description": "Maximum permits per city for bulk mode.",
                        "default": 25
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
