Documentation menu
Docs / Reference / Search planning applications

Search planning applications

GET/planning_application

Parameters

ParameterTypeDescription
municipalitystringoptionalFilter to one city by its slug, e.g. 'new_westminster', 'toronto', 'north_vancouver_city'. Exact match. This is the city filter for BuildData datasets (permits, development permits, planning applications, inspections); call /{entity_type}/coverage for the list of valid slugs. The 'city' param is accepted as an alias here. (For the US liquor/healthcare/tank datasets, 'city' is instead a distinct filter and 'municipality' does not apply.)
qstringoptionalFull-text search across the indexed fields of the record, including names (business, establishment, vendor, contractor) wherever the dataset carries them, e.g. q=brewery or q="Iron Hill". This is the name search: there is no separate name= parameter, and it works on every plan including free. It matches the BUSINESS or trade name, the address, city, county and licence/permit number. It does NOT match an owner, licensee or applicant's personal name: these datasets carry public business records only and never store an individual's name, so searching for a person returns nothing. Space-separated words require all terms (e.g. "wood panel"). Use OR to match any term ("wood OR panel OR acoustic"), quotes for exact phrases ("supply arrangement"), and a leading minus to exclude ("software -hardware").
statusstringoptionalFilter by status. Contracts/tenders: Active, Expired, Cancelled, Open (exact). Permits: use a status_canonical value instead (issued, in_review, completed, expired, cancelled, unknown).
status_canonicalstringoptionalNormalized permit status: issued, in_review, completed, expired, cancelled, unknown
citystringoptionalFilter by city. For the US liquor/healthcare/storage-tank datasets this is a distinct filter (exact, case-insensitive). For all other datasets it is an alias 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: published (publication_date, tenders only), date (event date; this is award_date for contracts/awards), value (the entity's value field), closing (closing_date for tenders)
sort_orderstringoptionalSort order: asc or desc
limitintegeroptional
offsetintegeroptional
cursorstringoptionalPagination cursor from next_cursor in a previous response. Use instead of offset for deep pagination.

Request

curl --request GET \
  --url 'https://builddata-canadian-construction-data-api.p.rapidapi.com/planning_application' \
  --header 'x-rapidapi-host: builddata-canadian-construction-data-api.p.rapidapi.com' \
  --header 'x-rapidapi-key: YOUR_RAPIDAPI_KEY'
import requests

url = "https://builddata-canadian-construction-data-api.p.rapidapi.com/planning_application"
headers = {"x-rapidapi-host": "builddata-canadian-construction-data-api.p.rapidapi.com", "x-rapidapi-key": "YOUR_RAPIDAPI_KEY"}
resp = requests.get(url, headers=headers)
print(resp.json())
const res = await fetch("https://builddata-canadian-construction-data-api.p.rapidapi.com/planning_application", {
  headers: {
    "x-rapidapi-host": "builddata-canadian-construction-data-api.p.rapidapi.com",
    "x-rapidapi-key": "YOUR_RAPIDAPI_KEY",
  },
});
const data = await res.json();
console.log(data);
<?php
$ch = curl_init("https://builddata-canadian-construction-data-api.p.rapidapi.com/planning_application");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "x-rapidapi-host: builddata-canadian-construction-data-api.p.rapidapi.com",
    "x-rapidapi-key: YOUR_RAPIDAPI_KEY",
]);
echo curl_exec($ch);
require "net/http"
require "uri"

uri = URI("https://builddata-canadian-construction-data-api.p.rapidapi.com/planning_application")
req = Net::HTTP::Get.new(uri)
req["x-rapidapi-host"] = "builddata-canadian-construction-data-api.p.rapidapi.com"
req["x-rapidapi-key"] = "YOUR_RAPIDAPI_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://builddata-canadian-construction-data-api.p.rapidapi.com/planning_application", nil)
    req.Header.Add("x-rapidapi-host", "builddata-canadian-construction-data-api.p.rapidapi.com")
    req.Header.Add("x-rapidapi-key", "YOUR_RAPIDAPI_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://builddata-canadian-construction-data-api.p.rapidapi.com/planning_application"))
    .header("x-rapidapi-host", "builddata-canadian-construction-data-api.p.rapidapi.com")
    .header("x-rapidapi-key", "YOUR_RAPIDAPI_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 planning_application record. Measured over 5,867 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 96% of sampled records.
applicantstringPopulated in 17% of sampled records.
applicant_namestringPopulated in 13% of sampled records.
application_datestringPopulated in 94% of sampled records.
application_subtypestringAlways present.
application_typestringPopulated in 31% of sampled records.
application_type_codestringPopulated in 10% of sampled records.
application_urlstringPopulated in 12% of sampled records.
categorystringPopulated in 14% of sampled records.
decision_datestringPopulated in 11% of sampled records.
descriptionstringPopulated in 84% of sampled records.
fetched_atstringWhen Nimbus last ingested this record. Bookkeeping, not source data. Always present.
folder_typestringPopulated in 14% of sampled records.
latstringPopulated in 12% of sampled records.
lngstringPopulated in 12% of sampled records.
municipalitystringCity slug. Call /{entity_type}/coverage for every slug in this dataset. Always present.
neighborhoodstringPopulated in 20% of sampled records.
normalized_addressstringAddress normalized for joining the same property across datasets. Populated in 96% of sampled records.
permit_typestringPopulated in 26% of sampled records.
pipeline_stagestringPopulated in 89% of sampled records.
provincestringAlways present.
record_idstringStable identifier for this record. Pass it to the /{entity_type}/{record_id} endpoint. Always present.
record_numberstringPopulated in 93% of sampled records.
statusstringPopulated in 97% of sampled records.
status_canonicalstringStatus mapped onto a shared vocabulary. This is what the status_canonical filter matches. Populated in 97% of sampled records.
wardstringPopulated in 24% of sampled records.
97 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
additional_scopestring0.1%
agentstring0.1%
agent_namestring3.2%
appealedstring0.5%
application_numberinteger3.4%
application_scopestring3.2%
application_type_frstring3.4%
approval_datestring1.2%
approved_datestring1.1%
approved_total_unitsinteger1.5%
benchmark_daysinteger3.4%
benchmark_metstring3.4%
character_areastring3.4%
city_plannerstring2.9%
city_webstring1.7%
communitystring6.8%
community_meeting_datestring0.8%
community_planstring3.4%
condo_numberstring0.1%
construction_typestring2.0%
contactstring1.7%
contact_namestring3.2%
council_decision_datestring0.7%
council_meeting_datestring3.1%
council_report_urlstring0.3%
current_land_usestring3.4%
current_zoningstring3.2%
days_to_processinteger3.4%
deemed_complete_datestring5.2%
demand_idstring3.4%
detail_urlstring3.4%
districtstring3.4%
documents_linkstring0.5%
domainstring3.4%
dwelling_units_createdstring3.4%
dwelling_units_loststring3.4%
engage_urlstring2.8%
existing_zoningstring0.9%
folder_descriptionstring6.8%
folder_namestring3.4%
folder_rsnstring3.4%
folderrsninteger3.4%
geocode_failedboolean0.5%
gis_linkstring3.4%
heritage_designationstring0.1%
inside_mtsastring3.4%
inspectorstring3.4%
intended_usestring2.1%
issue_datestring0.2%
issued_datestring1.3%
latitudestring3.4%
layerstring6.8%
legal_descriptionstring3.4%
longitudestring3.4%
lotsstring3.4%
major_usestring2.2%
max_storeysinteger1.7%
meeting_datestring0.0%
mtsa_namestring3.4%
municipality_namestring3.3%
neighbourhoodstring3.4%
non_residential_gfa_m2integer3.4%
normalized_business_namestring0.0%
opa_numberstring1.0%
parent_folder_numberstring1.5%
plannerstring6.7%
planner_emailstring3.4%
planner_namestring3.3%
postalstring4.9%
proposed_land_usestring3.4%
proposed_total_unitsinteger2.9%
proposed_usestring6.0%
proposed_use_codestring3.4%
proposed_zoningstring3.2%
public_meeting_datestring0.1%
public_status_descriptionstring2.8%
published_datestring3.4%
record_typestring3.4%
reference_filestring0.3%
regional_numberstring0.1%
registered_residential_lotsstring0.0%
residential_unitsinteger3.4%
sectorstring3.4%
status_datestring3.4%
subcategorystring3.4%
subdivision_numberstring0.2%
titlestring3.4%
updated_datestring3.4%
ward_idinteger3.4%
ward_namestring3.4%
ward_numberstring3.4%
web_linkstring0.9%
weblinkstring3.4%
year_of_applicationinteger3.4%
year_quarterstring2.0%
zba_numberstring2.7%
zonestring3.4%

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?Subscribe on RapidAPI to get your key and start calling BuildData in minutes.
Get your API key →