Get NYC DOB NOW approved building permits from NYC Open Data as clean records, one per permit: dates, borough, address, BIN/BBL, work types, job description, estimated cost, contractor and owner business. Filter by date, borough, work type, ZIP. Only-new-or-changed mode for daily feeds.
Versions follow MAJOR.MINOR.PATCH (src/version.py); Apify shows MAJOR.MINOR from .actor/actor.json.
Every run logs its version and records it in the RUN_STATS key-value record.
0.1.1 (2026-10-16)
A run that returns nothing (every input bad, private, blocked or unreachable, or an empty input) now ends
SUCCEEDED with an empty dataset and the reason as its status message and in the log, instead of FAILED. Only an
unexpected error still fails the run. RUN_STATS keeps the reason as before.
No change to output fields or price.
0.1.0 (unreleased)
First release.
Reads NYC Open Data's DOB NOW: Build – Approved Permits (dataset rbx6-tga4, updated daily by the Department
of Buildings) through its public SODA API, and returns one normalized record per permit issuance: the source's
rows (one per work type of the permit's job) are joined, with every work type in workTypes; boroughs spelled one
way; dates as YYYY-MM-DD; costs and coordinates as numbers; BIN/BBL as text; an address line; a stable id from
the permit, sequence and tracking numbers (Socrata's own row ids change on every reload); a sourceUrl API query
returning the permit's source rows; and sourceUpdatedAt, when DOB last changed them.
Filters: issued or approved date (last N days or a date range), boroughs, work types (matched on any of the job's
work types), filing reasons, permit statuses, ZIP codes, BINs, job-description keywords, minimum estimated cost.
"Only new or changed permits since the last run": state in the user's named store nyc-building-permits-memory,
one record per filter set (and optional monitor name); reads only rows DOB changed since the last run, skips (and
doesn't charge) permits re-published unchanged, labels the rest new or changed; a run where the dataset hasn't
changed stops after one request. Only what was pushed is remembered.
Person names (applicant, filing representative, owner) and the owner's mailing address are never requested or
returned.
Optional user-supplied Socrata app token, sent only in the X-App-Token header.
Charged per permit returned, through Apify's standard apify-default-dataset-item event; "Max results per run"
(default 1,000, so a run with no input stays small) and the maximum cost per run are honoured.
Terms: NYC Administrative Code § 23-502(d) (Local Law 11 of 2012): public data sets "shall be made available
without any registration requirement, license requirement or restrictions on their use", except that a third party
may be required "to explicitly identify the source and version of the public data set, and a description of any
modifications" (https://nyc-laws.readthedocs.io/en/latest/nycadmincode/t23/c05/ ; enacted text:
https://legistar.council.nyc.gov/LegislationDetail.aspx?ID=649911&GUID=E650813B-B1E9-4E56-81BA-58261487DA4A ).
NYC Open Data's FAQ (https://www.nyc.gov/opendata/get-started/FAQs ): "Are there restrictions on how I can use Open
Data? Open Data belongs to all New Yorkers. There are no restrictions on the use of Open Data." The portal's pages
link NYC.gov's terms of use (https://www.nyc.gov/main/terms-of-use ), which contain no clause on commercial reuse,
automated access or APIs: section I forbids unlawful use and disrupting the servers, section VI disclaims
warranties. Their section IV says materials
"contained in or displayed on NYC.gov" are the City's property, "All rights are reserved"; for public data sets
the Open Data Law above (no restrictions on use) and the portal's own FAQ govern. The dataset has no
license field; attribution: Department of Buildings (DOB). Source, version (RUN_STATS.source.datasetUpdatedAt,
sourceUpdatedAt per record) and the modifications are stated in the README.