Demographic data ships as areas. Addresses are points. Everything painful about using the two together comes from that one sentence.
You want to know the income mix, household types, and languages around a list of addresses. It sounds like an afternoon of work. It is not. You need to get the boundary files, match the boundary vintage to the data vintage, reproject both into a coordinate system where a point-in-polygon test actually means something, handle the areas that are suppressed for privacy because too few people live in them, and then decide what to do with the addresses that land on a boundary line.
Then you finish, and it is correct. And it stays correct for about a year.
That last part is the one that gets people. The join is a project. The rerun is a job. Boundaries get redrawn, data gets refreshed, new addresses get built, and the pipeline you wrote in March quietly drifts away from reality while you are busy doing something else. Somebody on your team now owns that drift forever.
What Houski returns instead
Houski holds 123 demographic fields, already joined to every address in the country, and keeps them current. You do not run a spatial join. You ask for the fields you want and they come back on the same row as the property.
The block below is a live call against the real API. The request and the response are generated every time this page renders, so they always reflect the current schema and current data:
const houski_data = async (): Promise<PropertiesResponse> => {
// You must copy the PropertiesResponse type declarations from the
// Houski API documentation to strongly type the response
const url = new URL('https://api.houski.ca/properties');
url.searchParams.set('api_key', 'YOUR_API_KEY');
url.searchParams.set('city', 'calgary');
url.searchParams.set('country_abbreviation', 'ca');
url.searchParams.set('province_abbreviation', 'ab');
url.searchParams.set('results_per_page', '5');
url.searchParams.set('select', 'address,city,postal_code,demographic_income_median_after_tax,demographic_age_median_of_the_population,demographic_household_type_family_with_children_percent,demographic_language_most_spoken_first');
const response = await fetch(url);
const data = await response.json();
return data;
}
(async () => {
let data: PropertiesResponse = await houski_data();
// Log the response
console.log(data);
})();
{
"cache_hit": false,
"cost_cents": 2.1999998092651367,
"data": [
{
"address": "31 Hawkside Park NW",
"city": "Calgary",
"demographic_age_median_of_the_population": 60.79999923706055,
"demographic_household_type_family_with_children_percent": 0.21621622145175937,
"demographic_income_median_after_tax": 53248,
"demographic_language_most_spoken_first": "English",
"postal_code": "T3G2W3",
"property_id": "10000f97f5cb7b9f"
},
{
"address": "6 1744 7 Street SW",
"city": "Calgary",
"demographic_age_median_of_the_population": 34.79999923706055,
"demographic_household_type_family_with_children_percent": 0.08695652335882187,
"demographic_income_median_after_tax": 55296,
"demographic_language_most_spoken_first": "English",
"postal_code": "T2T2W6",
"property_id": "10004f7afe0c1946"
},
{
"address": "384 Copperpond Landng SE",
"city": "Calgary",
"demographic_age_median_of_the_population": 33.599998474121094,
"demographic_household_type_family_with_children_percent": 0.3670886158943176,
"demographic_income_median_after_tax": 59904,
"demographic_language_most_spoken_first": "English",
"postal_code": "T2Z1G6",
"property_id": "10007f9761f49940"
},
{
"address": "239 Dalhurst Way NW",
"city": "Calgary",
"demographic_age_median_of_the_population": 37.20000076293945,
"demographic_household_type_family_with_children_percent": 0.36000001430511475,
"demographic_income_median_after_tax": 52224,
"postal_code": "T3A1P3",
"property_id": "100086f6bc064d3f"
},
{
"address": "52 Cedargrove Way SW",
"city": "Calgary",
"demographic_age_median_of_the_population": 39.599998474121094,
"demographic_household_type_family_with_children_percent": 0.2374100685119629,
"demographic_income_median_after_tax": 50176,
"demographic_language_most_spoken_first": "English",
"postal_code": "T2W4V2",
"property_id": "1000c277cd905d3b"
}
],
"error": "",
"pagination": {
"current_page": 1,
"has_next_page": true,
"has_previous_page": false,
"page_total": 136188
},
"price_quote": false,
"result_total": 680936,
"time_ms": 171,
"ui_info": {
"city": "Calgary",
"city_id": "6ec95b53075d062c",
"city_link": "ca/ab/calgary",
"city_slug": "calgary",
"country": "Canada",
"country_abbreviation": "CA",
"country_abbreviation_id": "9ace2b6431b7f1be",
"country_abbreviation_link": "ca",
"country_slug": "canada",
"province": "Alberta",
"province_abbreviation": "AB",
"province_abbreviation_id": "aae1f05a0f89d2c7",
"province_abbreviation_link": "ca/ab",
"province_slug": "alberta"
}
}
That is the whole integration. No boundary files, no reprojection, no vintage matching.
What is actually in there
The 123 fields group into a handful of families:
Income - median and average, both pre-tax and after-tax, plus the full distribution in buckets from under 10,000 dollars up to 150,000 and over.
Households - size, from one person to five or more. Type, split across family with children, family without children, single with children, and single without children.
Age - every five-year band from 0 to 4 up through 100 and over, plus the median and average of the population.
Language - the five most spoken languages in the area, each with the share of people who speak it. The names come back as values, not codes, so demographic_language_most_spoken_first returns something you can read.
Education - highest level reached, from no certificate through to earned doctorate, plus field of study for degree holders.
Employment - employed and unemployed shares, industry across all 20 industry groups, and occupation across all 10 occupation groups.
Transportation - how people get to work, split across car, public transit, bicycle, and walking.
Marital status, population density, and dwelling occupancy round it out.
For the complete list with descriptions, see the fields reference.
Two things you need to know before you use this
These are neighbourhood values, not household values. Houski does not know the income of the person living at 123 Main Street, and neither does anyone else who is being honest with you. What Houski knows is the income profile of the area around 123 Main Street. That distinction matters legally and it matters practically. Target neighbourhoods with it. Do not pretend it is a profile of a person.
The percent fields are fractions, not whole numbers. A value of 0.20 means 20 percent. This trips people up on their first filter, so filter on 0.20, not on 20.
One more subtlety worth knowing: the income composition fields, like demographic_employment_income_percent, are shares of total income in the area, not shares of residents. An area where employment income is 0.85 gets 85 percent of its total income from employment. It does not mean 85 percent of people have a job. That is what demographic_employment_employed_percent is for.
Filtering on it
The demographic fields are filterable like anything else, using the standard operators. Here is every property in Calgary in an area where the median after-tax income of residents clears 70,000 dollars and more than a quarter of households are families with children:
const houski_data = async (): Promise<PropertiesResponse> => {
// You must copy the PropertiesResponse type declarations from the
// Houski API documentation to strongly type the response
const url = new URL('https://api.houski.ca/properties');
url.searchParams.set('api_key', 'YOUR_API_KEY');
url.searchParams.set('city', 'calgary');
url.searchParams.set('country_abbreviation', 'ca');
url.searchParams.set('demographic_household_type_family_with_children_percent_gte', '0.25');
url.searchParams.set('demographic_income_median_after_tax_gte', '70000');
url.searchParams.set('province_abbreviation', 'ab');
url.searchParams.set('results_per_page', '25');
url.searchParams.set('select', 'address,postal_code,community,property_type,demographic_income_median_after_tax,demographic_household_type_family_with_children_percent,estimate_sale_price');
const response = await fetch(url);
const data = await response.json();
return data;
}
(async () => {
let data: PropertiesResponse = await houski_data();
// Log the response
console.log(data);
})();
{
"cache_hit": false,
"cost_cents": 8.749999046325684,
"data": [
{
"address": "6619 34 Street SW",
"community": "Lakeview",
"demographic_household_type_family_with_children_percent": 0.3478260934352875,
"demographic_income_median_after_tax": 75776,
"estimate_sale_price": 1009562,
"postal_code": "T3E5M3",
"property_id": "10014f3c7e5bfad9",
"property_type": "House"
},
{
"address": "432 27 Avenue NW",
"community": "Mount Pleasant",
"demographic_household_type_family_with_children_percent": 0.3653846085071564,
"demographic_income_median_after_tax": 73216,
"estimate_sale_price": 1166097,
"postal_code": "T2M2H6",
"property_id": "10021e44aa219b00",
"property_type": "House"
},
{
"address": "241 Tuscany Reserve Rise NW",
"community": "Tuscany",
"demographic_household_type_family_with_children_percent": 0.6875,
"demographic_income_median_after_tax": 73216,
"estimate_sale_price": 817736,
"postal_code": "T3L0A4",
"property_id": "1006595dbb3b58b6",
"property_type": "House"
},
{
"address": "94 Mahogany Gr SE",
"community": "Mahogany",
"demographic_household_type_family_with_children_percent": 0.5128205418586731,
"demographic_income_median_after_tax": 72192,
"estimate_sale_price": 913661,
"postal_code": "T3M3E1",
"property_id": "1006fb838f0cff42",
"property_type": "Apartment"
},
{
"address": "24 Westmore Place SW",
"community": "West Springs",
"demographic_household_type_family_with_children_percent": 0.5308641791343689,
"demographic_income_median_after_tax": 76288,
"estimate_sale_price": 1036326,
"postal_code": "T3H0Z2",
"property_id": "100d5a823a3ca83e",
"property_type": "House"
},
{
"address": "157 Cougar Ridge Close SW",
"community": "Cougar Ridge",
"demographic_household_type_family_with_children_percent": 0.7101449370384216,
"demographic_income_median_after_tax": 74752,
"estimate_sale_price": 907821,
"postal_code": "T3H0V4",
"property_id": "1013f1896836eb1d",
"property_type": "House"
},
{
"address": "2609 7 Avenue NW",
"community": "West Hillhurst",
"demographic_household_type_family_with_children_percent": 0.4000000059604645,
"demographic_income_median_after_tax": 75776,
"estimate_sale_price": 1825725,
"postal_code": "T2N1A6",
"property_id": "10177efba3636a6b",
"property_type": "House"
},
{
"address": "103 Pumpmeadow Place SW",
"community": "Pump Hill",
"demographic_household_type_family_with_children_percent": 0.42222222685813904,
"demographic_income_median_after_tax": 86400,
"estimate_sale_price": 1812323,
"postal_code": "T2V5C9",
"property_id": "101b24f83c50a76f",
"property_type": "House"
},
{
"address": "118 Tuscany Ravine Close NW",
"community": "Tuscany",
"demographic_household_type_family_with_children_percent": 0.6382978558540344,
"demographic_income_median_after_tax": 75776,
"estimate_sale_price": 889724,
"postal_code": "T3L2Y5",
"property_id": "101c9c533be3310a",
"property_type": "House"
},
{
"address": "4010 16 Street SW",
"community": "Altadore",
"demographic_household_type_family_with_children_percent": 0.4634146392345429,
"demographic_income_median_after_tax": 81920,
"estimate_sale_price": 761213,
"postal_code": "T2T4H4",
"property_id": "101d384958060b6a",
"property_type": "House"
},
{
"address": "36 68 Baycrest Place SW",
"community": "Bayview",
"demographic_household_type_family_with_children_percent": 0.42222222685813904,
"demographic_income_median_after_tax": 86400,
"estimate_sale_price": 1426399,
"postal_code": "T2V0K6",
"property_id": "101d9c6ee5cf31e6",
"property_type": "Duplex"
},
{
"address": "1712 47 Avenue SW",
"community": "Altadore",
"demographic_household_type_family_with_children_percent": 0.4430379867553711,
"demographic_income_median_after_tax": 88960,
"estimate_sale_price": 1030243,
"postal_code": "T2T2S2",
"property_id": "101ed0b92f7eba88",
"property_type": "House"
},
{
"address": "178 Aspen Summit Circle SW",
"community": "Aspen Woods",
"demographic_household_type_family_with_children_percent": 0.7924528121948242,
"demographic_income_median_after_tax": 74752,
"estimate_sale_price": 2075958,
"postal_code": "T3H0Z6",
"property_id": "101f5afc31e62bf6",
"property_type": "House"
},
{
"address": "638 Lake Simcoe Close SE",
"community": "Lake Bonavista",
"demographic_household_type_family_with_children_percent": 0.4838709533214569,
"demographic_income_median_after_tax": 71168,
"estimate_sale_price": 1452017,
"postal_code": "T2J5H6",
"property_id": "101f5dfb752a318b",
"property_type": "House"
},
{
"address": "19 1202 Street NW",
"community": "Beltline",
"demographic_household_type_family_with_children_percent": 0.43589743971824646,
"demographic_income_median_after_tax": 81408,
"estimate_sale_price": 795442,
"postal_code": "T2N2J7",
"property_id": "1020f7c057e903e8",
"property_type": "House"
},
{
"address": "204 Tuscany Valley Gr NW",
"community": "Tuscany",
"demographic_household_type_family_with_children_percent": 0.6875,
"demographic_income_median_after_tax": 73216,
"estimate_sale_price": 697489,
"postal_code": "T3L2M2",
"property_id": "102458962e824e6e",
"property_type": "House"
},
{
"address": "30 68 Baycrest Place SW",
"community": "Bayview",
"demographic_household_type_family_with_children_percent": 0.42222222685813904,
"demographic_income_median_after_tax": 86400,
"estimate_sale_price": 1425119,
"postal_code": "T2V0K6",
"property_id": "1026985d0bdd1d5f",
"property_type": "Duplex"
},
{
"address": "7 Tuscany Meadows Crescent NW",
"community": "Tuscany",
"demographic_household_type_family_with_children_percent": 0.6382978558540344,
"demographic_income_median_after_tax": 75776,
"estimate_sale_price": 736527,
"postal_code": "T3L2T9",
"property_id": "1026e067f9960c63",
"property_type": "House"
},
{
"address": "444 20 Avenue Northwest",
"community": "Beltline",
"demographic_household_type_family_with_children_percent": 0.3103448152542114,
"demographic_income_median_after_tax": 72704,
"estimate_sale_price": 620611,
"postal_code": "T3M3H1",
"property_id": "102702d77ba4532e",
"property_type": "House"
},
{
"address": "3420 7 Street SW",
"community": "Elbow Park",
"demographic_household_type_family_with_children_percent": 0.48275861144065857,
"demographic_income_median_after_tax": 107520,
"estimate_sale_price": 1436850,
"postal_code": "T2T2X9",
"property_id": "10278392d4e8cc49",
"property_type": "House"
},
{
"address": "88 Auburn Glen Gardens Southeast",
"community": "Beltline",
"demographic_household_type_family_with_children_percent": 0.6602563858032227,
"demographic_income_median_after_tax": 71680,
"estimate_sale_price": 729991,
"postal_code": "T3M3H1",
"property_id": "102fa05e4dc00baa",
"property_type": "House"
},
{
"address": "231 Parkvalley Drive SE",
"community": "Parkland",
"demographic_household_type_family_with_children_percent": 0.3461538553237915,
"demographic_income_median_after_tax": 70656,
"estimate_sale_price": 812799,
"postal_code": "T2J4V2",
"property_id": "1032e0aab660ccc1",
"property_type": "House"
},
{
"address": "2033 46 Avenue SW",
"community": "Altadore",
"demographic_household_type_family_with_children_percent": 0.5076923370361328,
"demographic_income_median_after_tax": 87040,
"estimate_sale_price": 1801613,
"postal_code": "T2T2S1",
"property_id": "1034eaa73b558210",
"property_type": "House"
},
{
"address": "102 Auburn Sound Manor SE",
"community": "Auburn Bay",
"demographic_household_type_family_with_children_percent": 0.7298387289047241,
"demographic_income_median_after_tax": 75776,
"estimate_sale_price": 1165099,
"postal_code": "T3M0R6",
"property_id": "103501832404ccb5",
"property_type": "House"
},
{
"address": "2019 47 Avenue SW",
"community": "Altadore",
"demographic_household_type_family_with_children_percent": 0.48571428656578064,
"demographic_income_median_after_tax": 87680,
"estimate_sale_price": 1209806,
"postal_code": "T2T2S7",
"property_id": "10392f1e43d2525d",
"property_type": "House"
}
],
"error": "",
"pagination": {
"current_page": 1,
"has_next_page": true,
"has_previous_page": false,
"page_total": 1109
},
"price_quote": false,
"result_total": 27724,
"time_ms": 164,
"ui_info": {
"city": "Calgary",
"city_id": "6ec95b53075d062c",
"city_link": "ca/ab/calgary",
"city_slug": "calgary",
"country": "Canada",
"country_abbreviation": "CA",
"country_abbreviation_id": "9ace2b6431b7f1be",
"country_abbreviation_link": "ca",
"country_slug": "canada",
"province": "Alberta",
"province_abbreviation": "AB",
"province_abbreviation_id": "aae1f05a0f89d2c7",
"province_abbreviation_link": "ca/ab",
"province_slug": "alberta"
}
}
You can stack demographic filters against property filters in the same query, which is where this gets useful. The demographics tell you who is nearby. The property fields tell you what they live in. Neither is worth much alone.
const houski_data = async (): Promise<PropertiesResponse> => {
// You must copy the PropertiesResponse type declarations from the
// Houski API documentation to strongly type the response
const url = new URL('https://api.houski.ca/properties');
url.searchParams.set('api_key', 'YOUR_API_KEY');
url.searchParams.set('city', 'calgary');
url.searchParams.set('construction_year_lte', '1985');
url.searchParams.set('country_abbreviation', 'ca');
url.searchParams.set('demographic_income_median_after_tax_gte', '80000');
url.searchParams.set('property_type_eq', 'House');
url.searchParams.set('province_abbreviation', 'ab');
url.searchParams.set('results_per_page', '25');
url.searchParams.set('select', 'address,postal_code,construction_year,interior_sq_m,heating_type_first,demographic_income_median_after_tax,demographic_age_median_of_the_population');
const response = await fetch(url);
const data = await response.json();
return data;
}
(async () => {
let data: PropertiesResponse = await houski_data();
// Log the response
console.log(data);
})();
{
"cache_hit": false,
"cost_cents": 13.249999046325684,
"data": [
{
"address": "4010 16 Street SW",
"construction_year": 1971,
"demographic_age_median_of_the_population": 36.79999923706055,
"demographic_income_median_after_tax": 81920,
"heating_type_first": "In-floor",
"interior_sq_m": 172.28726196289062,
"postal_code": "T2T4H4",
"property_id": "101d384958060b6a"
},
{
"address": "3420 7 Street SW",
"construction_year": 1945,
"demographic_age_median_of_the_population": 45.20000076293945,
"demographic_income_median_after_tax": 107520,
"heating_type_first": "Gas furnace",
"interior_sq_m": 167.96730041503906,
"postal_code": "T2T2X9",
"property_id": "10278392d4e8cc49"
},
{
"address": "2033 46 Avenue SW",
"construction_year": 1954,
"demographic_age_median_of_the_population": 37.20000076293945,
"demographic_income_median_after_tax": 87040,
"heating_type_first": "In-floor",
"interior_sq_m": 172.28726196289062,
"postal_code": "T2T2S1",
"property_id": "1034eaa73b558210"
},
{
"address": "2019 47 Avenue SW",
"construction_year": 1954,
"demographic_age_median_of_the_population": 38.0,
"demographic_income_median_after_tax": 87680,
"heating_type_first": "In-floor",
"interior_sq_m": 172.28726196289062,
"postal_code": "T2T2S7",
"property_id": "10392f1e43d2525d"
},
{
"address": "1219 18 Street NW",
"construction_year": 1953,
"demographic_age_median_of_the_population": 41.20000076293945,
"demographic_income_median_after_tax": 81408,
"heating_type_first": "Gas furnace",
"interior_sq_m": 123.74581909179688,
"postal_code": "T2N2G8",
"property_id": "10564fb894e319b0"
},
{
"address": "1308 Kerwood Crescent SW",
"construction_year": 1966,
"demographic_age_median_of_the_population": 41.599998474121094,
"demographic_income_median_after_tax": 94080,
"heating_type_first": "Gas furnace",
"interior_sq_m": 143.90560913085938,
"postal_code": "T2V2N6",
"property_id": "1075a9b22021a573"
},
{
"address": "4019 14A Street SW",
"construction_year": 1957,
"demographic_age_median_of_the_population": 45.599998474121094,
"demographic_income_median_after_tax": 90240,
"heating_type_first": "In-floor",
"interior_sq_m": 172.28726196289062,
"postal_code": "T2T3Y3",
"property_id": "1098a1621243024"
},
{
"address": "1120 Frontenac Avenue SW",
"construction_year": 1910,
"demographic_age_median_of_the_population": 45.20000076293945,
"demographic_income_median_after_tax": 107520,
"heating_type_first": "In-floor",
"interior_sq_m": 246.0052032470703,
"postal_code": "T2T1B6",
"property_id": "10cbf68817603752"
},
{
"address": "9015 Bay Ridge Drive SW",
"construction_year": 1972,
"demographic_age_median_of_the_population": 51.599998474121094,
"demographic_income_median_after_tax": 86400,
"heating_type_first": "Gas furnace",
"interior_sq_m": 286.464111328125,
"postal_code": "T2V0N8",
"property_id": "10d06718101cd68"
},
{
"address": "4120 15 Street SW",
"construction_year": 1957,
"demographic_age_median_of_the_population": 45.599998474121094,
"demographic_income_median_after_tax": 90240,
"heating_type_first": "In-floor",
"interior_sq_m": 172.28726196289062,
"postal_code": "T2T4A9",
"property_id": "1104db85d69cd5d0"
},
{
"address": "723 Willard Road SE",
"construction_year": 1971,
"demographic_age_median_of_the_population": 52.337364196777344,
"demographic_income_median_after_tax": 80553,
"heating_type_first": "Gas furnace",
"interior_sq_m": 190.44964599609375,
"postal_code": "T2J2A4",
"property_id": "1127c4909e2febd1"
},
{
"address": "1312 70 Avenue SW",
"construction_year": 1959,
"demographic_age_median_of_the_population": 41.599998474121094,
"demographic_income_median_after_tax": 94080,
"heating_type_first": "Gas furnace",
"interior_sq_m": 143.90560913085938,
"postal_code": "T2V0R3",
"property_id": "11326166bd745168"
},
{
"address": "868 Hillcrest Avenue SW",
"construction_year": 1926,
"demographic_age_median_of_the_population": 45.20000076293945,
"demographic_income_median_after_tax": 107520,
"heating_type_first": "In-floor",
"interior_sq_m": 246.0052032470703,
"postal_code": "T2T0Y9",
"property_id": "115a2281a8b8c7b9"
},
{
"address": "4304 15 Street SW",
"construction_year": 1956,
"demographic_age_median_of_the_population": 45.599998474121094,
"demographic_income_median_after_tax": 90240,
"heating_type_first": "In-floor",
"interior_sq_m": 172.28726196289062,
"postal_code": "T2T4B2",
"property_id": "116a74938fbb0458"
},
{
"address": "1103 39 Avenue SW",
"construction_year": 1958,
"demographic_age_median_of_the_population": 45.599998474121094,
"demographic_income_median_after_tax": 90240,
"heating_type_first": "Gas furnace",
"interior_sq_m": 167.96730041503906,
"postal_code": "T2T2K6",
"property_id": "1197808da57966b3"
},
{
"address": "3808 13 Street SW",
"construction_year": 1952,
"demographic_age_median_of_the_population": 45.599998474121094,
"demographic_income_median_after_tax": 90240,
"heating_type_first": "Gas furnace",
"interior_sq_m": 167.96730041503906,
"postal_code": "T2T3R3",
"property_id": "11aea6368d473d79"
},
{
"address": "2315 8 Street SW",
"construction_year": 1929,
"demographic_age_median_of_the_population": 45.20000076293945,
"demographic_income_median_after_tax": 107520,
"heating_type_first": "In-floor",
"interior_sq_m": 246.0052032470703,
"postal_code": "T2T3A1",
"property_id": "11edf2b5be1e7b47"
},
{
"address": "1203 Council Way SW",
"construction_year": 1948,
"demographic_age_median_of_the_population": 45.20000076293945,
"demographic_income_median_after_tax": 107520,
"heating_type_first": "Gas furnace",
"interior_sq_m": 110.64659881591795,
"postal_code": "T2T1X6",
"property_id": "11fbc49f7a9aba0f"
},
{
"address": "59 Bay View Drive SW",
"construction_year": 1971,
"demographic_age_median_of_the_population": 51.599998474121094,
"demographic_income_median_after_tax": 86400,
"heating_type_first": "Gas furnace",
"interior_sq_m": 286.464111328125,
"postal_code": "T2V3N9",
"property_id": "12015c3e324d63e"
},
{
"address": "1722 6 Avenue NW",
"construction_year": 1911,
"demographic_age_median_of_the_population": 41.20000076293945,
"demographic_income_median_after_tax": 81408,
"heating_type_first": "Gas furnace",
"interior_sq_m": 142.0475616455078,
"postal_code": "T2N0W2",
"property_id": "120ccfbf461cd0b3"
},
{
"address": "704 Willamette Drive SE",
"construction_year": 1972,
"demographic_age_median_of_the_population": 53.20000076293945,
"demographic_income_median_after_tax": 81920,
"heating_type_first": "Gas furnace",
"interior_sq_m": 253.8089904785156,
"postal_code": "T2J2A2",
"property_id": "1226717dbe4d7ff8"
},
{
"address": "1915 Bay Shore Road SW",
"construction_year": 1967,
"demographic_age_median_of_the_population": 51.599998474121094,
"demographic_income_median_after_tax": 86400,
"heating_type_first": "Gas furnace",
"interior_sq_m": 292.82794189453125,
"postal_code": "T2V3M3",
"property_id": "1236c3e19ef91a89"
},
{
"address": "3832 6 Street SW",
"construction_year": 1914,
"demographic_age_median_of_the_population": 43.745635986328125,
"demographic_income_median_after_tax": 80686,
"heating_type_first": "Gas furnace",
"interior_sq_m": 167.96730041503906,
"postal_code": "T2S2M8",
"property_id": "1237ebbf825955c5"
},
{
"address": "1715 48 Avenue SW",
"construction_year": 1956,
"demographic_age_median_of_the_population": 38.0,
"demographic_income_median_after_tax": 88960,
"heating_type_first": "In-floor",
"interior_sq_m": 172.28726196289062,
"postal_code": "T2T2T2",
"property_id": "12767ff66e71fe52"
},
{
"address": "3903 Crestview Road SW",
"construction_year": 1961,
"demographic_age_median_of_the_population": 45.599998474121094,
"demographic_income_median_after_tax": 90240,
"heating_type_first": "Gas furnace",
"interior_sq_m": 316.6573791503906,
"postal_code": "T2T2L5",
"property_id": "127e0f3ec4016277"
}
],
"error": "",
"pagination": {
"current_page": 1,
"has_next_page": true,
"has_previous_page": false,
"page_total": 67
},
"price_quote": false,
"result_total": 1658,
"time_ms": 179,
"ui_info": {
"city": "Calgary",
"city_id": "6ec95b53075d062c",
"city_link": "ca/ab/calgary",
"city_slug": "calgary",
"country": "Canada",
"country_abbreviation": "CA",
"country_abbreviation_id": "9ace2b6431b7f1be",
"country_abbreviation_link": "ca",
"country_slug": "canada",
"province": "Alberta",
"province_abbreviation": "AB",
"province_abbreviation_id": "aae1f05a0f89d2c7",
"province_abbreviation_link": "ca/ab",
"province_slug": "alberta"
}
}
Older houses, in areas with the income to renovate them. That query is a contractor's entire prospect list, and it took one request.
The use cases are the point
Once demographics live on the address, a surprising number of jobs collapse into a single query.
Direct mail is the cleanest fit, because mail is addressed to a dwelling rather than to a person. You do not need anyone's name, and you do not need a list broker. You pick the streets worth mailing and you mail them. Filter on the demographic mix that matches your customer, export the addresses, hand them to your printer.
Choosing where to spend on any geographic channel. Flyer drops, door knocking, canvassing routes, local radio, out-of-home placement. Anything you currently buy by city, you can buy by neighbourhood instead.
Site selection. Where does a new location go? Childcare wants families with children. A pharmacy wants an older age profile. A bike shop wants demographic_transportation_bicycle_percent to be high. Each of those is a filter.
Service area planning. A trades business deciding which neighbourhoods to serve, weighing drive time against the density of houses that match its work.
Language-aware outreach. demographic_language_most_spoken_first through fifth tells you where a translated mailer or a bilingual rep will actually land.
Market sizing before you launch. How many households in this province live in the profile I sell to? That is a count, not a study.
Feature engineering. If you are training a model, these are 123 pre-joined features per address. The part of the project you were dreading is already done.
The pre-built version
If you want the output rather than the query, the datasets page has the census and demographics category already assembled, along with 90 or so others. Language communities, single-parent households, empty nesters and retirees, public transit commuters, university-educated areas, trades-certified workforce, cycling communities, high population density. Each one is a filter someone already wrote, delivered as a comma-separated values or JSON export that drops into Snowflake, BigQuery, Databricks, Power BI, or a notebook.
They update daily, which is the part that matters. The list you pull in July is not the list you pulled in March, because the country changed and the data changed with it.
If the cut you need is not there, our data team builds custom datasets - combining fields, applying your filters, developing analytics specific to your business - delivered in your format on your schedule. Ask us for one.
Where the data comes from
The demographic data is assembled from public, government, and crowdsourced data sources, cleaned and conformed across every province so a field means the same thing in Halifax as it does in Victoria. That conforming step is most of the work and all of the value. Raw sources disagree with each other constantly, and reconciling them is the reason this is a product rather than a download.
Getting started
- Sign up for API access and get a key
- Pick your demographic profile from the fields reference
- Build the filter using the filtering guide
- Test on one city before you scale it nationally
- Export to mail, to your customer system, or to your model
Most fields cost a tenth of a cent per field per property, so a 10,000 address pull with 10 fields runs about 100 dollars, and there is a 99 dollar monthly minimum. Add price_quote to any request to see the cost before you commit to it. Full detail on the pricing page.
The spatial join is a solved problem. It just was not solved for you, and it was never going to stay solved. Explore the API documentation or browse the datasets page to see what is already built.
