Back to home
REST API

API Documentation

Access Toronto zoning data programmatically. Look up any address and get back effective standards, development potential, GIS layers, and more. The same data that powers the web app.

Base URL

https://toronto-zoning-production.up.railway.app

All endpoints accept and return JSON. Every endpoint requires a signed-in account — create one free and send your session token as a Bearer credential. Calls without one return 401 sign_in_required.

Quick Start

Look up zoning data for any Toronto address with a single API call:

curl -X POST https://toronto-zoning-production.up.railway.app/lookup \
  -H "Content-Type: application/json" \
  -d '{"address": "226 Viewmount Ave"}'
POST

/lookup

The primary endpoint. Returns a complete zoning profile for a Toronto address including effective standards, development potential, GIS layers, and constraints.

Request Body

addressrequiredstringToronto street address (e.g. "226 Viewmount Ave")
include_parcelbooleanInclude property boundary geometry. Default: true
include_nearbybooleanInclude nearby development activity. Default: false
include_policybooleanInclude policy conformity analysis. Default: false
lot_area_sqmnumberOverride lot area (useful for assembly scenarios)
lot_frontage_mnumberOverride lot frontage
lot_depth_mnumberOverride lot depth
proposed_usestringProposed use to analyze (e.g. "restaurant", "dwelling unit")

Response

{
  "address": "226 Viewmount Ave",
  "coordinates": { "latitude": 43.65633, "longitude": -79.43123 },
  "effective_standards": {
    "zone_code": "RD",
    "zone_string": "RD (f12.0; a325) (x123)",
    "height": { "effective_m": 10, "effective_storeys": 3, "effective_source": "base_zone" },
    "fsi": { "effective_total": 0.6, "effective_source": "base_zone" },
    "lot_coverage": { "effective_pct": 35, "effective_source": "base_zone" },
    "setbacks": { "effective_front_m": 6.0, "effective_rear_m": 7.5, "effective_side_m": 1.2 },
    "exception": { "exception_number": 123 },
    "heritage_impact": { "has_heritage": false },
    "natural_hazards": { "has_hazards": false }
  },
  "development_potential": {
    "lot": { "area_sqm": 325, "frontage_m": 12.0, "depth_m": 27.1 },
    "max_gfa": { "sqm": 195, "limiting_factor": "lot_coverage" },
    "height": { "max_m": 10, "max_storeys": 3 },
    "setbacks": { "buildable_area_sqm": 195 },
    "confidence": { "overall_score": 85, "overall_confidence": "high", "grade": "A" }
  },
  "layers": {
    "zoning_area": [ ... ],
    "heritage_register": [ ... ],
    "major_transit_station_area": [ ... ]
  },
  "policy_conformity": { ... },
  "zoning_statistics_table": { ... }
}
POST

/suggest

Address autocomplete. Returns matching Toronto addresses for typeahead search.

Request Body

textrequiredstringPartial address text (minimum 3 characters)
max_suggestionsnumberMaximum results to return. Default: 8
curl -X POST https://toronto-zoning-production.up.railway.app/suggest \
  -H "Content-Type: application/json" \
  -d '{"text": "226 view"}'

// Response
{
  "suggestions": [
    "226 Viewmount Ave",
    "226 View North Rd",
    ...
  ]
}
POST

/lookup/batch

Look up multiple addresses in a single request (up to 50).

Request Body

addressesrequiredstring[]Array of Toronto addresses (max 50)
include_parcelbooleanInclude property boundaries. Default: true
include_nearbybooleanInclude nearby activity. Default: false
max_concurrencynumberMax parallel lookups. Default: 10
curl -X POST https://toronto-zoning-production.up.railway.app/lookup/batch \
  -H "Content-Type: application/json" \
  -d '{
    "addresses": [
      "226 Viewmount Ave",
      "100 Queen St W",
      "1 Yonge St"
    ]
  }'

// Response
{
  "results": [ ... ],
  "total": 3,
  "success_count": 3,
  "error_count": 0,
  "total_ms": 2340
}
POST

/analyze-use

Check if a specific use is permitted in a zone. Returns conditions, parking requirements, and by-law references.

Request Body

userequiredstringThe use to analyze (e.g. "restaurant", "dwelling unit", "retail store")
reportrequiredobjectFull zoning report object (from /lookup response)
// First, get a zoning report
const report = await fetch("https://toronto-zoning-production.up.railway.app/lookup", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ address: "100 Queen St W" })
}).then(r => r.json());

// Then check use eligibility
const analysis = await fetch("https://toronto-zoning-production.up.railway.app/analyze-use", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    use: "restaurant",
    report: report
  })
}).then(r => r.json());
POST

/analyze-use/list

List all available uses that can be analyzed for a given zone family.

curl -X POST https://toronto-zoning-production.up.railway.app/analyze-use/list \
  -H "Content-Type: application/json" \
  -d '{"zone_family": "CR"}'

// Response
{
  "uses": ["amusement arcade", "art gallery", "artist studio", "bar", ...]
}
POST

/reference

Fetch by-law text, exception details, SASP policies, or zone information.

Request Body

typerequiredstring"bylaw-section", "exception", "sasp", "op-designation", or "zone-info"
idrequiredstringSection ID, exception number, or policy reference
zone_codestringZone code for context (optional)
curl -X POST https://toronto-zoning-production.up.railway.app/reference \
  -H "Content-Type: application/json" \
  -d '{"type": "exception", "id": "123"}'

// Response
{
  "found": true,
  "title": "Exception 123",
  "text": "Despite regulation 10.20.40.10(1), the maximum ...",
  "data": { ... }
}
GET

/map/metadata

List all available GIS layers with styling information. Useful for building map UIs.

curl https://toronto-zoning-production.up.railway.app/map/metadata

// Response
{
  "layers": [
    {
      "key": "zoning_area",
      "label": "Zoning Areas",
      "color": "#3b82f6",
      "weight": 2,
      "fillOpacity": 0.15,
      "group": "Zoning"
    },
    ...
  ]
}
GET

/map/layers/{layer_key}

Get GeoJSON features for a specific GIS layer within a radius of a coordinate.

Query Parameters

lonrequirednumberLongitude
latrequirednumberLatitude
radiusnumberRadius in degrees. Default: 0.005
curl "https://toronto-zoning-production.up.railway.app/map/layers/zoning_area?lon=-79.431&lat=43.656&radius=0.005"

// Response: GeoJSON FeatureCollection
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": { "type": "Polygon", "coordinates": [...] },
      "properties": {
        "ZONE_CODE": "RD",
        "ZONE_LABEL": "Residential Detached",
        ...
      }
    }
  ]
}
GET

/nearby-activity

Nearby development activity: building permits, Committee of Adjustment applications, and rezoning applications.

Query Parameters

lonrequirednumberLongitude
latrequirednumberLatitude
radiusnumberRadius in metres. Default: 500
limitnumberMax events to return. Default: 50
event_typestringFilter by type: "permit", "coa", "rezoning"
curl "https://toronto-zoning-production.up.railway.app/nearby-activity?lon=-79.431&lat=43.656&radius=500"

// Response
{
  "center": { "lon": -79.431, "lat": 43.656 },
  "radius_m": 500,
  "total": 12,
  "by_type": { "permit": 8, "coa": 3, "rezoning": 1 },
  "events": [ ... ]
}
POST

/dev-charges/calculate

Estimate development charges for a proposed project based on unit counts and building type.

Request Body

units_bachelornumberNumber of bachelor units
units_2plusnumberNumber of 2+ bedroom units
units_lowrisenumberNumber of low-rise units
units_single_seminumberNumber of single/semi units
non_residential_gfa_sqmnumberNon-residential GFA in m²
is_purpose_built_rentalbooleanIs this purpose-built rental? (affects exemptions)
curl -X POST https://toronto-zoning-production.up.railway.app/dev-charges/calculate \
  -H "Content-Type: application/json" \
  -d '{
    "units_2plus": 6,
    "is_purpose_built_rental": false
  }'

// Response
{
  "city_dc": { "items": [...], "subtotal": 142800 },
  "education_dc": { "items": [...], "subtotal": 18600 },
  "go_transit_dc": { ... },
  "exemptions_applied": [],
  "total_estimated": 168420
}

Usage Notes

  • The API is free during the beta period. Rate limits may be introduced in the future.
  • Responses are cached for up to 1 hour. Identical requests will return cached results.
  • Data is sourced from the City of Toronto Open Data Portal. This is not legal advice.
  • Batch requests are limited to 50 addresses per call.

Ready to integrate?

Create a free account to get a token, then start making calls.