NYC Business Licenses - Inspections, Violations, Complaints
Pricing
from $0.06 / 1,000 nyc dcwp records
NYC Business Licenses - Inspections, Violations, Complaints
NYC DCWP's licensing ecosystem (public open data): 72.5K licences, 65.9K applications, 278K field inspections, 137K violations with their Admin Code charge and hearing outcome, and 76.5K consumer complaints - all linked by business id, so one lookup returns a business's whole regulatory record.
Pricing
from $0.06 / 1,000 nyc dcwp records
Rating
0.0
(0)
Developer
Wenhao Yang
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
Low cost
From $0.0001 per record, down to $0.00006 at Gold - pay per record delivered, and nothing for the query. Cost scales with what you pull, not with the size of the register.
New York City's Department of Consumer and Worker Protection licensing ecosystem. Not just a licence list: the applications behind the licence, the inspections of the premises, the charges that came out of those inspections, and the consumer complaints filed against the business - five tables, all resolved on one business id.
What you get
| Table | Rows | What it holds |
|---|---|---|
| licenses | 72,452 | current licences: status, category, licence type, address with BIN/BBL/community board |
| applications | 65,932 | new and renewal applications: intake channel, submission and closure, temporary-operation letters |
| inspections | 277,976 | field inspections: type (patrol, tobacco sale-to-minor, scale, sweep), status, outcome |
| violations | 137,316 | the charge itself - the Admin Code or Public Health Law section cited - with the hearing outcome and disposition flags |
| complaints | 76,527 | consumer complaints: 311 channel, result, and any refund or contract-cancellation amount |
Modes
- licenses (default) / applications / inspections / violations / complaints
- business - everything above for one business id, in one response
- aggregate - counts by status, category, charge, outcome
A business query turns five separate datasets into one answer: this business holds these licences, applied on these dates, was inspected here, was charged under these sections, and had these complaints - with the outcome of each.
Example inputs
One business, all five tables - mode=business resolves the id across licences, applications, inspections, violations and complaints in one response.
{ "mode": "business", "businessId": "BA-1786461-2026" }
Active tobacco licences in one borough - category and borough are substring matches; licenseStatus is the exact published value.
{ "licenseStatus": "Active", "category": "Tobacco","borough": "Brooklyn", "maxResults": 100 }
Charges that were pleaded - mode=violations with the exact hearing outcome.
{ "mode": "violations", "outcome": "Pleaded", "maxResults": 100 }
What the city inspects most - mode=aggregate counts one row per group.
{ "mode": "aggregate", "corpus": "inspections", "groupBy": "inspectionType" }
Why this is hard
The five tables spell the same facts differently. The building number is address_building on one, building_number on the next, building_no on the third and building_nbr on the fourth; ZIP is address_zip / zip / zip_code / postcode. Nothing joins unless you know each table's spelling. Expiry dates carry sentinel rows dated 2100 - and because an expiry date in the future is the normal state of an active licence (44,099 of them), a naive date ceiling deletes every valid licence in the register while keeping the junk. The complaint table is the only one missing the business id on some rows (2,497 of them), so the join has to tolerate gaps rather than drop them.
Output
One schema across all five tables - every record carries the full key set, empty where the table has nothing to say. Dates arrive as YYYY-MM-DD.
Notes
- Public open data from NYC Open Data. No login, no scraping.
- DCWP publishes this because it is the city's consumer-protection record - who is licensed, and what they did with the licence.
- Charges are metered per record delivered, so pulling one business's record costs a fraction of a cent.
Example output
One licence - businessId=BA-1786461-2026 on the default licenses mode. Every record carries the full key set; the columns the table has nothing to say about come back "", and the aggregate columns (groupKey, groupCount, groupBy) are "" outside aggregate mode:
{"platform": "nyc-dcwp","source": "nyc-dcwp-licenses","corpus": "licenses","recordKind": "license","mode": "licenses","groupKey": "", "groupCount": "", "groupBy": "","businessId": "BA-1786461-2026","businessName": "Paceline Consults Inc","dbaTradeName": "","businessCategory": "Debt Collection Agency","licenseNumber": "2136952-DCWP","licenseType": "Premises","licenseStatus": "Active","licenseCreationDate": "2026-08-19","licenseExpirationDate": "2027-01-31","detail": "","contactPhone": "(212) 812-2995","addressType": "Complete Address","addressBuilding": "225","addressStreet": "W 34TH ST","addressStreet2": "","addressCity": "NEW YORK","addressState": "NY","addressZip": "10122","addressBorough": "Manhattan","communityBoard": "105","councilDistrict": "03","bin": "1014402","bbl": "1007840019","nta": "MN17","censusTract": "109","latitude": "40.751483","longitude": "-73.991764","applicationId": "", "applicationType": "", "intakeChannel": "", "submissionDate": "", "applicationStatus": "", "dateClosed": "","tempOpLetterIssued": "", "tempOpLetterExpiration": "", "certificateOfInspection": "","inspectionNumber": "", "dateOfOccurrence": "", "dcwpLicenseNumber": "", "inspectionType": "", "inspectionStatus": "","nohNumber": "", "recordId": "", "relatedRecordType": "", "violationDate": "", "charge": "", "chargeCount": "","cureEligible": "", "cured": "", "outcome": "", "guilty": "", "notGuilty": "", "dismissed": "","intakeDate": "", "serviceRequestNumber": "", "complaintCode": "", "resultDate": "", "result": "", "referredTo": "","contractCancelledAmount": "", "refundAmount": "","sourceUpdatedAt": "2026-08-20"}