# NYC Construction Permit & Contractor Leads (`afkdigital/newapi03-nyc-construction-permit-contractor-leads`) Actor

Find recent NYC construction permit signals and business contact details matched to active city contractor licenses. Official NYC Open Data; JSON and CSV exports.

- **URL**: https://apify.com/afkdigital/newapi03-nyc-construction-permit-contractor-leads.md
- **Developed by:** [AFK Digital](https://apify.com/afkdigital) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.50 / 1,000 unique contractor leads

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

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

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## NYC Construction Permit & Licensed Contractor Leads (NEWAPI03)

Find recently issued NYC construction permits and connect an applicant to contact information only when an active DOB license record matches its license number **and** mapped license type. Designed for construction suppliers, software vendors, insurers, and B2B research teams.

### Sources and scope

- Official NYC DOB NOW approved permits: https://data.cityofnewyork.us/Housing-Development/DOB-NOW-Build-Approved-Permits/rbx6-tga4
- Official NYC DOB active licenses: https://data.cityofnewyork.us/Housing-Development/DOB-Licenses-Filtered-for-Active/9hiw-49pz
- NYC Open Data policy: https://www.nyc.gov/opendata/get-started/user-guides/open-data-apis and NYC Admin. Code §23-502(d).
- No Houzz access, reviews, ratings, revenue estimation, personal owner contact enrichment, or automated outreach. No affiliation or endorsement by NYC.
- License information is a snapshot, not a guarantee of current validity. Check with the issuing authority. Estimated job cost is a filing estimate, **not** contractor revenue or a confirmed contract value.

### Input

`borough` (NYC borough or All), exact `workType`, `zipCode`, `keyword`, `issuedSince` (YYYY-MM-DD), `minEstimatedCost`, `maxEstimatedCost`, `maxResults` (1–1000), and `maxPermitRows` (50–5000). Defaults: Manhattan, General Construction, previous 7 days, 25 unique contractor records, at most 500 permit rows. Filters with unavailable cost exclude rows with missing cost when a cost threshold is used.

### Output

One JSON dataset item per distinct applicant license number (or normalized business name when missing). Fields: `business_name`, `license_number`, `license_type`, `license_status`, `license_match_status`, `business_phone`, `business_email`, `business_address`, `borough`, `zip_code`, `work_type`, `job_description`, `estimated_job_cost_usd`, `issued_date`, `work_permit`, `source_url`, `license_source_url`, `observed_at`. Empty fields remain null. Dataset exports JSON and CSV in Apify; flat rows work in Clay and n8n. A permit source URL and observation timestamp accompany each item.

A matched license is labeled `number_and_type_active`. Unmatched applicants retain the permit's public business data but no license-derived phone or email. We do not label any business “verified.” The API can have stale or missing information, and a permit indicates past issuance rather than an open bid.

### Limits and operation

Uses official SODA API pagination in batches of 100; request timeout 15s, up to four attempts with backoff for transient errors, maximum 240 seconds, scan cap, max results, and in-run deduplication. An optional `NYC_SOCRATA_APP_TOKEN` environment variable can improve API reliability; it is never logged. Default needs no token. Runs against public NYC data and does not send messages.

Local: `npm ci && npm test && npm start`. Set `APIFY_LOCAL_STORAGE_DIR` and provide `storage/key_value_stores/default/INPUT.json` to run with custom input. Container: `docker build -t newapi03 .`.

### Pricing

Pay-per-event `result` is charged once per emitted contractor record through `Actor.pushData(row, 'result')`. Live pay-per-event price: **$0.0045 per distinct contractor result ($4.50 per 1,000)**. Apify charges this event once per emitted row. Platform usage, Apify commission, and any account-tier discounts affect the creator's net payout. A two-result paid test run measured $0.00017 in platform usage; large-run profitability has not been measured.

# Actor input Schema

## `borough` (type: `string`):

Permit location.

## `workType` (type: `string`):

Exact NYC DOB work type; General Construction by default.

## `zipCode` (type: `string`):

Permit ZIP code filter for NYC permit records.

## `keyword` (type: `string`):

Job description keyword filter for NYC permit records.

## `issuedSince` (type: `string`):

Defaults to the previous seven days.

## `minEstimatedCost` (type: `integer`):

Minimum estimated job cost (USD) filter for NYC permit records.

## `maxEstimatedCost` (type: `integer`):

Maximum estimated job cost (USD) filter for NYC permit records.

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

Maximum unique contractors filter for NYC permit records.

## `maxPermitRows` (type: `integer`):

Maximum permit rows scanned filter for NYC permit records.

## Actor input object example

```json
{
  "borough": "Manhattan",
  "workType": "General Construction",
  "maxResults": 25,
  "maxPermitRows": 500
}
```

# Actor output Schema

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

// Run the Actor and wait for it to finish
const run = await client.actor("afkdigital/newapi03-nyc-construction-permit-contractor-leads").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("afkdigital/newapi03-nyc-construction-permit-contractor-leads").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{}' |
apify call afkdigital/newapi03-nyc-construction-permit-contractor-leads --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,afkdigital/newapi03-nyc-construction-permit-contractor-leads"
        }
    }
}
```

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

## OpenAPI specification

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