!

Targeting heat pump rebate programs at scale with Canadian property data

Photo of Alex Wilkinson
Alex Wilkinson
CEO of Houski
2026-05-11

The federal Greener Homes Loan has fully committed its funding envelope and the new-application portal closed in late 2025, with approved loans continuing to fund through their full disbursement schedule. The Oil to Heat Pump Affordability Program is winding down through 2026 and 2027, according to Natural Resources Canada, with most provincial co-delivery arrangements requiring participant registration by mid-2026 and project completion by March 31, 2027. Provincial programs in Quebec, British Columbia, Nova Scotia, New Brunswick, and Ontario are layered on top, each with its own eligibility envelope. The combined annual outreach budget across federal, provincial, and utility-funded programs is now in the hundreds of millions of dollars.

That money buys postcards, door knockers, radio spots, search ads, and an awful lot of contractor co-marketing. A meaningful share of it lands in front of homeowners who already installed a cold climate heat pump two winters ago, or who heat with electric resistance in a 400 square metre lakefront house that is never going to qualify for an income-tested grant. Program managers know this. They have known it for years. The constraint has not been awareness, it has been a way to tell, at the parcel level, which Canadian homes are actually pre-qualified retrofit candidates and which ones are not.

This post is about closing that gap. Specifically, how to use Houski's property data to score every home in a service territory, then build outreach lists, budget allocations, and progress reports off the same underlying dataset. It is written for the people running these programs, not the contractors chasing the leads they generate.

The broad-stroke marketing problem, in numbers

Pick any utility or program admin you like and the funnel looks something like this. You start with the total dwelling count in your service territory. Call it three million homes. Of those, a meaningful share are apartments, condos, or rentals where the tenant cannot authorize a system swap. Another share already heat with electricity. Another share already installed a heat pump in the last cycle. Another share are above any reasonable income threshold for a needs-based grant. Another share heat with natural gas in a region where gas is still the cheapest fuel after carbon pricing math, so the payback story does not pencil.

By the time you peel all of that away, the genuinely targetable population for an oil-to-heat-pump program in Atlantic Canada might be 60,000 to 90,000 homes. For an income-qualified electric resistance retrofit in Quebec it might be 150,000. For a gas furnace retrofit in southern Ontario it might be 400,000.

If your outreach is hitting all three million, your cost per qualified contact is roughly 30 to 50 times your cost per piece. If your outreach is hitting only the 60,000 to 400,000 that actually convert, your cost per acquired participant collapses, your budget stretches further, and your year-over-year market share numbers for the program board start looking like the slide you wanted to present.

The leverage is in the targeting. The targeting requires data that exists at the parcel level, covers the full country, and updates often enough that last decade's heating system swap shows up before you mail the homeowner a flyer telling them to do the swap.

What programmatic targeting actually needs

A scoring engine for heat pump retrofit suitability is not complicated in concept. For each home in the country, you want a small set of attributes:

  • Current heating equipment type. Gas furnace, electric furnace, heat pump, hot water, radiant, geothermal, or unknown. Fuel is not a direct field, so legacy oil-era systems are targeted through equipment class plus construction vintage plus region.
  • Equipment vintage. When was the current system installed.
  • Building envelope vintage. What construction year, which is a reasonable proxy for insulation, window quality, and air sealing in the absence of a blower door test.
  • Building size. Floor area in square metres, used for sizing the proposed system and estimating retrofit cost.
  • Income proxy. The most defensible non-personal proxy is the median after-tax income for the surrounding area, which lets you tier outreach without ever touching individual financial records.
  • Geographic identifiers. Postal code, Forward Sortation Area, city, province, latitude, longitude. These let you join to climate zone, utility service territory, and program rule sets.

Houski exposes every one of these as a queryable field on the /properties endpoint. The fields you will lean on most are heating_type_first, heating_install_year_first, heating_brand_first, construction_year, interior_sq_m, gas_provider, electricity_provider, demographic_income_median_after_tax, postal_code, city, province_abbreviation, latitude, and longitude. The heating_type_first field uses values like Gas furnace, Electric furnace, Heat pump, Hot water, In-floor, Radiant, Electric, Geothermal, and Fireplace, so query filters need to match those exact tokens.

What follows is how to use them.

Example one, sizing the Oil to Heat Pump Affordability Program in Nova Scotia

The Oil to Heat Pump Affordability Program targets households that heat primarily with home heating oil. Atlantic Canada has the highest oil-heat penetration in the country, and Nova Scotia in particular has been a focus province since the program launched. Before you can budget outreach, you need a defensible count of how many oil-heated homes actually exist in the province, broken down by community.

The /aggregate endpoint returns one aggregation per call, scoped to a country, province, city, or community, and the regular filter operators stack on top. To get the per-city oil-heat dwelling count for Nova Scotia, you call /aggregate once per Nova Scotia city you care about. Pull the city list from the /location endpoint and loop. The block below is a live call against the real API, showing the underlying per-city aggregate that the loop would repeat:

API request
Python code
from dataclasses import dataclass
from dataclasses_json import dataclass_json
import requests

params = {}
params['aggregation'] = 'count'
params['api_key'] = 'YOUR_API_KEY'
params['city'] = 'halifax'
params['construction_year_lte'] = '1990'
params['country_abbreviation'] = 'ca'
params['field'] = 'property_id'
params['heating_type_first_eq'] = 'Hot water'
params['province_abbreviation'] = 'ns'

response = requests.get('https://api.houski.ca/aggregate', params=params)

if response.status_code == 200:
    json_data = response.json()

    print(json_data)

    # You must copy the AggregateResponse type declarations from the 
    # Houski API documentation to strongly type the response
    typed_response = AggregateResponse.from_dict(json_data)

    # Log the response
    print(typed_response)
else:
    print(f'Failed to get data: {response}')
API response
JSON
{
  "cache_hit": false,
  "cost_cents": 1.0,
  "data": [
    {
      "aggregation": "count",
      "field": "property_id",
      "value": "43"
    }
  ],
  "error": "",
  "price_quote": false,
  "time_ms": 76
}

The response gives you the candidate dwelling count for that one city. The heating_type_first enum captures the system class (Hot water, Gas furnace, Electric furnace, Heat pump, Electric, In-floor, Radiant, Geothermal, Fireplace, None) rather than the fuel type. Combine the vintage filter with a Nova Scotia province scope to bias toward the dwelling stock that is dominated by oil-era equipment in the Atlantic provinces. Stitch the per-city responses together to build the provincial picture. Layering in age cuts is a one-line filter. Tighten construction_year_lte=1990 to focus on older envelopes that need the deepest retrofit, or add heating_install_year_first_lte=2005 to focus on equipment that is already past the typical service life of a legacy heating unit.

If you want the actual property-level list to hand to a regional outreach contractor, you switch to the /properties endpoint and select only the address and routing fields. The same query against /properties looks like this:

API request
Python code
from dataclasses import dataclass
from dataclasses_json import dataclass_json
import requests

params = {}
params['api_key'] = 'YOUR_API_KEY'
params['construction_year_lte'] = '1990'
params['country_abbreviation'] = 'ca'
params['heating_type_first_eq'] = 'Hot water'
params['interior_sq_m_lte'] = '260'
params['province_abbreviation'] = 'ns'
params['results_per_page'] = '10'
params['select'] = 'address,city,postal_code,construction_year,heating_type_first,heating_install_year_first,interior_sq_m,demographic_income_median_after_tax,latitude,longitude'

response = requests.get('https://api.houski.ca/properties', params=params)

if response.status_code == 200:
    json_data = response.json()

    print(json_data)

    # You must copy the PropertiesResponse type declarations from the 
    # Houski API documentation to strongly type the response
    typed_response = PropertiesResponse.from_dict(json_data)

    # Log the response
    print(typed_response)
else:
    print(f'Failed to get data: {response}')
API response
JSON
{
  "cache_hit": false,
  "cost_cents": 5.59999942779541,
  "data": [
    {
      "address": "9 Bumpy Lane",
      "city": "Lake Echo",
      "construction_year": 1982,
      "demographic_income_median_after_tax": 45568,
      "heating_install_year_first": 2017,
      "heating_type_first": "Hot water",
      "interior_sq_m": 103.3073272705078,
      "latitude": 44.747127532958984,
      "longitude": -63.380126953125,
      "postal_code": "B3E1B7",
      "property_id": "104e3376592f643c"
    },
    {
      "address": "3057 Hinchey Avenue",
      "city": "New Waterford",
      "construction_year": 1910,
      "demographic_income_median_after_tax": 39168,
      "heating_install_year_first": 2023,
      "heating_type_first": "Hot water",
      "interior_sq_m": 107.6737289428711,
      "latitude": 46.250633239746094,
      "longitude": -60.072784423828125,
      "postal_code": "B1H2K5",
      "property_id": "10a16241035abc71"
    },
    {
      "address": "34 Country Lake Drive",
      "city": "Lake Echo",
      "construction_year": 1982,
      "demographic_income_median_after_tax": 43008,
      "heating_install_year_first": 2017,
      "heating_type_first": "Hot water",
      "interior_sq_m": 142.93014526367188,
      "latitude": 44.72334671020508,
      "longitude": -63.38092803955078,
      "postal_code": "B3E1E4",
      "property_id": "10c37cee3db02476"
    },
    {
      "address": "24 Linda Lane",
      "city": "Lake Echo",
      "construction_year": 1982,
      "demographic_income_median_after_tax": 50176,
      "heating_install_year_first": 2017,
      "heating_type_first": "Hot water",
      "interior_sq_m": 142.93014526367188,
      "latitude": 44.73392105102539,
      "longitude": -63.388179779052734,
      "postal_code": "B3E1B3",
      "property_id": "11250373444cf268"
    },
    {
      "address": "160 Mineville Road",
      "city": "Lake Echo",
      "construction_year": 1982,
      "demographic_income_median_after_tax": 50176,
      "heating_install_year_first": 2017,
      "heating_type_first": "Hot water",
      "interior_sq_m": 142.93014526367188,
      "latitude": 44.716426849365234,
      "longitude": -63.39690017700195,
      "postal_code": "B3E1N3",
      "property_id": "11297b6fb856873d"
    },
    {
      "address": "19 Roland Norwood Drive",
      "city": "Lake Echo",
      "construction_year": 1982,
      "demographic_income_median_after_tax": 43008,
      "heating_install_year_first": 2017,
      "heating_type_first": "Hot water",
      "interior_sq_m": 142.93014526367188,
      "latitude": 44.73267364501953,
      "longitude": -63.37914276123047,
      "postal_code": "B3E1C9",
      "property_id": "114b36b6b2f9b4d0"
    },
    {
      "address": "45 Joyce Court",
      "city": "Lake Echo",
      "construction_year": 1982,
      "demographic_income_median_after_tax": 54784,
      "heating_install_year_first": 2017,
      "heating_type_first": "Hot water",
      "interior_sq_m": 142.93014526367188,
      "latitude": 44.739715576171875,
      "longitude": -63.3948860168457,
      "postal_code": "B3E1A8",
      "property_id": "118a43c94861411"
    },
    {
      "address": "2969 Highway 7",
      "city": "Lake Echo",
      "construction_year": 1982,
      "demographic_income_median_after_tax": 48640,
      "heating_install_year_first": 2017,
      "heating_type_first": "Hot water",
      "interior_sq_m": 142.93014526367188,
      "latitude": 44.73225021362305,
      "longitude": -63.39360046386719,
      "postal_code": "B3E1C6",
      "property_id": "11a113c8dc6567ec"
    },
    {
      "address": "1 Dopey Lane",
      "city": "Lake Echo",
      "construction_year": 1982,
      "demographic_income_median_after_tax": 43008,
      "heating_install_year_first": 2017,
      "heating_type_first": "Hot water",
      "interior_sq_m": 142.93014526367188,
      "latitude": 44.74325942993164,
      "longitude": -63.38127899169922,
      "postal_code": "B3E1C3",
      "property_id": "11eacb524ae942b2"
    },
    {
      "address": "2870 Highway 7",
      "city": "Lake Echo",
      "construction_year": 1982,
      "demographic_income_median_after_tax": 50176,
      "heating_install_year_first": 2017,
      "heating_type_first": "Hot water",
      "interior_sq_m": 142.93014526367188,
      "latitude": 44.727569580078125,
      "longitude": -63.393550872802734,
      "postal_code": "B3E1C6",
      "property_id": "121b428c56579706"
    }
  ],
  "error": "",
  "pagination": {
    "current_page": 1,
    "has_next_page": true,
    "has_previous_page": false,
    "page_total": 145
  },
  "price_quote": false,
  "result_total": 1446,
  "time_ms": 50,
  "ui_info": {
    "country": "Canada",
    "country_abbreviation": "CA",
    "country_abbreviation_id": "9ace2b6431b7f1be",
    "country_abbreviation_link": "ca",
    "country_slug": "canada",
    "province": "Nova Scotia",
    "province_abbreviation": "NS",
    "province_abbreviation_id": "6762b7e64abb3230",
    "province_abbreviation_link": "ca/ns",
    "province_slug": "nova_scotia"
  }
}

The interior_sq_m_lte filter is the kind of small touch that matters for program design. The federal Oil to Heat Pump Affordability Program is income-tested and aimed at modest single-family homes. Including a 600 square metre estate in your outreach is wasted postage and creates a bad headline if the wrong journalist sees it. The size cap pushes the list toward the program's actual policy intent.

Example two, tiering Ontario homes for a multi-program pipeline

Ontario program managers are usually juggling three or four overlapping incentive structures at once. There is the federal Greener Homes Loan, there is the Home Renovation Savings Program funded through the Independent Electricity System Operator (IESO), there are utility-administered demand-response and electrification riders, and there are community-level pilot programs. Each program has a slightly different ideal participant. A clean way to manage that complexity is to score every home into one of three or four tiers, then route each tier into the program where the conversion economics are best.

We would loop through every Ontario candidate home and assign each one to a tier based on heating fuel, vintage, and the area income proxy. The primary underlying API call looks like this:

API request
TypeScript code
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('country_abbreviation', 'ca');
    url.searchParams.set('heating_type_first_in', 'Gas furnace,Hot water,Electric furnace,Electric');
    url.searchParams.set('property_type_in', 'House,Townhouse,Duplex');
    url.searchParams.set('province_abbreviation', 'on');
    url.searchParams.set('results_per_page', '10');
    url.searchParams.set('select', 'property_id,address,city,postal_code,construction_year,heating_type_first,heating_install_year_first,interior_sq_m,demographic_income_median_after_tax,electricity_provider,gas_provider');

    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);
})();
API response
JSON
{
  "cache_hit": false,
  "cost_cents": 7.400000095367432,
  "data": [
    {
      "address": "1 107 12 Fourth Avenue",
      "city": "Ottawa",
      "construction_year": 2005,
      "demographic_income_median_after_tax": 76288,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2022,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 111.38981628417967,
      "postal_code": "K1S2L1",
      "property_id": "1000012a72a63be7"
    },
    {
      "address": "16 Balloon Crescent",
      "city": "Brampton",
      "construction_year": 1990,
      "demographic_income_median_after_tax": 38912,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2025,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 139.260498046875,
      "postal_code": "L6P4B7",
      "property_id": "10000c1259c75058"
    },
    {
      "address": "1 410 Pine Grove Avenue",
      "city": "Shelburne",
      "construction_year": 2015,
      "demographic_income_median_after_tax": 51200,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2015,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 140.00372314453125,
      "postal_code": "L9V2Z7",
      "property_id": "10000e5c7395578a"
    },
    {
      "address": "1 99 Hopewell Avenue",
      "city": "Ottawa",
      "construction_year": 1920,
      "demographic_income_median_after_tax": 65536,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2025,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 139.260498046875,
      "postal_code": "K1S2Y9",
      "property_id": "10000f4d120a2e1d"
    },
    {
      "address": "577 Wingrove Crescent",
      "city": "Oakville",
      "construction_year": 2015,
      "demographic_income_median_after_tax": 47616,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2015,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 139.260498046875,
      "postal_code": "L6L4R7",
      "property_id": "1000163bfa743f6"
    },
    {
      "address": "57 Ellen Street W",
      "city": "Kitchener",
      "construction_year": 1989,
      "demographic_income_median_after_tax": 55296,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2024,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 122.90969848632812,
      "postal_code": "N2H4K1",
      "property_id": "10001a21157e0bf3"
    },
    {
      "address": "206 Wychwood Park",
      "city": "London",
      "construction_year": 1966,
      "demographic_income_median_after_tax": 72192,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2026,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 183.66778564453125,
      "postal_code": "N6G1S3",
      "property_id": "10001c0a409cb394"
    },
    {
      "address": "70 Gallant Place",
      "city": "Vaughan",
      "construction_year": 2010,
      "demographic_income_median_after_tax": 52224,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2010,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 139.260498046875,
      "postal_code": "L4H3W7",
      "property_id": "10001e50d0fd8d30"
    },
    {
      "address": "18 Griffen Place",
      "city": "Whitby",
      "construction_year": 2000,
      "demographic_income_median_after_tax": 56320,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2017,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 139.260498046875,
      "postal_code": "L1R2N5",
      "property_id": "10002659edbb02b9"
    },
    {
      "address": "23 Silent Pond Crescent",
      "city": "Brampton",
      "construction_year": 1990,
      "demographic_income_median_after_tax": 45056,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2025,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 139.260498046875,
      "postal_code": "L6V4R6",
      "property_id": "100029e8a35ad67"
    }
  ],
  "error": "",
  "pagination": {
    "current_page": 1,
    "has_next_page": true,
    "has_previous_page": false,
    "page_total": 474791
  },
  "price_quote": false,
  "result_total": 4747904,
  "time_ms": 178,
  "ui_info": {
    "country": "Canada",
    "country_abbreviation": "CA",
    "country_abbreviation_id": "9ace2b6431b7f1be",
    "country_abbreviation_link": "ca",
    "country_slug": "canada",
    "province": "Ontario",
    "province_abbreviation": "ON",
    "province_abbreviation_id": "146699ee774499d3",
    "province_abbreviation_link": "ca/on",
    "province_slug": "ontario"
  }
}

The tiering logic itself is a small pure function applied to each row:

  • Tier 1: heating type Hot water, built 1985 or earlier, area income at or below $70,000. This is the queryable proxy for the legacy oil-heat cohort. Smallest cohort, deepest retrofit value, near-universal program qualifier.
  • Tier 2: forced air gas, built before 2000, area income $60,000 to $110,000. Largest cohort by volume, primary demand-side management target for gas utilities.
  • Tier 3: electric resistance, built before 1995. Fast payback, highest completion rates.
  • Tier 4: everything else. Deprioritize this cycle.

A few notes on what is happening in the tier logic. Tier 1 is the smallest and most expensive group to acquire, but it is also the group where the program economics are strongest. A legacy hot water system plus a pre-1985 envelope plus a household at the lower end of the income distribution is the closest queryable stand-in for the oil-heat cohort, which is a near-universal program qualifier across federal and provincial offerings, and the per-home greenhouse gas reduction is the highest of any retrofit category in the country.

Tier 2 is where most of the volume lives. Gas furnaces in homes built between the 1970s and the late 1990s represent millions of dwellings. The conversion math is more sensitive to gas prices and electricity prices, but for utilities running demand-side management programs, Tier 2 is usually where the kilowatt-hour acquisition costs land in a defensible range.

Tier 3 is the easy win that often gets ignored. Older small homes with electric baseboards in Ontario and Atlantic Canada flip to a cold climate heat pump with very fast payback because the existing electricity bill is already high. These homes do not need fuel switching, they need efficiency. Program managers who run a dedicated Tier 3 lane often see the highest completion rates of any cohort.

Tier 4 is everything else, which gets deprioritized in this cycle and revisited later.

Example three, budget allocation by Forward Sortation Area

Once you have a tier per home, the next question is how to split a fixed annual outreach budget across regions. The most defensible way to do that is to count qualified homes per Forward Sortation Area, then allocate budget proportionally to qualified count, weighted by program priority.

The Forward Sortation Area is the first three characters of a Canadian postal code, and it is the natural geographic unit for Canada Post bulk mail. Houski returns full postal_code on every property, so deriving Forward Sortation Area is a string slice.

We would loop through every Ontario city in scope, using the /aggregate endpoint once per city to avoid paying per row when you only need totals. Pull the city list from the /location endpoint. The underlying per-city call looks like this:

API request
Python code
from dataclasses import dataclass
from dataclasses_json import dataclass_json
import requests

params = {}
params['aggregation'] = 'count'
params['api_key'] = 'YOUR_API_KEY'
params['city'] = 'toronto'
params['construction_year_lte'] = '1999'
params['country_abbreviation'] = 'ca'
params['demographic_income_median_after_tax_lte'] = '95000'
params['field'] = 'property_id'
params['heating_type_first_in'] = 'Gas furnace,Hot water'
params['province_abbreviation'] = 'on'

response = requests.get('https://api.houski.ca/aggregate', params=params)

if response.status_code == 200:
    json_data = response.json()

    print(json_data)

    # You must copy the AggregateResponse type declarations from the 
    # Houski API documentation to strongly type the response
    typed_response = AggregateResponse.from_dict(json_data)

    # Log the response
    print(typed_response)
else:
    print(f'Failed to get data: {response}')
API response
JSON
{
  "cache_hit": false,
  "cost_cents": 1.0,
  "data": [
    {
      "aggregation": "count",
      "field": "property_id",
      "value": "26966"
    }
  ],
  "error": "",
  "price_quote": false,
  "time_ms": 232
}

Stitch the per-city counts together client-side, then divide a fixed annual budget proportionally to qualified-home count.

What this gives a program manager is a defensible allocation table in front of a board. Every dollar is tied to a count of pre-qualified candidate homes. If the board asks why London is getting more outreach budget than Sudbury this year, the answer is not gut feel, it is a count of qualified candidate homes pulled from a specific dataset on a specific date.

For Forward Sortation Area resolution, pull the underlying property rows from /properties selecting only postal_code and roll up the first three characters client-side. For utility-administered programs that have to align with service territory rather than political boundaries, the gas_provider and electricity_provider fields let you slice further.

A reference implementation in Python

For program teams who want a single end-to-end pipeline, the shape is the same as the examples above. We would loop through each province in scope, pull the province-wide candidate list from /properties, apply the tier function in memory, weight each tier, group by city, and write three comma-separated values (CSV) exports (candidates, tier counts, city budget allocation). The heating_type_first_in list already excludes heat pumps, so no separate exclusion filter is needed. The primary underlying API call is the province-wide candidate pull:

API request
Python code
from dataclasses import dataclass
from dataclasses_json import dataclass_json
import requests

params = {}
params['api_key'] = 'YOUR_API_KEY'
params['construction_year_lte'] = '1999'
params['country_abbreviation'] = 'ca'
params['heating_type_first_in'] = 'Gas furnace,Hot water,Electric furnace,Electric'
params['property_type_in'] = 'House,Townhouse,Duplex'
params['province_abbreviation'] = 'on'
params['results_per_page'] = '10'
params['select'] = 'property_id,address,city,postal_code,construction_year,heating_type_first,heating_install_year_first,interior_sq_m,demographic_income_median_after_tax,electricity_provider,gas_provider,latitude,longitude'

response = requests.get('https://api.houski.ca/properties', params=params)

if response.status_code == 200:
    json_data = response.json()

    print(json_data)

    # You must copy the PropertiesResponse type declarations from the 
    # Houski API documentation to strongly type the response
    typed_response = PropertiesResponse.from_dict(json_data)

    # Log the response
    print(typed_response)
else:
    print(f'Failed to get data: {response}')
API response
JSON
{
  "cache_hit": false,
  "cost_cents": 7.599999904632568,
  "data": [
    {
      "address": "16 Balloon Crescent",
      "city": "Brampton",
      "construction_year": 1990,
      "demographic_income_median_after_tax": 38912,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2025,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 139.260498046875,
      "latitude": 43.81475830078125,
      "longitude": -79.72196197509766,
      "postal_code": "L6P4B7",
      "property_id": "10000c1259c75058"
    },
    {
      "address": "1 99 Hopewell Avenue",
      "city": "Ottawa",
      "construction_year": 1920,
      "demographic_income_median_after_tax": 65536,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2025,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 139.260498046875,
      "latitude": 45.39194107055664,
      "longitude": -75.68727111816406,
      "postal_code": "K1S2Y9",
      "property_id": "10000f4d120a2e1d"
    },
    {
      "address": "57 Ellen Street W",
      "city": "Kitchener",
      "construction_year": 1989,
      "demographic_income_median_after_tax": 55296,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2024,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 122.90969848632812,
      "latitude": 43.45667266845703,
      "longitude": -80.48759460449219,
      "postal_code": "N2H4K1",
      "property_id": "10001a21157e0bf3"
    },
    {
      "address": "206 Wychwood Park",
      "city": "London",
      "construction_year": 1966,
      "demographic_income_median_after_tax": 72192,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2026,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 183.66778564453125,
      "latitude": 43.0022087097168,
      "longitude": -81.29854583740234,
      "postal_code": "N6G1S3",
      "property_id": "10001c0a409cb394"
    },
    {
      "address": "23 Silent Pond Crescent",
      "city": "Brampton",
      "construction_year": 1990,
      "demographic_income_median_after_tax": 45056,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2025,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 139.260498046875,
      "latitude": 43.71971893310547,
      "longitude": -79.76009368896484,
      "postal_code": "L6V4R6",
      "property_id": "100029e8a35ad67"
    },
    {
      "address": "434 25 Westhill Drive",
      "city": "Waterloo",
      "construction_year": 1974,
      "demographic_income_median_after_tax": 44032,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2009,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 139.260498046875,
      "latitude": 43.44560623168945,
      "longitude": -80.56916809082031,
      "postal_code": "N2T0B6",
      "property_id": "10002c548c70372e"
    },
    {
      "address": "36 Josephine Street",
      "city": "London",
      "construction_year": 1989,
      "demographic_income_median_after_tax": 42496,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2024,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 111.38981628417967,
      "latitude": 42.972900390625,
      "longitude": -81.22303009033203,
      "postal_code": "N5W0A6",
      "property_id": "1000370a4cfb98d3"
    },
    {
      "address": "156 Agava Street",
      "city": "Brampton",
      "construction_year": 1990,
      "demographic_income_median_after_tax": 45056,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2025,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 139.260498046875,
      "latitude": 43.7029914855957,
      "longitude": -79.85221862792969,
      "postal_code": "L7A4S1",
      "property_id": "100038a9b8aed534"
    },
    {
      "address": "1 13 Allard Street",
      "city": "Sault Ste. Marie",
      "construction_year": 1977,
      "demographic_income_median_after_tax": 31232,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2012,
      "heating_type_first": "Electric",
      "interior_sq_m": 153.47454833984375,
      "latitude": 46.52204132080078,
      "longitude": -84.30962371826172,
      "postal_code": "P6B5E7",
      "property_id": "100043270c116fb9"
    },
    {
      "address": "4 Meighen Crescent",
      "city": "Brockville",
      "construction_year": 1989,
      "demographic_income_median_after_tax": 47616,
      "electricity_provider": "Grid",
      "gas_provider": "Municipal",
      "heating_install_year_first": 2024,
      "heating_type_first": "Gas furnace",
      "interior_sq_m": 66.65764617919922,
      "latitude": 44.60491943359375,
      "longitude": -75.70667266845703,
      "postal_code": "K6V3J7",
      "property_id": "1000436f7d44ec8f"
    }
  ],
  "error": "",
  "pagination": {
    "current_page": 1,
    "has_next_page": true,
    "has_previous_page": false,
    "page_total": 204422
  },
  "price_quote": false,
  "result_total": 2044214,
  "time_ms": 185,
  "ui_info": {
    "country": "Canada",
    "country_abbreviation": "CA",
    "country_abbreviation_id": "9ace2b6431b7f1be",
    "country_abbreviation_link": "ca",
    "country_slug": "canada",
    "province": "Ontario",
    "province_abbreviation": "ON",
    "province_abbreviation_id": "146699ee774499d3",
    "province_abbreviation_link": "ca/on",
    "province_slug": "ontario"
  }
}

From there, the production version usually adds rate limiting, retry logic, an output to your data warehouse rather than CSV, a join to the climate zone overlay, and a versioned snapshot table so year-over-year comparisons are reproducible.

Stacking utility data on top of property data

The /properties endpoint returns gas_provider and electricity_provider for properties where Houski has been able to resolve service territory. For utility-administered programs, this is the field that turns a national dataset into a service-territory dataset without requiring a custom data export from a regulator.

A few use cases that drop out of this directly.

For Enbridge Gas, you can pull every Ontario home where gas_provider resolves to Enbridge and the heating_type_first is Gas furnace or Hot water, then cross-tab against construction_year vintage cohorts to build a fuel-switching potential map. The same pattern works for FortisBC in British Columbia, ATCO and Alberta-area gas distributors in Alberta, and Energir in Quebec.

For BC Hydro, Hydro-Quebec, Manitoba Hydro, NB Power, and the various provincial and municipal electric utilities, the inverse query gives you the existing electric-heat customer base where a heat pump retrofit has the highest demand-side management value. Electric resistance to cold climate heat pump conversions are the highest impact retrofit a winter-peaking utility can run, because the peak load reduction is dramatic and the customer-side bill savings make the program self-marketing.

For combined-utility programs that touch both gas and electricity, like the joint rebates running in parts of British Columbia and Quebec, the cross-utility filter lets you build a single qualified-home list that satisfies both program partners' service territory definitions.

We would loop once per Ontario city in scope, calling /aggregate with the heating and vintage filters in place, and layer the gas_provider filter on top where the field has resolved to a specific utility for that area. The underlying call looks like this:

API request
Shell session
curl -X GET "https://api.houski.ca/aggregate?aggregation=count&api_key=YOUR_API_KEY&city=toronto&construction_year_lte=1999&country_abbreviation=ca&field=property_id&heating_type_first_in=Gas furnace,Hot water&province_abbreviation=on"
API response
JSON
{
  "cache_hit": false,
  "cost_cents": 1.0,
  "data": [
    {
      "aggregation": "count",
      "field": "property_id",
      "value": "26966"
    }
  ],
  "error": "",
  "price_quote": false,
  "time_ms": 208
}

The result, stitched across cities, is the city-by-city count of gas-heated homes built in or before 1999, ready to feed into a service-territory budget allocation. Where Houski has resolved gas_provider to a specific distributor, add it as a one-line filter to narrow the count to the relevant service territory. The same loop without any provider filter gives you the all-utility comparison, which is useful when you need to argue for cross-utility coordination on overlapping outreach campaigns.

Climate zone overlays for system selection

Heat pump suitability is also a function of climate zone. A standard air-source heat pump tuned for southern Ontario behaves very differently in northern Manitoba, and program rules increasingly distinguish between standard and cold climate units. Houski's latitude and longitude fields let you join any property list to the climate zone overlay your program already uses, whether that is the National Energy Code climate zones, the Natural Resources Canada heating degree day bands, or a custom utility-defined zone.

The pattern is straightforward. Pull your candidate list with latitude and longitude in the select clause, then in your downstream pipeline do a spatial join against your climate zone polygon set. Homes in zones 7A and 7B get flagged for cold climate equipment lists. Homes in zones 4 and 5 can use standard equipment, which opens up a broader contractor network and lower per-install rebate amounts.

This is the kind of overlay that program managers sometimes try to bake into the property data layer itself. Resist the urge. Climate zones change as standards get updated, and your program rules will evolve faster than any vendor can re-tag a national dataset. Keep climate zone as a join in your own pipeline so you control the version.

Using income data without crossing a line

Every program manager gets nervous about income-based targeting, and they are right to. The line between defensible socioeconomic targeting and creepy individual income inference is real. Houski's demographic_income_median_after_tax field is an area median, derived from public, government, and crowdsourced data sources. It is not a household-level income value, and it should not be used as one. It tells you something about the neighbourhood the home sits in, which is exactly what most income-tested programs already use as a screening proxy before they request actual income documentation from the applicant.

The defensible pattern is this. Use the area median to tier outreach, so that the highest-cost outreach formats like door knocking and in-person events are concentrated in areas where program eligibility is statistically more likely. Use the lower-cost formats like postal-code-targeted mail and digital ads more broadly. When a homeowner responds, the eligibility verification step is where actual household income gets checked, with the homeowner's consent and through the documentation process the program already has in place.

In practice that looks like setting demographic_income_median_after_tax_lte at a value that is somewhat above your program's actual income cap, so you are not screening out eligible households who happen to live in higher-income areas. A program with an $85,000 household cap might tier outreach with an area median ceiling of $110,000 or $120,000, which catches a generous superset of the eligible population without leaking obvious mis-targets into the list.

What to do with homes that already have a heat pump

One of the highest-value uses of the heating_type_first field is the negative filter. Programs spend real money mailing homeowners who already converted, partly because contractors selling into the program do not always report installs back to the utility in a timely way, and partly because legacy customer relationship management systems treat anyone who ever had a gas account as still being on gas.

Adding a heating_type_first_neq=Heat pump filter to every outreach query is a one-line change that removes the most embarrassing mis-targets from your list. A homeowner who installed a heat pump in 2024 and gets a 2026 mailer from the same program offering them a rebate for the install they already did is a small annoyance individually and a meaningful credibility hit at scale.

The same logic applies to recently installed equipment. Adding heating_install_year_first_lte=2015 keeps the list focused on homes whose existing equipment is genuinely near end of life, not homes that already replaced a furnace in the last cycle and are not in the market for another swap for a decade.

These two filters together are the single largest reduction in wasted outreach dollars available in real program builds, and they are both single line additions to a query you were already running.

Handling missing data without breaking the program

No national dataset has 100 percent coverage on every field. The realistic numbers for heating-related fields in Canada land somewhere in the 60 to 90 percent range depending on the province and how recently the property has generated new records. Houski's coverage is strongest where public, government, and crowdsourced data sources are most active, which generally means major metros and the provinces with the longest-running retrofit programs.

The right way to design around incomplete coverage is to treat missing data as a separate cohort, not as a default-no. A home with heating_type_first as null is a home where you do not know the heating fuel, which is information in itself. Some programs route the unknown cohort into a low-cost broadcast outreach channel with a heating-system survey question on the response form, then enrich the dataset with the responses for the next cycle. Others use the unknown cohort to prioritize ground-truth surveys in specific geographies.

In the tier logic from earlier, you can add an explicit branch.

JavaScript code
if (!fuel || !builtYear) {
  return 'tier_unknown_enrich';
}

That cohort then gets treated as an enrichment opportunity rather than being silently dropped from the program.

Measuring market-share progress year over year

Heat pump program success used to be measured in raw participant counts. That is a fine input metric, but the metric program boards actually want is share of the addressable retrofit market converted per year. To compute that, you need a denominator that is anchored to a specific dataset, and a numerator you can pull on the same basis a year later.

The denominator is the count of qualified homes in your service territory at the start of the program year. You pull that with the aggregate query above and snapshot the result.

The numerator is the count of those homes that transitioned out of the qualified pool by the end of the program year, either because the heating_type_first changed to a heat pump or because the heating_install_year_first updated past your replacement threshold. Houski refreshes heating data as it becomes available from public, government, and crowdsourced data sources, so year-over-year deltas at the parcel level are observable for a meaningful share of the dwelling stock.

The share captured is numerator divided by denominator. If you set up the snapshot correctly, you can also compute capture share by tier, by Forward Sortation Area, by utility service territory, and by income band, which is the kind of cross-tab a program board will reward you for showing up with.

Privacy, ethics, and the right way to use this

A few things to be clear about, because this is a sensitive domain.

The Houski dataset is a property dataset, not a homeowner dataset. The fields described here are about the building, the area, and the equipment installed in the building. They are not personal contact information, they are not credit data, and they are not household-level income data. The right use of this data for program targeting is to identify which homes are pre-qualified candidates so that outreach budgets are spent efficiently. The right way to actually contact those homes is through the channels homeowners have opted into, or through broadcast formats like postal mail that have been the foundation of program outreach for decades.

The combination of property targeting and opt-in outreach is the version of this that program boards will defend in public. The combination of property targeting and scraped personal contact data is the version that ends up in a Globe and Mail story you do not want to be in.

It is worth saying out loud, even though most program managers reading this already know it.

A note on the federal program landscape going into 2026

The federal Greener Homes Loan portal stopped accepting new applications in late 2025 once the funding envelope was fully committed, though approved loans continue to fund through their full disbursement schedule. The grant component of the original Canada Greener Homes Grant wound down on the previous schedule, and the targeted Oil to Heat Pump Affordability Program remains active for the moment but is winding down, with most provinces requiring participant registration by mid-2026 and final project completion by March 31, 2027.

The Oil to Heat Pump Affordability Program coordinates with provincial top-ups in several provinces. Nova Scotia, Prince Edward Island, Newfoundland and Labrador, and New Brunswick all have provincial agreements that stack on top of the federal contribution, which means the effective install cost for a qualified Atlantic Canada household can be very low. The remaining window for these stacked offers is short, which makes targeting in Atlantic Canada a time-sensitive opportunity. The dwelling counts are well within reach for a single province-wide outreach campaign.

In Quebec, the LogisVert program suite continues to fund both heat pump installs and envelope upgrades. Targeting under LogisVert is well aligned with electric resistance retrofits in older small homes, which is the Tier 3 cohort from the earlier example. Hydro-Quebec's customer base is essentially the entire province, which simplifies the service-territory layer.

In Ontario, the Home Renovation Savings Program funded through the IESO and the Save on Energy framework runs alongside Enbridge gas-side rebates and the federal loan. The Tier 1 and Tier 2 logic from earlier maps directly onto this program structure.

In British Columbia, the CleanBC Better Homes program coordinates federal, provincial, and BC Hydro and FortisBC utility incentives. The provincial heat pump rebate amounts are among the highest in the country for income-qualified households, and the program targeting often runs into the inverse problem from elsewhere in the country, namely too many qualified candidates and not enough installer capacity. Targeting in British Columbia often means tiering by installer service territory rather than by candidate density.

In Alberta, the program landscape is more fragmented and utility-driven, with ATCO and other distributors running narrower offerings. The federal loan still applies, and contractor-led rebate stacking is common. Property data targeting in Alberta is often most useful for the contractor-program partnerships rather than direct utility outreach.

The point of this rundown is that the targeting logic is the same everywhere. The fields that matter are heating fuel, equipment age, envelope vintage, building size, area income, and service territory. The program rules differ by jurisdiction, but the underlying property data layer is national. A program manager who builds a targeting pipeline once can adapt it to any jurisdictional rule set with a configuration change rather than a rebuild.

Where to start

If you are running a heat pump rebate program in Canada and you want to move toward parcel-level targeting, the practical first step is small. Pull aggregate counts for your service territory, broken down by current heating fuel and construction year, and compare those counts to your last cycle's outreach mix. The gap between those two numbers is usually the business case for the entire engagement.

From there, build the tiering logic that matches your program's actual eligibility rules, snapshot a baseline qualified-home count, and run your next outreach cycle against the tiered list. The reporting will write itself.

If you want to see the underlying fields, run a few queries against your own service territory, and confirm the data covers the parcels you care about, the fastest way is to grab an API key and run a few requests. You can get started in about 10 minutes at /api-documentation/quick-start. Pricing starts at $99 a month, which covers more than enough volume to validate coverage in your region and confirm the tier logic on a few hundred homes before you build the production version of the pipeline.

Program managers running this kind of build keep coming back to the same observation. The data has been the missing piece for a long time, the analytical chops were never the bottleneck. Once the data shows up at parcel level, the entire program design conversation changes from "how do we reach more homeowners" to "how do we convert the right homeowners faster." That is the conversation worth having in 2026.