Agriculture
Read parcel-level agriculture intelligence and render agriculture map layers.
On this page
Agriculture Parcel Reports
Soil, capability, crop rotation, and land-use data for any quarter section in AB, SK, and MB. LSD inputs resolve up to their quarter section.
Example request
curl --get "https://developer.townshipcanada.com/ag/report" \
-H "X-API-Key: $TOWNSHIP_API_KEY" \
--data-urlencode "legal_location=NW-11-5-6-W2"Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| legal_location | string | Required | Quarter section or LSD (LSDs resolve up to their quarter section) NW-11-5-6-W2 |
| include | string | Optional | Comma-separated sections to return (omit for the full report). Only the requested sections are queried. geometry attaches the parcel polygon soil,drought,geometryproductivity , cropping , soil , land_use , drought , wetlands , hydrology , parcel_context , provincial_detail , geometry |
Example Response
{
"legal_location": "NW-11-5-6-W2",
"resolved_legal_location": "NW-11-5-6-W2",
"grain": "quarter_section",
"province": "SK",
"parcel": { "area_ha": 64.75, "centroid": { "lat": 50.36, "lng": -104.65 }, "geometry": null },
"productivity": {
"lsrs": { "score": 62, "class": "3", "limiter": "M - Moisture" },
"cli": { "score": 60, "class": "3", "limiter": "M" }
},
"cropping": {
"dominant": { "code": "146", "name": "Spring Wheat", "category": "Cereal" },
"rotation": "Wheat-Canola",
"diversity_index": 0.6412,
"years_covered": 10
},
"soil": {
"classification": { "order": "Chernozemic", "great_group": "Dark Brown Chernozem", "subgroup_code": "Orthic Dark Brown Chernozem" },
"drainage_class": "Well drained",
"slope_class": "2-5%"
},
"land_use": {
"dominant": { "code": "51", "label": "Annual cropland", "ipcc_class": "Cropland" },
"breakdown": [{ "code": "51", "label": "Annual cropland", "ipcc_class": "Cropland", "pct": 88.2 }]
},
"drought": { "class": "D1", "severity_label": "Moderate Drought", "as_of": "2026-07" },
"wetlands": null,
"hydrology": {
"watercourse": { "name": "Wascana Creek", "distance_m": 240, "is_on_parcel": false },
"water_body": { "name": null, "distance_m": null, "is_on_parcel": false, "on_parcel_pct": null },
"search_radius_m": 500
},
"parcel_context": { "municipality": { "name": "Sherwood No. 159", "type": "Rural Municipality" } },
"provincial_detail": { "crown_land": [], "soils": [], "pastures": [] },
"units": { "area": "ha", "distance": "m" },
"meta": {
"unavailable": [{ "section": "wetlands", "reason": "not_published_in_province" }],
"sources": { "...": "..." }
}
}Vector Tiles
The Agriculture bundle's 18 map layers as vector tiles: soils, capability, crop rotation, Crown land, pastures, and the ALR. Served from the maps CDN, authenticated with an api_key query parameter.
Tile URL Pattern
https://maps.townshipcanada.com/ag/{archive}/{z}/{x}/{y}.mvt?api_key=... https://maps.townshipcanada.com/ag/{archive}.json?api_key=... (TileJSON) Available Archives
The source layer is the layer name inside the tile - MapLibre needs it in source-layer, and it does not always match the archive name. Anything outside this list returns 403.
| Archive | Source Layer | Zoom | Layer |
|---|---|---|---|
ag_summary_qs | ag_summary | z9-22 | Ag Summary (quarter section) |
ag_summary_sec | ag_summary_sec | z6-9 | Ag Summary (section rollup) |
ag_summary_twp | ag_summary_twp | z0-6 | Ag Summary (township rollup) |
aafc_crop_summary | crops | z9-22 | Crops (quarter section) |
aafc_crop_summary_sec | crops_sec | z6-9 | Crops (section rollup) |
aafc_crop_summary_twp | crops_twp | z0-6 | Crops (township rollup) |
soils | soils | z6-22 | Soil Landscapes of Canada |
lsrs_productivity | lsrs | z9-22 | Productivity / LSRS (quarter section) |
lsrs_productivity_sec | lsrs_sec | z6-9 | Productivity / LSRS (section rollup) |
lsrs_productivity_twp | lsrs_twp | z0-6 | Productivity / LSRS (township rollup) |
bc_ag_capability | bc_ag_capability | z6-22 | BC Agricultural Capability |
sk_ag_crown_land | sk_ag_crown_land | z6-22 | SK Agricultural Crown Land |
sk_ag_crown_land_labels | sk_ag_crown_land | z10+ | SK Agricultural Crown Land (labels) |
sk_pastures | sk_pastures | z4-22 | SK Pastures |
sk_pastures_labels | sk_pastures | z8+ | SK Pastures (labels) |
bc_alr | bc_alr | z4-22 | BC Agricultural Land Reserve |
bc_alr_labels | bc_alr | z10+ | BC Agricultural Land Reserve (labels) |
bc_fwa_wetlands | bc_fwa_wetlands | z6-22 | BC Freshwater Atlas Wetlands |
Zoom-Banded Rollup Families
ag_summary, aafc_crop_summary, and lsrs_productivity each ship as three archives covering different zoom bands - quarter-section geometry is far too dense to draw at province scale. Add all three as separate sources and let the zoom ranges hand off; a client that adds only the detail archive sees an empty map below z9.
| Zoom | Archive | Granularity |
|---|---|---|
| z0-6 | _twp | Township (6 x 6 miles) |
| z6-9 | _sec | Section (1 x 1 mile) |
| z9+ | base archive (_qs / _lsd / no suffix) | Quarter section / LSD |
The _labels archives are the same footprint rendered as a label layer - add them as their own source alongside the geometry archive when you want text.
MapLibre Usage
const KEY = "YOUR_API_KEY";
const base = "https://maps.townshipcanada.com/ag";
// Ag Summary is a zoom-banded family: add all three sources.
// A client that adds only the detail archive sees an empty map below z9.
map.addSource("ag-summary-twp", {
type: "vector",
tiles: [`${base}/ag_summary_twp/{z}/{x}/{y}.mvt?api_key=${KEY}`],
minzoom: 0,
maxzoom: 6
});
map.addSource("ag-summary-sec", {
type: "vector",
tiles: [`${base}/ag_summary_sec/{z}/{x}/{y}.mvt?api_key=${KEY}`],
minzoom: 6,
maxzoom: 9
});
map.addSource("ag-summary-qs", {
type: "vector",
tiles: [`${base}/ag_summary_qs/{z}/{x}/{y}.mvt?api_key=${KEY}`],
minzoom: 9,
maxzoom: 14
});
map.addLayer({
id: "ag-summary-qs-fill",
type: "fill",
source: "ag-summary-qs",
"source-layer": "ag_summary", // note: not the archive name
minzoom: 9,
paint: { "fill-color": "#41ab5d", "fill-opacity": 0.6 }
});
// TileJSON works too, and carries the bounds and zoom range
map.addSource("soils", {
type: "vector",
url: `${base}/soils.json?api_key=${KEY}`
});