Documentation menu
Docs / Reference / Search building inspections

Search building inspections

GET/inspection

Parameters

ParameterTypeDescription
municipalitystringoptionalFilter to one city by its slug, e.g. 'new_westminster', 'toronto', 'north_vancouver_city'.Exact match. The dataset's /coverage endpoint lists the valid slugs. 'city' is accepted as an alias.
qstringoptionalFull-text search across the indexed fields of the record, e.g. q=roofing or q="Iron Hill".Matches business, contractor and project names, the address, the city and the permit or licence number, on every plan including free. It does not match a person's name: these datasets carry business records only. Space-separated words require all terms ("deck addition"). Use OR to match any term ("pool OR spa"), quotes for an exact phrase ("secondary suite"), and a leading minus to exclude ("renovation -interior").
contractorstringoptionalFilter permits by the firm that pulled them.A whole name is matched exactly against the normalized contractor name and is indexed; a fragment falls back to a substring across the contractor, company and builder fields. Cities file the same firm under several spellings, so the normalized form is the one that groups them.
structure_typestringoptionalFilter by structure or building type as the city publishes it (exact, case-insensitive), e.g. 'Single Family Dwelling', 'Hotel'.Call /permit/stats for the values in use.
neighbourhoodstringoptionalFilter by neighbourhood (partial match).Matches whichever of neighborhood, neighbourhood or community the city publishes; Calgary calls it community.
wardstringoptionalFilter by electoral ward as the city publishes it (exact, case-insensitive).
statusstringoptionalPermits: the normalized status (issued, in_review, completed, expired, cancelled, unknown), same as status_canonical.Major projects: proposed, under_construction, complete, on_hold, cancelled. Business licences: the status the city publishes, e.g. APPROVED, case-insensitive. Other datasets: the status as the city publishes it.
citystringoptionalAlias for municipality.
issued_afterstringoptionalFilter by date >= YYYY-MM-DD (issued_date).Aliases: date_from, date_after
issued_beforestringoptionalFilter by date <= YYYY-MM-DD.Aliases: date_to, date_before
latnumberoptionalLatitude for proximity search.Send with lng.
lngnumberoptionalLongitude for proximity search.Send with lat.
radius_kmnumberoptionalRadius in km, 0.1 to 25.Optional: lat and lng with no radius search 1 km around the point. The radius actually applied is returned as radius_km in the response, so a default is never silent. For every record at one street address rather than everything near it, use /property.
sort_bystringoptionalSort field: date (the record's own date, e.g. issued_date for permits) or value (the field value_min reads).
sort_orderstringoptionalSort order: asc or desc
limitintegeroptionalRecords per page, 1 to 500.Free-tier keys are capped lower; the cap applied is the `count` in the response.
offsetintegeroptionalRecords to skip. Fine for jumping to a known page;use `cursor` to walk a whole result set, because offset re-reads everything it skips and shifts when new records arrive.
cursorstringoptionalPagination cursor from next_cursor in a previous response.Use instead of offset for deep pagination.

Request

curl --request GET \
  --url 'https://api.builddata.ca/inspection' \
  --header 'X-API-Key: YOUR_API_KEY'
import requests

url = "https://api.builddata.ca/inspection"
headers = {"X-API-Key": "YOUR_API_KEY"}
resp = requests.get(url, headers=headers)
print(resp.json())
const res = await fetch("https://api.builddata.ca/inspection", {
  headers: {
    "X-API-Key": "YOUR_API_KEY",
  },
});
const data = await res.json();
console.log(data);
<?php
$ch = curl_init("https://api.builddata.ca/inspection");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "X-API-Key: YOUR_API_KEY",
]);
echo curl_exec($ch);
require "net/http"
require "uri"

uri = URI("https://api.builddata.ca/inspection")
req = Net::HTTP::Get.new(uri)
req["X-API-Key"] = "YOUR_API_KEY"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
puts res.body
package main

import (
    "fmt"
    "io"
    "net/http"
)

func main() {
    req, _ := http.NewRequest("GET", "https://api.builddata.ca/inspection", nil)
    req.Header.Add("X-API-Key", "YOUR_API_KEY")
    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()
    body, _ := io.ReadAll(res.Body)
    fmt.Println(string(body))
}
import java.net.URI;
import java.net.http.*;

HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://api.builddata.ca/inspection"))
    .header("X-API-Key", "YOUR_API_KEY")
    .build();
HttpResponse<String> res = HttpClient.newHttpClient()
    .send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());

Example response

{
  "entity_type": "permit",
  "count": 1,
  "offset": 0,
  "results": [
    {
      "record_id": "24 223023 PLB:00",
      "municipality": "toronto",
      "lat": 43.65401,
      "lng": -79.42376,
      "work": "Building Permit Related(PS)",
      "status": "Permit Issued",
      "address": "865 COLLEGE ST",
      "description": "Plumbing - INTERIOR ALTERNATION OF 3RD FLOOR SUITE",
      "issued_date": "2025-01-29",
      "permit_type": "Plumbing(PS)",
      "application_date": "2024-10-07",
      "construction_value": null
    }
  ]
}

Response fields

One inspection record. Measured over 800 live records sampled across municipalities. Percentages say how often each field is populated: sources publish different columns, so a field missing from a given record is normal rather than an error.

FieldTypeDescription
addressstringPopulated in 50% of sampled records.
checkliststringPopulated in 19% of sampled records.
created_datestringPopulated in 25% of sampled records.
deficienciesbooleanPopulated in 19% of sampled records.
deficiencystringPopulated in 19% of sampled records.
discipline_typestringPopulated in 25% of sampled records.
enforcementbooleanPopulated in 25% of sampled records.
fetched_atstringWhen Nimbus last ingested this record. Bookkeeping, not source data. Always present.
inspection_datestringAlways present.
inspection_idstringPopulated in 25% of sampled records.
inspection_typestringAlways present.
issued_datestringPopulated in 19% of sampled records.
job_typestringPopulated in 19% of sampled records.
latnumberPopulated in 47% of sampled records.
lngnumberPopulated in 47% of sampled records.
municipalitystringCity slug. Call /{entity_type}/coverage for every slug in this dataset. Always present.
normalized_addressstringAddress normalized for joining the same property across datasets. Populated in 50% of sampled records.
permit_close_datestringPopulated in 19% of sampled records.
permit_namestringPopulated in 25% of sampled records.
permit_numberstringPopulated in 75% of sampled records.
property_typestringPopulated in 25% of sampled records.
provincestringAlways present.
record_idstringStable identifier for this record. Pass it to the /{entity_type}/{record_id} endpoint. Always present.
resultstringAlways present.
statusstringPopulated in 25% of sampled records.
violation_codestringPopulated in 13% of sampled records.
violation_descriptionstringPopulated in 12% of sampled records.
violation_itemstringPopulated in 25% of sampled records.
wardstringPopulated in 25% of sampled records.
9 more fields published by only one or two cities

Present on under 10% of records. Useful when you are working with a specific city, not something to rely on across the dataset.

FieldTypePopulated
applicant_typestring5.9%
closed_datestring4.4%
contractorstring5.5%
deficiency_resolvedboolean1.4%
general_contractorstring0.0%
normalized_business_namestring5.5%
permit_typestring5.9%
resolved_datestring1.4%
work_classstring5.9%

Errors

Every error returns {"detail": "…"}, a sentence naming what was wrong and, where there is one, the fix.

StatusWhen
400The request is understood but cannot be served as asked, e.g. offset above 9500, or cursor combined with sort_by=value. The message names the fix.
403Missing or invalid API key.
404No such endpoint, or no record with that id.
422A parameter is invalid: an unknown city slug, an impossible date, a limit above 500, an unrecognised sort field, or a misspelled parameter name. The message names the parameter and, where there is one, the nearest valid value.
429Rate limit or plan quota exceeded.
500Unexpected server error.
504The query took too long. Narrow it with a municipality or a date range.
Ready to build?Create a free key and start calling BuildData in minutes. No card required.
Get your API key →