!

/map

GET
https://api.houski.ca/map
Our interactive map page is powered by this endpoint.

Returns property pins and clusters for interactive maps.

Also generates heatmap data as a grid of cells whose intensity reflects property concentration. Filtering supports list price, sale price, for sale status, bedrooms, and more.

Supports standard filtering and sorting.

Example use cases

  1. Monitor property changes within a boundary (e.g. new listings).
  2. Property marketplaces adding map-based browsing.
  3. Governments using pin and cluster data for urban planning.
  4. Investors visualizing high-potential areas.
  5. Insurers assessing geographic risk.
  6. Property managers optimizing rental pricing.
  7. Journalists creating visualizations on housing trends (e.g. 'Where are the cheapest houses in Canada?').
  8. Analysts deriving insights from clustered property data.

Request parameters

NameRequiredTypeDescription
api_keyYesUUID v4Your API key for authorization
clusterNoBoolean (default: false)Manual control of whether the data returned should be in pins or clusters.
cluster_overNoIntegerAutomatically return clusters instead of pins when there are more results than this.
heatmapNoBoolean (default: false)Return heatmap data instead of pins.
heatmap_cell_limitNoIntegerThe max number of heatmap cells returned (default: 1000, max: 10000)
heatmap_aggregation_fieldNoStringField to use for heatmap intensity calculation. When not provided, density of properties is used.
heatmap_aggregation_typeNoString (default: 'mean')aggregation method for heatmap values. Possible values: 'mean', 'median', 'sum'
heatmap_aggregation_invert_intensityNoBoolean (default: false)When true, inverts the intensity values (1.0 - intensity) to make lower values appear as higher intensity
abort_overNoIntegerAbort request if number of results exceeds this value (cost control).
polygonIf not using bboxPolygon filter stringGet results inside a polygon.
bbox_ne_latIf not using polygonFloatNortheast latitude for bounding box.
bbox_ne_lngIf not using polygonFloatNortheast longitude for bounding box.
bbox_sw_latIf not using polygonFloatSouthwest latitude for bounding box.
bbox_sw_lngIf not using polygonFloatSouthwest longitude for bounding box.
selectNoString - see selectingThe fields to return for each pin. Defaults to latitude, longitude, and property_id
results_per_pageNoIntegerNumber of results per page. Maximum 1000. Ignored when clusters or a heatmap are returned.
pageNoIntegerThe page number to retrieve results from, starting at 1

Working with heatmaps

Heatmaps can visualize property density or numeric attributes.

Basic heatmap (property density)

Set heatmap=true without heatmap_aggregation_field to get a density heatmap where each cell's intensity is its property concentration.

Aggregated field heatmap

Pair heatmap=true with heatmap_aggregation_field to map numeric values like price, square footage, or bedrooms.

Choose how cell values aggregate:

  • mean (default): average value in the cell
  • median: middle value in the cell
  • sum: total of all values in the cell

By default higher values mean higher intensity. Set heatmap_aggregation_invert_intensity=true to flip this - useful for affordability views where low values are the target.

Response object

Type declarations are available at the bottom of this page.

NameTypeDescription
abortedBooleanIndicates if the request was aborted due to exceeding the abort_over limit
cache_hitBooleanIndicates if the data was retrieved from the cache
cost_centsIntegerCost of the API call in cents
dataObjectContains the map data in 'clusters', 'properties', or 'heatmap' arrays depending on the request type
errorStringDetails about the error. Empty if no error
is_propertiesBooleanIndicates if the returned data contains individual properties
is_clustersBooleanIndicates if the returned data contains clustered properties
is_heatmapBooleanIndicates if the returned data contains heatmap cells
is_heatmap_aggregationBoolean (nullable)When present, indicates if the heatmap uses a field for aggregation (true) or just property density (false)
is_heatmap_aggregation_invert_intensityBoolean (nullable)When present, indicates if heatmap intensity values are inverted (1.0 - value)
heatmap_aggregation_typeString (nullable)When present, indicates the type of aggregation used: 'mean', 'median', or 'sum'
heatmap_aggregation_max_valueFloat (nullable)When present, the maximum value found in the aggregated field (before normalization)
heatmap_aggregation_min_valueFloat (nullable)When present, the minimum value found in the aggregated field (before normalization)
heatmap_aggregation_fieldString (nullable)When present, the field name used for heatmap aggregation
paginationObjectPagination information
price_quoteBooleanIndicates if this is a price quote request
result_totalIntegerTotal number of results
time_msIntegerTime taken for the request to complete in milliseconds

MapData object

The data field varies by request type:

NameTypeDescription
propertiesArray<Property>Array of individual property objects when is_properties is true
clustersArray<Cluster>Array of cluster objects when is_clusters is true
heatmapArray<HeatPoint>Array of heatmap points when is_heatmap is true

Property object

Each property contains fields chosen via select. Over 400 fields available.

See the Fields documentation for the full list.

Cluster object

Grouped properties for map display:

NameTypeDescription
latitudeFloatCenter latitude coordinate of the cluster
longitudeFloatCenter longitude coordinate of the cluster
number_of_propertiesIntegerNumber of properties grouped in this cluster

HeatPoint object

Cells in a heatmap:

NameTypeDescription
latitudeFloatCenter latitude coordinate of the heatmap cell
longitudeFloatCenter longitude coordinate of the heatmap cell
intensityFloatNormalized intensity value (0.0 to 1.0) for heatmap visualization
number_of_propertiesIntegerNumber of properties in this heatmap cell
aggregation_valueFloat (nullable)Raw aggregated value before normalization (when using field-based heatmaps)

Pagination object

Pagination info:

NameTypeDescription
current_pageIntegerCurrent page number (1-based)
results_per_pageIntegerNumber of results per page. Maximum 1000.
total_pagesIntegerTotal number of pages available
total_resultsIntegerTotal number of results across all pages

Example requests and responses

Programming language

Select the programming language you want to display the code examples in.

Get map data by bounding box
Request
Shell session
curl -X GET "https://api.houski.ca/map?abort_over=500000&api_key=YOUR_API_KEY&bbox_ne_lat=51.17345&bbox_ne_lng=-113.96269&bbox_sw_lat=50.87234&bbox_sw_lng=-114.22313&bedroom_gte=4&cluster_over=1000"
TypeScript code
const houski_map_data_bounding_box = async (): Promise<MapResponse> => {

    // You must copy the MapResponse type declarations from the 
    // Houski API documentation to strongly type the response

    const url = new URL('https://api.houski.ca/map');
    url.searchParams.set('abort_over', '500000');
    url.searchParams.set('api_key', 'YOUR_API_KEY');
    url.searchParams.set('bbox_ne_lat', '51.17345');
    url.searchParams.set('bbox_ne_lng', '-113.96269');
    url.searchParams.set('bbox_sw_lat', '50.87234');
    url.searchParams.set('bbox_sw_lng', '-114.22313');
    url.searchParams.set('bedroom_gte', '4');
    url.searchParams.set('cluster_over', '1000');

    const response = await fetch(url);
    const data = await response.json();

    return data;
}

(async () => {
let data: MapResponse = await houski_map_data_bounding_box();

// Log the response
console.log(data);
})();
Response
JSON
{
  "aborted": false,
  "cache_hit": true,
  "cost_cents": 0.0853400006890297,
  "data": {
    "clusters": [
      {
        "latitude": 51.05131912231445,
        "longitude": -113.99966430664062,
        "number_of_properties": 303
      },
      {
        "latitude": 50.911903381347656,
        "longitude": -114.10991668701172,
        "number_of_properties": 1541
      },
      {
        "latitude": 50.90584182739258,
        "longitude": -114.0041046142578,
        "number_of_properties": 1627
      },
      {
        "latitude": 51.04402160644531,
        "longitude": -114.18861389160156,
        "number_of_properties": 2468
      },
      {
        "latitude": 50.9903678894043,
        "longitude": -114.10713958740234,
        "number_of_properties": 1777
      },
      {
        "latitude": 50.93876647949219,
        "longitude": -114.05735778808594,
        "number_of_properties": 1354
      },
      {
        "latitude": 51.12089157104492,
        "longitude": -114.19044494628906,
        "number_of_properties": 1442
      },
      {
        "latitude": 51.14344787597656,
        "longitude": -114.1373519897461,
        "number_of_properties": 3459
      },
      {
        "latitude": 51.14748764038086,
        "longitude": -113.98980712890624,
        "number_of_properties": 781
      },
      {
        "latitude": 51.071407318115234,
        "longitude": -114.1011199951172,
        "number_of_properties": 2316
      }
    ],
    "heatmap": [],
    "properties": []
  },
  "error": "",
  "heatmap_aggregation_field": null,
  "heatmap_aggregation_max_value": null,
  "heatmap_aggregation_min_value": null,
  "heatmap_aggregation_type": null,
  "is_clusters": true,
  "is_heatmap": false,
  "is_heatmap_aggregation": null,
  "is_heatmap_aggregation_invert_intensity": null,
  "is_properties": false,
  "pagination": {
    "current_page": 1,
    "has_next_page": false,
    "has_previous_page": false,
    "page_total": 1
  },
  "price_quote": false,
  "result_total": 10,
  "time_ms": 101
}
Basic heatmap (property density)
Returns a heatmap based on property density within the bounding box.
Request
Shell session
curl -X GET "https://api.houski.ca/map?api_key=YOUR_API_KEY&bbox_ne_lat=51.17345&bbox_ne_lng=-113.96269&bbox_sw_lat=50.87234&bbox_sw_lng=-114.22313&heatmap=true&heatmap_cell_limit=10"
TypeScript code
const houski_map_data_basic_heatmap = async (): Promise<MapResponse> => {

    // You must copy the MapResponse type declarations from the 
    // Houski API documentation to strongly type the response

    const url = new URL('https://api.houski.ca/map');
    url.searchParams.set('api_key', 'YOUR_API_KEY');
    url.searchParams.set('bbox_ne_lat', '51.17345');
    url.searchParams.set('bbox_ne_lng', '-113.96269');
    url.searchParams.set('bbox_sw_lat', '50.87234');
    url.searchParams.set('bbox_sw_lng', '-114.22313');
    url.searchParams.set('heatmap', 'true');
    url.searchParams.set('heatmap_cell_limit', '10');

    const response = await fetch(url);
    const data = await response.json();

    return data;
}

(async () => {
let data: MapResponse = await houski_map_data_basic_heatmap();

// Log the response
console.log(data);
})();
Response
JSON
{
  "aborted": false,
  "cache_hit": true,
  "cost_cents": 2.5396149158477783,
  "data": {
    "clusters": [],
    "heatmap": [
      {
        "aggregation_value": null,
        "intensity": 0.017478259280323982,
        "latitude": 51.20560836791992,
        "longitude": -113.9850845336914,
        "number_of_properties": 2253
      },
      {
        "aggregation_value": null,
        "intensity": 0.049603190273046494,
        "latitude": 51.20560836791992,
        "longitude": -114.17552185058594,
        "number_of_properties": 6394
      },
      {
        "aggregation_value": null,
        "intensity": 0.051201291382312775,
        "latitude": 50.919952392578125,
        "longitude": -114.17552185058594,
        "number_of_properties": 6600
      },
      {
        "aggregation_value": null,
        "intensity": 0.1329914778470993,
        "latitude": 51.20560836791992,
        "longitude": -114.0802993774414,
        "number_of_properties": 17143
      },
      {
        "aggregation_value": null,
        "intensity": 0.1412690132856369,
        "latitude": 51.110389709472656,
        "longitude": -113.9850845336914,
        "number_of_properties": 18210
      },
      {
        "aggregation_value": null,
        "intensity": 0.26275572180747986,
        "latitude": 51.01517105102539,
        "longitude": -113.9850845336914,
        "number_of_properties": 33870
      },
      {
        "aggregation_value": null,
        "intensity": 0.3050278127193451,
        "latitude": 50.919952392578125,
        "longitude": -113.9850845336914,
        "number_of_properties": 39319
      },
      {
        "aggregation_value": null,
        "intensity": 0.4229847192764282,
        "latitude": 51.01517105102539,
        "longitude": -114.17552185058594,
        "number_of_properties": 54524
      },
      {
        "aggregation_value": null,
        "intensity": 0.5016329884529114,
        "latitude": 51.110389709472656,
        "longitude": -114.0802993774414,
        "number_of_properties": 64662
      },
      {
        "aggregation_value": null,
        "intensity": 0.5264966487884521,
        "latitude": 51.110389709472656,
        "longitude": -114.17552185058594,
        "number_of_properties": 67867
      },
      {
        "aggregation_value": null,
        "intensity": 0.5289093255996704,
        "latitude": 50.919952392578125,
        "longitude": -114.0802993774414,
        "number_of_properties": 68178
      },
      {
        "aggregation_value": null,
        "intensity": 1.0,
        "latitude": 51.01517105102539,
        "longitude": -114.0802993774414,
        "number_of_properties": 128903
      }
    ],
    "properties": []
  },
  "error": "",
  "heatmap_aggregation_field": null,
  "heatmap_aggregation_max_value": null,
  "heatmap_aggregation_min_value": null,
  "heatmap_aggregation_type": "mean",
  "is_clusters": false,
  "is_heatmap": true,
  "is_heatmap_aggregation": false,
  "is_heatmap_aggregation_invert_intensity": false,
  "is_properties": false,
  "pagination": {
    "current_page": 1,
    "has_next_page": false,
    "has_previous_page": false,
    "page_total": 1
  },
  "price_quote": false,
  "result_total": 12,
  "time_ms": 81
}
Price heatmap with median aggregation
Returns a heatmap based on the median listing price of properties in each cell.
Request
Shell session
curl -X GET "https://api.houski.ca/map?api_key=YOUR_API_KEY&bbox_ne_lat=51.17345&bbox_ne_lng=-113.96269&bbox_sw_lat=50.87234&bbox_sw_lng=-114.22313&heatmap=true&heatmap_aggregation_field=estimate_list_price&heatmap_aggregation_type=median&heatmap_cell_limit=10"
TypeScript code
const houski_map_data_price_heatmap = async (): Promise<MapResponse> => {

    // You must copy the MapResponse type declarations from the 
    // Houski API documentation to strongly type the response

    const url = new URL('https://api.houski.ca/map');
    url.searchParams.set('api_key', 'YOUR_API_KEY');
    url.searchParams.set('bbox_ne_lat', '51.17345');
    url.searchParams.set('bbox_ne_lng', '-113.96269');
    url.searchParams.set('bbox_sw_lat', '50.87234');
    url.searchParams.set('bbox_sw_lng', '-114.22313');
    url.searchParams.set('heatmap', 'true');
    url.searchParams.set('heatmap_aggregation_field', 'estimate_list_price');
    url.searchParams.set('heatmap_aggregation_type', 'median');
    url.searchParams.set('heatmap_cell_limit', '10');

    const response = await fetch(url);
    const data = await response.json();

    return data;
}

(async () => {
let data: MapResponse = await houski_map_data_price_heatmap();

// Log the response
console.log(data);
})();
Response
JSON
{
  "aborted": false,
  "cache_hit": true,
  "cost_cents": 2.5396149158477783,
  "data": {
    "clusters": [],
    "heatmap": [
      {
        "aggregation_value": 576733.0,
        "intensity": 0.206860288977623,
        "latitude": 51.110389709472656,
        "longitude": -113.9850845336914,
        "number_of_properties": 18210
      },
      {
        "aggregation_value": 637003.0,
        "intensity": 0.4210264384746551,
        "latitude": 50.919952392578125,
        "longitude": -114.0802993774414,
        "number_of_properties": 68178
      },
      {
        "aggregation_value": 669490.0,
        "intensity": 0.5364672541618347,
        "latitude": 51.110389709472656,
        "longitude": -114.0802993774414,
        "number_of_properties": 64662
      },
      {
        "aggregation_value": 799936.0,
        "intensity": 1.0,
        "latitude": 51.01517105102539,
        "longitude": -114.17552185058594,
        "number_of_properties": 54524
      },
      {
        "aggregation_value": 541876.5,
        "intensity": 0.08299960196018219,
        "latitude": 51.01517105102539,
        "longitude": -113.9850845336914,
        "number_of_properties": 33870
      },
      {
        "aggregation_value": 584563.0,
        "intensity": 0.23468376696109772,
        "latitude": 51.20560836791992,
        "longitude": -114.0802993774414,
        "number_of_properties": 17143
      },
      {
        "aggregation_value": 518519.0,
        "intensity": 0.0,
        "latitude": 51.20560836791992,
        "longitude": -114.17552185058594,
        "number_of_properties": 6394
      },
      {
        "aggregation_value": 637884.0,
        "intensity": 0.4241570234298706,
        "latitude": 50.919952392578125,
        "longitude": -113.9850845336914,
        "number_of_properties": 39319
      },
      {
        "aggregation_value": 635795.0,
        "intensity": 0.41673389077186584,
        "latitude": 51.01517105102539,
        "longitude": -114.0802993774414,
        "number_of_properties": 128903
      },
      {
        "aggregation_value": 722781.0,
        "intensity": 0.7258338928222656,
        "latitude": 51.110389709472656,
        "longitude": -114.17552185058594,
        "number_of_properties": 67867
      },
      {
        "aggregation_value": 720508.0,
        "intensity": 0.7177569270133972,
        "latitude": 50.919952392578125,
        "longitude": -114.17552185058594,
        "number_of_properties": 6600
      },
      {
        "aggregation_value": 547350.0,
        "intensity": 0.10244938731193542,
        "latitude": 51.20560836791992,
        "longitude": -113.9850845336914,
        "number_of_properties": 2253
      }
    ],
    "properties": []
  },
  "error": "",
  "heatmap_aggregation_field": "estimate_list_price",
  "heatmap_aggregation_max_value": 799936.0,
  "heatmap_aggregation_min_value": 518519.0,
  "heatmap_aggregation_type": "median",
  "is_clusters": false,
  "is_heatmap": true,
  "is_heatmap_aggregation": true,
  "is_heatmap_aggregation_invert_intensity": false,
  "is_properties": false,
  "pagination": {
    "current_page": 1,
    "has_next_page": false,
    "has_previous_page": false,
    "page_total": 1
  },
  "price_quote": false,
  "result_total": 12,
  "time_ms": 106
}
Get map data by polygon
Polygon requests are made from a string in the format of 'lat_lng,lat_lng,lat_lng...', for all of the polygon's points.
Request
Shell session
curl -X GET "https://api.houski.ca/map?abort_over=500000&address_regex=^1(1|2|3)(1|2|3|4|5).*$&api_key=YOUR_API_KEY&cluster_over=1000&page=1&polygon=51.0447_-114.0719,51.0544_-114.0719,51.0544_-114.0856,51.0452_-114.0856&results_per_page=3&select=address"
TypeScript code
const houski_map_data_polygon = async (): Promise<MapResponse> => {

    // You must copy the MapResponse type declarations from the 
    // Houski API documentation to strongly type the response

    const url = new URL('https://api.houski.ca/map');
    url.searchParams.set('abort_over', '500000');
    url.searchParams.set('address_regex', '^1(1|2|3)(1|2|3|4|5).*$');
    url.searchParams.set('api_key', 'YOUR_API_KEY');
    url.searchParams.set('cluster_over', '1000');
    url.searchParams.set('page', '1');
    url.searchParams.set('polygon', '51.0447_-114.0719,51.0544_-114.0719,51.0544_-114.0856,51.0452_-114.0856');
    url.searchParams.set('results_per_page', '3');
    url.searchParams.set('select', 'address');

    const response = await fetch(url);
    const data = await response.json();

    return data;
}

(async () => {
let data: MapResponse = await houski_map_data_polygon();

// Log the response
console.log(data);
})();
Response
JSON
{
  "aborted": false,
  "cache_hit": true,
  "cost_cents": 0.119999997317791,
  "data": {
    "clusters": [],
    "heatmap": [],
    "properties": [
      {
        "address": "1213 608 9 Street SW",
        "latitude": 51.04768371582031,
        "longitude": -114.0837173461914,
        "property_id": "10ab0ffc777c870"
      },
      {
        "address": "1110 605 5 Avenue SW",
        "latitude": 51.048583984375,
        "longitude": -114.0745086669922,
        "property_id": "10c1af6fea51866f"
      },
      {
        "address": "1110 618 5 Avenue SW",
        "latitude": 51.04884719848633,
        "longitude": -114.07439422607422,
        "property_id": "113a70687880c4e9"
      }
    ]
  },
  "error": "",
  "heatmap_aggregation_field": null,
  "heatmap_aggregation_max_value": null,
  "heatmap_aggregation_min_value": null,
  "heatmap_aggregation_type": null,
  "is_clusters": false,
  "is_heatmap": false,
  "is_heatmap_aggregation": null,
  "is_heatmap_aggregation_invert_intensity": null,
  "is_properties": true,
  "pagination": {
    "current_page": 1,
    "has_next_page": true,
    "has_previous_page": false,
    "page_total": 59
  },
  "price_quote": false,
  "result_total": 176,
  "time_ms": 485
}

Response type declarations

TypeScript code
interface MapResponse {
    aborted: boolean;
    cache_hit: boolean;
    cost_cents: number;
    data: MapData;
    error: string;
    is_clusters: boolean;
    is_properties: boolean;
    is_heatmap: boolean;
    is_heatmap_aggregation?: boolean | null;
    is_heatmap_aggregation_invert_intensity?: boolean | null;
    heatmap_aggregation_type?: string | null;
    heatmap_aggregation_max_value?: number | null;
    heatmap_aggregation_min_value?: number | null;
    heatmap_aggregation_field?: string | null;
    pagination: Pagination;
    price_quote: boolean;
    result_total: number;
    time_ms: number;
}

interface MapData {
    properties: Property[];
    clusters: Cluster[];
    heatmap: HeatPoint[];
}

interface Cluster {
    latitude: number;
    longitude: number;
    number_of_properties: number;
}

interface HeatPoint {
    latitude: number;
    longitude: number;
    intensity: number;
    number_of_properties: number;
    aggregation_value?: number | null;
}

interface Pagination {
    current_page: number;
    has_next_page: boolean;
    has_previous_page: boolean;
    page_total: number;
}

// You can find the Property type on the /properties endpoint API docs
// https://www.houski.ca/api-documentation/properties