If you own or manage property in New York City, a DOT sidewalk violation can show up with almost no warning. Under NYC Administrative Code §7-210, the property owner is responsible for sidewalk repairs, and once a violation is issued, there is a fixed window to correct it before the city steps in and does the work at a much higher cost.
Most owners find out about a violation by mail or by manually digging through NYC's Open Data portal. As developers, we can do better. NYC publishes its DOT sidewalk violation records as a public dataset, queryable through a REST API. In this tutorial, we will build a small tool that checks whether a given NYC address has an open sidewalk violation, using nothing but a browser, JavaScript, and a free public API.
The Dataset: DOT Sidewalk Violations
The dataset we need is called Sidewalk Management Database - Violations, published by the NYC Department of Transportation on the NYC Open Data portal (built on the Socrata platform). It covers sidewalk violation records across all five boroughs.
A few fields matter most for our checker:
- house_num and frstname — the house number and street name of the violation location
- trip_haz — flagged when the defect is a trip hazard
- grace_pd — the grace period (in days) given to fix the issue
- vissuedate — the date the violation was issued
- vdismissdate — populated only once the violation is closed or dismissed
- violationid — a unique ID for the record
- bblid — the borough-block-lot ID, useful if you want to cross-reference against other city property datasets
An open violation is any record where vdismissdate is empty. That single distinction is really the whole logic of our checker.
Setting Up the API Request
NYC Open Data exposes this table through the Socrata Open Data API (SODA) as JSON, no authentication required for light use:
https://data.cityofnewyork.us/resource/6kbp-uz6m.json
You can filter results using SoQL (Socrata Query Language) directly in the query string. Here's a simple lookup by house number and street name:
async function checkAddress(houseNum, streetName) {
const base = "https://data.cityofnewyork.us/resource/6kbp-uz6m.json";
const where = `house_num='${houseNum}' AND upper(frstname) like upper('%${streetName}%')`;
const url = `${base}?$where=${encodeURIComponent(where)}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Open Data request failed: ${response.status}`);
}
return response.json();
}
For production use, register for a free app token on the NYC Open Data developer portal and pass it as a header. Anonymous requests work fine for testing, but they're rate-limited more aggressively.
const response = await fetch(url, {
headers: { "X-App-Token": "YOUR_APP_TOKEN" }
});
Parsing the Results
Once you have the raw records, the useful work is turning them into a human answer: open, closed, or none on file.
function summarizeViolations(records) {
if (records.length === 0) {
return { status: "none", violations: [] };
}
const open = records.filter(r => !r.vdismissdate);
return {
status: open.length > 0 ? "open" : "closed",
violations: records.map(r => ({
id: r.violationid,
issued: r.vissuedate,
gracePeriodDays: r.grace_pd,
tripHazard: r.trip_haz === "X",
dismissed: r.vdismissdate || null
}))
};
}
The tripHazard check works because DOT marks defect-type columns like trip_haz with an "X" when that condition applies, and leaves them blank otherwise. That pattern shows up across most of the defect columns in this table (broken, patchwork, undermined, and so on), so the same logic extends easily if you want to surface the specific type of defect.
Building a Minimal Front End
A basic form is enough to make this usable for a non-technical owner:
<form id="checker-form">
<input type="text" id="houseNum" placeholder="House number" required="" />
<input type="text" id="streetName" placeholder="Street name" required="" />
<button type="submit">Check Address</button></form>
<div id="result"></div>
<script>
document.getElementById("checker-form").addEventListener("submit", async (e) => {
e.preventDefault();
const houseNum = document.getElementById("houseNum").value.trim();
const streetName = document.getElementById("streetName").value.trim();
const resultDiv = document.getElementById("result");
resultDiv.textContent = "Checking...";
try {
const records = await checkAddress(houseNum, streetName);
const summary = summarizeViolations(records);
if (summary.status === "none") {
resultDiv.textContent = "No sidewalk violations on file for this address.";
} else if (summary.status === "open") {
resultDiv.textContent = `Open violation(s) found: ${summary.violations.length}`;
} else {
resultDiv.textContent = "All violations on file for this address are closed.";
}
} catch (err) {
resultDiv.textContent = "Something went wrong. Please try again.";
}
});
</script>
That's a working, if bare-bones, violation checker. From here you could add borough filtering, map the bblid to a lot info dataset for owner records, or cache results locally to cut down on repeat API calls.
A Note on Data Accuracy
DOT records street names using its own internal formatting (for example, "7 AVENUE" rather than "7th Ave"), so exact-match queries can miss results if the input doesn't follow that convention. The like and upper() functions in the example above help with partial matches, but for a production tool it's worth normalizing user input against DOT's standard street naming conventions, or offering an autocomplete pulled from the same dataset. The table is also maintained by DOT and updated on a rolling basis as inspections close out and new violations are issued, so treat any result as a snapshot rather than a live feed.
What to Do If You Find an Open Violation
If your checker turns up an open violation, the clock is already running. Owners typically have a limited window (75 days from issuance under current DOT enforcement) to complete repairs before the city can do the work itself and bill the owner at a significantly higher rate.
At that point, it stops being a coding problem. NY Vanta Contractors handles NYC sidewalk violation repairs end to end, including DOT permit coordination and the final sign-off needed to close out the violation record. If you're building tools like this for your own property or for clients, it's worth having a contractor reference on hand for exactly this step.
Visual Mockup of the Sidewalk Violation Checker
The user enters the NYC address and the tool pulls DOT's public sidewalk violation records to show whether that property has an open violation, when it was issued, and how many days remain in the grace period before the city can step in and bill the owner directly.

FAQ
Is this dataset updated in real time? No. It reflects DOT's inspection and closeout process, so there can be a lag between a violation being resolved on-site and the record being marked dismissed.
Does this work for all five boroughs? Yes, the dataset covers sidewalk violations citywide.
Is a violation the same as a 311 complaint? No. A 311 complaint is how a defect gets reported; a DOT violation is the formal notice issued after inspection. They're related but tracked in different datasets.
Conclusion
The NYC Open Data API turns what used to be a manual portal search into a five-minute scripting exercise. Whether you're building this for a personal project, a real estate tool, or a client-facing app, the same pattern (query by address, check for an open dismiss date, surface the defect type) extends to most of DOT's other public inspection datasets as well.
