# NYC HPD Violation Status & Correction Date Alerts (`natstandridge/nyc-hpd-compliance-alerts`) Actor

Watch your NYC buildings for new HPD violations, official status changes, and Class C correction-date windows. Supply BBLs or BINs; receive building-level alerts only when something changes.

- **URL**: https://apify.com/natstandridge/nyc-hpd-compliance-alerts.md
- **Developed by:** [Nathaniel Standridge](https://apify.com/natstandridge) (community)
- **Categories:** Real estate, Business
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 delivered nyc hpd building alerts

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 HPD Violation Status & Correction Date Alerts

Property managers and housing operations teams need a short alert feed for the buildings they already manage. Supply NYC BBL or BIN identifiers, run this Actor daily or weekly, and receive building-level rows when an HPD violation first appears as open, its published status or correction date changes, or an open Class C notice crosses a selected correction-date window. The first run delivers the current open inventory; later unchanged runs deliver no rows.

This Actor reads the [official NYC HPD Housing Maintenance Code Violations dataset](https://data.cityofnewyork.us/d/wvxf-dwi5) through its public SODA API. It does not search for properties to sell or append owners, phone numbers, apartment numbers, tenant details, or raw violation descriptions. `orderNumber`, `noticeType`, class, and the exact official row link help distinguish notices at one building.

### Try one building

Paste this input into the Actor's Input tab. BBL `1007780075` is a public HPD building key; on November 6, 2026, the official feed showed seven open notices at that BBL. The hard alert cap keeps this example at **at most 20 charged rows ($0.06 at $0.003 each)**; if the building grows beyond that cap, the run fails before any alert is billed or state is advanced. Use a unique `monitorName` for each independent test or portfolio.

```json
{
  "bbls": ["1007780075"],
  "bins": [],
  "monitorName": "example-370-8th",
  "maxResults": 20
}
```

An alert row looks like this (building-level fields from a real HPD notice; observation time and hash are illustrative):

```json
{
  "schemaVersion": 1,
  "observationId": "74c9e5c37a83258dca0f66fa1227aa96576ee7e9d9ee0a2cdb45badb5855a347",
  "violationId": "19241376",
  "bbl": "1007780075",
  "bin": "1014276",
  "buildingAddress": "370 8 AVENUE, MANHATTAN, 10001",
  "violationClass": "C",
  "orderNumber": "568",
  "noticeType": "Original",
  "issuedDate": "2026-09-25",
  "violationStatus": "Open",
  "currentStatus": "INVALID CERTIFICATION",
  "currentStatusDate": "2026-10-14",
  "previousViolationStatus": null,
  "previousCurrentStatus": null,
  "correctionDate": "2026-10-21",
  "correctionDateSource": "originalcorrectbydate",
  "dateBand": "past_source_date",
  "reasons": ["new_open", "correction_date_past_source_date"],
  "observedAt": "2026-11-06T17:00:00Z",
  "sourceUpdatedAt": "2026-11-06T15:53:52Z",
  "sourceUrl": "https://data.cityofnewyork.us/resource/wvxf-dwi5.json?violationid=19241376"
}
```

Rows are in the default dataset for CSV, Excel, JSON, API, or webhook use. The free `OUTPUT` record reports the publisher update timestamp, source rows checked, alert count, and whether the run completed. An empty dataset with `OUTPUT.complete = true` means no tracked change was found. A failed or stale-source run does not mean there were no changes.

### Alert rules

| Reason | When it appears |
| --- | --- |
| `new_open` | A currently open violation was not in this monitor's prior snapshot, including the first run. |
| `source_status_changed` | HPD's `violationstatus` or `currentstatus` changed since the previous completed run. |
| `source_correction_date_changed` | HPD changed `newcorrectbydate` or `originalcorrectbydate`. |
| `correction_date_within_window` | An open Class C notice entered the selected window before the published correction date. |
| `correction_date_past_source_date` | An open Class C notice's published correction date is earlier than the current New York date. |

One violation generates at most one billed alert row in a run, even if several reasons apply. The date bands are mechanical comparisons with HPD's published fields. They do not determine legal deadlines, compliance, repairs, or whether a correction is accepted. Check the official record and your own counsel or agency process before acting.

The Actor reads all currently open notices at your selected BBLs/BINs, recent status updates within `lookbackDays`, and any previously tracked open notice by ID. A completed run stores a snapshot in a named key-value store under the running Apify user's account and `monitorName`. Use the same input and name on later runs. Changing the building scope or date-window settings with the same name is rejected; start a new name. Do not overlap runs of the same monitor.

### Inputs and boundaries

- `bbls`: 10-digit NYC borough-block-lot identifiers; `bins`: 7-digit building identifiers. Supply at least one and at most 20 total. A BBL can include multiple buildings, while a BIN identifies one building.
- `monitorName`: 1–20 letters, digits, underscores, or hyphens. Separate names keep independent state.
- `lookbackDays`: 7–180 days, default 90. The source query still includes current open rows and previously tracked open IDs.
- `dateWindowDays`: 1–30 days, default 7.
- `maxSourceRows`: 50–2,000, default 1,000. `maxResults`: 1–500, default 200. Exceeding either cap stops before billing or state advancement.
- `maxRunSeconds`: 60–240, default 180. Set the platform timeout to at least 300 seconds.

No arbitrary URL is accepted. Requests go only to the official `data.cityofnewyork.us` API, with redirects disabled and bounded retries. The Actor never sends an operator deployment credential to NYC.

### Price and freshness

Proposed price: **$0.003 per delivered alert dataset row** under Apify Pay Per Event. There is no Actor-start event and no charge for source rows, unchanged notices, or the `OUTPUT` summary. A first run with seven alerts would be $0.021; actual rows may change. Platform prices and the deployed listing must be read back before treating this as a live price.

HPD's publisher timestamp is included in each alert and `OUTPUT`. The Actor stops without billing when the dataset timestamp is more than 96 hours old or invalid. HPD status updates can lag real-world inspections and corrections. A source API error, a building with more rows than the cap, or an exhausted charge limit stops the run instead of presenting a misleading empty success.

The dataset contains historical notices and may change fields or status values. This Actor recognizes HPD `Open` and `Close` values and fails on unknown values. It does not monitor DOB violations, infer an owner, send outreach, verify repair completion, or supply legal compliance advice.

# Actor input Schema

## `bbls` (type: `array`):

NYC 10-digit borough-block-lot IDs. Supply BBLs or BINs, at most 20 identifiers total. The Actor queries only these buildings.

## `bins` (type: `array`):

NYC 7-digit Building Identification Numbers. Supply BBLs or BINs, at most 20 identifiers total.

## `monitorName` (type: `string`):

Use a distinct name for each portfolio and each independent test. This name scopes the saved comparison state within your account.

## `lookbackDays` (type: `integer`):

Fetch status changes within this many days, plus every currently open notice and every previously tracked open notice. Daily or weekly schedules are recommended.

## `dateWindowDays` (type: `integer`):

Report a new band when the publisher's correction date is this many days away. This is a date comparison, not a legal determination.

## `maxSourceRows` (type: `integer`):

Safety cap over the complete selected portfolio. If exceeded, the run stops before billing or changing monitor state.

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

If more alerts would be emitted, the run stops before billing or advancing state. Narrow the portfolio or raise this cap.

## `maxRunSeconds` (type: `integer`):

Includes fetching, checks, and output. Set the platform run timeout to at least 300 seconds.

## Actor input object example

```json
{
  "bbls": [
    "1007780075"
  ],
  "bins": [],
  "monitorName": "default",
  "lookbackDays": 90,
  "dateWindowDays": 7,
  "maxSourceRows": 1000,
  "maxResults": 200,
  "maxRunSeconds": 180
}
```

# Actor output Schema

## `alerts` (type: `string`):

No description

## `summary` (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 = {
    "bbls": [
        "1007780075"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("natstandridge/nyc-hpd-compliance-alerts").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 = { "bbls": ["1007780075"] }

# Run the Actor and wait for it to finish
run = client.actor("natstandridge/nyc-hpd-compliance-alerts").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 '{
  "bbls": [
    "1007780075"
  ]
}' |
apify call natstandridge/nyc-hpd-compliance-alerts --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,natstandridge/nyc-hpd-compliance-alerts"
        }
    }
}
```

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/nnDfU568qGt9c8ZKb/builds/K6WzjhS0uhKH4JfSX/openapi.json
