# NYC Event & Permit Explorer — Research Beta (`bgmowl/nyc-event-access-radar-prototype`) Actor

Research beta: browse bounded NYC event and same-segment construction permit records with retrieved stipulations and embargo counter-evidence. Raw timing, completeness and physical access are unverified. No disruption or clearance prediction. $0 developer fee; Apify usage charges apply.

- **URL**: https://apify.com/bgmowl/nyc-event-access-radar-prototype.md
- **Developed by:** [bgm owl](https://apify.com/bgmowl) (community)
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 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/actors/running/actors-in-store.md#pay-per-usage

## 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 Event & Permit Explorer — Research Beta

A limited research beta for comparing public NYC event permits, construction applications and their companion stipulations. It produces an evidence-linked review list, **not validated access-risk predictions**.

A permit does not prove work is occurring. An embargo or restoration requirement does not prove compliance or clear access. Floating source timestamps have no verified common timezone or DST interpretation.

**Pricing:** $0 developer fee. Apify platform usage charges apply to runs, data transfer and storage according to your plan. This is a bounded research tool, not a no-cost guarantee.

### Why the third source matters

The DOT dictionary says `SpecificStipulations` adds to rules in a separate table. Reading that field alone missed event-specific work embargoes and restoration requirements in all three curated examples.

The corrected comparison joins [companion stipulations](https://data.cityofnewyork.us/d/gsgx-6efw) by exact permit number and prominently shows applicable-on-the-provisional-calendar and potential counter-evidence. Raw rule text, IDs, source links, retrieval timestamps, dataset update timestamps and coverage limits remain available.

The original three administrative application groups carry these rules:

- Cumberland Farms production parking: SE536C, October 8, 00:01–23:59.
- Stan Deutcsh lighting show: SE682B explicitly lists October 4, 5 and 8, 06:00–23:30. The header is not expanded into a continuous interval.
- Grand Central Community Fall Expo: SE91T0, October 8, 08:00–20:00.

A fourth weekend-work application is retained with timing uncertainty and its own companion embargo evidence. These are administrative facts, not four validated disruptions or four clear-access conclusions.

### Run offline

Python 3.11 or newer; the CLI and unit suite need no third-party packages.

```sh
python -m unittest discover -s tests -v
python -m event_access_radar --input examples/audited-cases/input.json \
  --fixtures examples/audited-cases --fixture-today 2026-10-08 \
  --output audited-report.json --brief audited-brief.txt
```

`--fixture-today` is available only for offline replay. The exact public 248-row companion fixture is preserved byte-for-byte, with its audit and source manifest. `examples/synthetic/` provides artificial inputs; historical earlier reports are labeled and preserved rather than presented as current validation.

### One bounded live read

```json
{
  "startDate": "2026-10-08",
  "endDate": "2026-10-08",
  "borough": "Manhattan",
  "maxEvents": 1000,
  "maxConstruction": 2000,
  "maxCheckedEvents": 10,
  "maxCompanionRows": 2000,
  "maxCompanionPermits": 100,
  "segments": []
}
```

```sh
python -m event_access_radar --input input.json --output report.json --brief brief.txt
```

Update dates when the example becomes historical. Input accepts today or later under a UTC validation policy, at most seven requested calendar dates. That validation policy does not establish the source's timezone.

The program reads a bounded event sample, chooses up to ten parseable event windows by default, queries construction for their street-segment supersets, performs exact local matches and fetches companion rows for at most 100 candidate permit IDs. Optional exact block filters use `street`, `fromStreet` and `toStreet`. No account, token, proxy, paid API, AWS resource, recurring work or alert is required by the CLI.

### Time is provisional, never an authoritative exclusion

Source `calendar_date` values are floating. They are retained without offsets or conversion. Comparing them across datasets assumes a shared calendar basis that has not been verified.

This version retains matched candidates when raw clocks are disjoint or a recognized work-hours rule would otherwise exclude them. It shows that provisional counter-evidence instead of silently removing the candidate. There is no claim about elapsed time, current activity, local timezone or DST fold/gap resolution.

Live retrieval uses a disclosed two-calendar-day boundary buffer on either side of the requested date range. Requested-calendar matches are prioritized during event selection. This is a bounded recall aid, **not a proof of timezone completeness**; row/selection caps and the finite buffer can still omit relevant records. Zero matches never mean access is clear.

Explicit cancelled/revoked administrative status and affirmative event-own permit references are separately listed as exclusions. Those administrative exclusions also do not establish physical clearance. Invalid, reversed, unexpectedly offset-aware and anomalously long source windows are quarantined rather than repaired.

### Rules and counter-evidence

- Every companion row joins by permit number. A stipulation ID repeated across permits is not globally deduplicated.
- Exact duplicate rows collapse; changed text for the same permit/rule ID remains conflicting evidence.
- `createdon` is a source record field, not a retrieval or dataset-freshness timestamp.
- Query completeness, permit IDs attempted, rows returned, analysis budget and knowledge of all applicable rules are distinct. The last remains unverified.
- Missing companion rows **never mean no rules**. The audit's initial read omitted Grand Central rows that appeared in the later saved retrieval; the cause remains unresolved.
- Explicit dated embargo windows and the exact supported explicit recurring-date list are recognized only with the observed full event/restoration template. Unfamiliar tails, cancellation, overrides, unfamiliar recurrence, missing-year inference and malformed dates stay unknown.
- Potential rules outside the event's raw calendar interval remain visible because cross-source alignment is unverified.
- Restoration keyword mentions are neutral signals. A recognized affirmative obligation is nullable and still does not prove compliance.
- Storage outside work hours is not equivalent to work-hour activity. Rules such as a ban on chopping concrete are not generalized into bans on all roadway occupancy.

Application IDs group administrative filings, not physical projects. Extensions or reissues can span application IDs. Permit start/end dates mean effectiveness and expiration; no administrative status establishes observed activity.

`LocationGeometry` is a type label. Only supported actual WKT syntax contributes to the representation flag, currently simple 2D POINT or LINESTRING. Raw WKT presence is reported separately. No geometric proximity, entrance effects, topology or accessibility route is validated.

### Sources and provenance

Event data: **NYC Office of Citywide Event Coordination and Management (CECM)**. Construction permits and companion stipulations: **NYC Department of Transportation (DOT)**, via NYC Open Data. This independent derivative filters records, normalizes street text and groups permits by administrative application. It is **not endorsed by the City of New York**. Consult original records; the City does not guarantee accuracy, completeness or fitness for a particular use. No City branding rights or blanket open-content license is asserted.

Each result retains source links. `sources[].fetched_at` is our retrieval time; `source_rows_updated_at` is the dataset's update time, which does not establish the freshness or physical activity of an individual permit.

- [NYC permitted event information](https://data.cityofnewyork.us/d/tvpp-9vvx)
- [Street construction permits](https://data.cityofnewyork.us/d/tqtj-sjs8)
- [Street construction permit stipulations](https://data.cityofnewyork.us/d/gsgx-6efw)
- Official DOT dictionary and [Socrata floating timestamp documentation](https://dev.socrata.com/docs/datatypes/floating_timestamp.html), preserved with hashes under `audit-2026-10-08/`.

Event windows can include setup and breakdown. Short film street impacts are omitted from the event source. Exact street normalization misses partial/contained segments, aliases, parks, nearby streets and entrance-level effects.

### Hard limits

- 5,000 event rows and 5,000 construction rows maximum; defaults 1,000 and 2,000.
- Default 10 selected event windows, maximum 25; at most 50 queried segments.
- At most 100 candidate permit IDs in four 25-ID companion queries.
- Total companion-row budget 2,000 by default, maximum 5,000; one extra row detects truncation.
- At most nine normal HTTP requests: four base data/metadata requests, four companion chunks and one companion metadata request. No automatic pagination, retries or proxy fallback.
- 12 MiB response limit, 30-second socket timeout, 50,000 comparisons, 2,000 result groups and 10,000 rule associations.
- Missing/unprocessed evidence is flagged. Required data-fetch failures stop the run; metadata failure leaves freshness unknown.

### Read coverage before interpreting a candidate

**Research into administrative records only. Partial retrieval may omit an embargo or other evidence.** Source times have no verified common timezone or DST interpretation. The selected sample, matching rules and query caps can miss relevant records or conditions. Missing companion rows and embargo obligations do not establish clear access; permits do not establish actual work.

The default overview shows **All selected-source reads complete?** and **All group permit queries complete?** next to each application. False means evidence retrieval is incomplete. Even true does not establish that all applicable rules are known. Switch to **Per-permit evidence JSON: open Permits**, then select **JSON** to read the complete Permits array. Each permit retains `companion_stipulations.status`, `query_complete`, `returned_rule_rows`, `analysis_rows_truncated` and `warning` without flattening or dropping evidence. These are the actual query status, completeness, returned count and analysis truncation flag. `not_queried_or_provenance_unavailable` differs from `no_rows_returned_rules_unknown`; neither means no rules.

Select **Full REPORT and input: open REPORT** from Output, then view or download the **REPORT** record in the native storage list. It includes the exact attempted/unqueried companion IDs, query caps, source-update and retrieval timestamps, skipped records and full warnings. On older runs without the new Output selector, use **Storage → Key-value store → REPORT**.

The October 8 private QA example is a **partial source sample**: three event windows selected from a truncated 1,000-row event read; 29 permit rows retrieved; companion queries for six of 29 candidate permit IDs, with 23 IDs not queried. The absence of displayed embargo evidence for an unqueried permit does not negate separately audited rules. These are facts about that saved run, not assumed counts for future runs.

The legacy `potential_permit_overlap` classification means same-segment administrative candidates, including retained disjoint-clock records. It is not a claim that work overlaps, is active or obstructs an event.

### Runtime and release

The Apify adapter saves a full REPORT and evidence-linked dataset rows. Three private bounded three-source Docker/Apify runs completed successfully on October 8, 2026. The final check on build 0.0.4 produced 13 schema-valid rows, verified report/provenance consistency, and checked the actual coverage indicators, per-permit JSON and native REPORT download. This is runtime and presentation evidence, not validated access risk or complete source coverage.

The audited sample selected three event windows from a truncated 1,000-row event read and queried companion rules for six of 29 candidate permits. Missing evidence remained explicit. Counts describe those saved tests, not every future run.

This limited administrative-record research beta is released with a $0 developer fee; Apify platform usage charges apply. Source timing, rule completeness, compliance and physical access remain unverified. Access-risk predictions, routing safety and clearance conclusions are outside this beta. No user-created schedule or Standby is enabled by this release. Apify Store may run platform-managed daily health tests; those are separate from user-created schedules.

# Actor input Schema

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

Requested raw source-calendar date, YYYY-MM-DD. UTC today-or-later validation is an input policy, not a claim about source timezone. Retrieval includes a disclosed two-calendar-day boundary buffer.

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

End of requested raw-calendar range; maximum seven requested dates. Source timezone alignment and DST remain unverified.

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

Manhattan is the initially validated prototype market.

## `maxEvents` (type: `integer`):

One bounded query; overflow is flagged as incomplete coverage.

## `maxConstruction` (type: `integer`):

One bounded query; no automatic pagination.

## `segments` (type: `array`):

Up to 50 exact block filters. Eligible events are selected first; their parsed segments also narrow the construction query.

## `maxCheckedEvents` (type: `integer`):

Select this many parseable event windows from the bounded event read, then query construction for their segments only. Does not claim borough-wide coverage.

## `maxCompanionRows` (type: `integer`):

Total rule-row budget across at most four 25-permit queries. Missing or truncated rows never establish no rules.

## `maxCompanionPermits` (type: `integer`):

Candidate permit IDs beyond this cap remain explicitly unqueried/unknown.

## Actor input object example

```json
{
  "borough": "Manhattan",
  "maxEvents": 1000,
  "maxConstruction": 2000,
  "maxCheckedEvents": 10,
  "maxCompanionRows": 2000,
  "maxCompanionPermits": 100
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `permitEvidence` (type: `string`):

No description

## `fullReport` (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("bgmowl/nyc-event-access-radar-prototype").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("bgmowl/nyc-event-access-radar-prototype").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 bgmowl/nyc-event-access-radar-prototype --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bgmowl/nyc-event-access-radar-prototype"
        }
    }
}
```

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/tCbA3GHg9mVB0gNfq/builds/AMMGl3Am6rvrOQHFT/openapi.json
