Home insurance prices a building as it stood on the day the policy was written. Then the policyholder finishes the basement, adds a garage, converts the ground floor to a storefront, or guts the place to the studs - and tells nobody, because notifying your insurer mid-renovation is on exactly no homeowner's checklist. The premium keeps reflecting a building that no longer exists.
This drifts in both directions, and both cost you. A major addition means the rebuild cost is now higher than the coverage limit, which surfaces as an underinsured total loss and a very bad claims conversation. New wiring, a new roof, or a modern furnace means the risk improved and a competitor quoting fresh data will undercut the premium you are still charging.
Permits are how this drift becomes visible. A permit application is a dated, property-specific declaration that the building is about to change. Houski carries building permits and business licenses for Calgary, Edmonton, Toronto, and Vancouver, attached to property records, which makes monitoring a policy book for permit activity a scheduled query rather than a project.
The sweep
Resolve your insured addresses to property identifiers once, through the search endpoint:
const houski_data = async (): Promise<SearchResponse> => {
// You must copy the SearchResponse type declarations from the
// Houski API documentation to strongly type the response
const url = new URL('https://api.houski.ca/search');
url.searchParams.set('api_key', 'YOUR_API_KEY');
url.searchParams.set('query', '123+main+st+calgary');
const response = await fetch(url);
const data = await response.json();
return data;
}
(async () => {
let data: SearchResponse = await houski_data();
// Log the response
console.log(data);
})();
{
"cache_hit": true,
"cost_cents": 0.19999998807907104,
"data": [
{
"address": "1215 19489 Main Street SE",
"property_id": "1a0d9646b3b7fee4"
},
{
"address": "20913 Main Street Southeast",
"property_id": "1bb955452668e179"
},
{
"address": "1206 19489 Main Street SE",
"property_id": "25dbe5737d863d68"
},
{
"address": "20693 Main Street Southeast",
"property_id": "265563c5cf7aaeb"
},
{
"address": "1203 19489 Main Street SE",
"property_id": "2cb6522c907d3cad"
},
{
"address": "1217 19489 Main Street SE",
"property_id": "3c360263b5035097"
},
{
"address": "1218 19489 Main Street SE",
"property_id": "3e9b995b7a2575cf"
},
{
"address": "120 180 Legacy Main Street SE",
"property_id": "4715657394081588"
},
{
"address": "1209 19489 Main Street SE",
"property_id": "4e6754f302f2956c"
},
{
"address": "151 Legacy Main Street Southeast",
"property_id": "61a5c09375eb16aa"
}
],
"error": "",
"match_meta": [
{
"match_value": 0.8333333134651184,
"property_id": "1a0d9646b3b7fee4"
},
{
"match_value": 0.8333333134651184,
"property_id": "1bb955452668e179"
},
{
"match_value": 0.8333333134651184,
"property_id": "25dbe5737d863d68"
},
{
"match_value": 0.8333333134651184,
"property_id": "265563c5cf7aaeb"
},
{
"match_value": 0.8333333134651184,
"property_id": "2cb6522c907d3cad"
},
{
"match_value": 0.8333333134651184,
"property_id": "3c360263b5035097"
},
{
"match_value": 0.8333333134651184,
"property_id": "3e9b995b7a2575cf"
},
{
"match_value": 0.8333333134651184,
"property_id": "4715657394081588"
},
{
"match_value": 0.8333333134651184,
"property_id": "4e6754f302f2956c"
},
{
"match_value": 0.8333333134651184,
"property_id": "61a5c09375eb16aa"
}
],
"price_quote": false,
"result_total": 10,
"time_ms": 1007
}
Then, on whatever cycle suits your book, ask one question: which of my insured properties have permit activity since the last sweep?
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('expand', 'permits');
url.searchParams.set('expand_permit_application_date_gte', '2026-01-01');
url.searchParams.set('filter_expand_match', 'all');
url.searchParams.set('property_id_in', '1a0d9646b3b7fee4,10169c4adca227cb');
url.searchParams.set('results_per_page', '25');
url.searchParams.set('select', 'address,property_type,construction_year,interior_sq_m');
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": 0.24000002443790436,
"data": [
{
"address": "2806 Ogden Road SE",
"construction_year": 1959,
"interior_sq_m": 163.50799560546875,
"permits": [
{
"expand_permit_application_date": "2026-02-25",
"expand_permit_content": "Status: Move in Progress|Tradename: SHIV MOTORS|Home occupation: N|License type: MOTOR VEHICLE DEALER - PREMISES|Expiration date: 2027-02-24",
"expand_permit_id": "16729287",
"expand_permit_type": "Business license",
"property_id": "10169c4adca227cb"
}
],
"property_id": "10169c4adca227cb",
"property_type": "Commercial"
}
],
"error": "",
"pagination": {
"current_page": 1,
"has_next_page": false,
"has_previous_page": false,
"page_total": 1
},
"price_quote": false,
"result_total": 1,
"time_ms": 48,
"ui_info": {}
}
The filter does the work: properties with no new permits drop out of the response entirely. A ten-thousand-policy sweep comes back as the short list of addresses where something changed, each with its permit records attached - type, application date, and a content field carrying the details the source city provides, typically including status, work class, estimated project cost, and applicant.
At a tenth of a cent per field per property, sweeping a book of ten thousand policies costs a few dollars. The renewal cycle stops being the only time you look at the risk.
What the permit tells the underwriter
Estimated project cost is a replacement-cost tripwire. A six-figure renovation on a policy whose dwelling limit was set years ago is a file that needs a coverage conversation before the loss, not after. This is also, handled well, a retention play: "we noticed you are renovating, let us make sure you are covered" is one of the few insurer letters a customer reads as service rather than upsell.
Work class separates cosmetic from structural. The content distinguishes an alteration from an addition from a new build. Your triage rules decide which classes wake an underwriter and which just annotate the file for renewal.
A business license at a residential address is a use change. A property insured as a home that licenses a vehicle dealership, a daycare, or a food business is a different risk on the same street corner. This class of change is nearly invisible through any other channel, and it is sitting in the same feed.
A demolition-scale permit is an exposure event. Construction sites burn, flood, and get robbed at rates settled buildings do not, and vacancy clauses in most policies turn on facts the permit feed surfaces weeks early.
Renewal repricing without a questionnaire
The same mechanism runs proactively at renewal: sweep the cohort renewing next quarter, and every file arrives at the underwriter's desk with its permit history since the last term already attached. No mailed questionnaire, no reliance on the broker remembering to ask, no "has your home changed" checkbox that everyone ticks "no" on. The files with no activity renew straight through. The files with activity get looked at by a human with the permit in front of them.
For the risk-scoring side of the same workflow - climate and catastrophe exposure on each insured property - see climate risk underwriting and catastrophe risk scores. The permit sweep and the hazard scores ride on the same property identifiers, so one integration serves both.
Honest limits
Four cities. Calgary, Edmonton, Toronto, Vancouver. Policies elsewhere are invisible to this sweep, so report coverage honestly to whoever owns the monitoring program.
Unpermitted work stays dark. The homeowner who finishes a basement without a permit is exactly as invisible to us as to you. Permit monitoring catches the compliant majority of significant work, not all of it.
A permit is intent, not completion. Applications get cancelled and projects stall. The content carries status - route on it, and treat the application date as the start of a story, not proof of a finished addition.
Match confidence matters at book scale. The search endpoint returns a confidence score per address. Send the low-confidence tail to a human once, at onboarding, rather than silently monitoring the wrong building for years.
Getting started
- Sign up for API access
- Resolve the book to property identifiers through the search endpoint, storing match confidence
- Run the first sweep with a lookback long enough to catch active projects - a year is a sane start
- Write the triage rules - which permit classes and cost thresholds open a file, which just annotate it
- Schedule it monthly or quarterly, and route the short list into the underwriting queue you already have
Pricing details on the pricing page, query mechanics in the expand documentation. If you would rather receive the sweep as a delivered file - your policy identifiers in, flagged changes out - our data team builds custom datasets on your schedule. Talk to us.
Every building in your book is changing, and today you find out at claim time. The permit feed moves that discovery to the week the change was declared. Explore the API or browse the datasets.
