Design philosophy

Every endpoint is built on the same handful of decisions, so learning one endpoint gets you most of the way through the next: the same response shape, the same way of charging, and the same filter, sort and select parameters wherever an endpoint supports them. The quick start has a runnable request in your language.

Every endpoint declares one unit of billing

Endpoints that return property records bill for the fields you selected on the rows you got, so a tighter select parameter is a smaller bill. A typical field is $0.001 per field per row.

Endpoints that return something other than a property record bill per thing returned: a value from aggregate at $0.01, a cluster or heatmap cell from map at $0.00001, a place from location at $0.00001, a nested row from expand at $0.001, a predicted value from predict at the same rate as the field it predicts.

One endpoint is flat priced per request. The automated valuation model endpoint costs $5.00 USD per request because it runs a full valuation rather than handing back stored values. Every rate sits in one table on the pricing page, and each endpoint's own page states what it charges.

Searching is free, returning is what costs

Nothing is billed on how much data was searched to answer you. Filtering across the whole country costs no more than filtering across one street when the same amount comes back. Scanned rows are not a billing unit anywhere in the API, so where a scan needs a ceiling it gets a row limit instead of a charge: map has no ceiling by default, and you can set one yourself with the abort_over parameter.

A repeat of an identical request is served from cache and priced exactly the same as the first one, and the response tells you which one you got. You are paying for the data, not for the work of producing it.

Identifiers and links are priced at a tenth

IDs, links, slugs, place names, coordinates and source tags bill at $0.0001 per field per row, a tenth of a typical field. They are not really data on their own, just what makes the rest of the data usable, so selecting the ones your interface needs stays close to free. Per-field rates are listed on the fields page.

Price quotes on any request

Add price_quote=true to a request on any billed endpoint and the response comes back with the cost of the current page of results, an empty data field, and no charge. The quote is the real cost of that exact request, not an estimate from a formula.

The published rate and the charged rate are the same number

Every price on this site is read from the same definition the billing code charges from. No page quotes a rate of its own, so the pricing page, the endpoint pages and your invoice cannot drift apart.

Pay-as-you-go usage has a $99 USD/month minimum. If usage is below $99, you're billed $99. See the pricing page for details, including enterprise contracts for companies over $2M revenue.

Consistent logic for sorting, filtering, and field selection

Sorting, filtering and field selection work the same way on every endpoint that supports them, down to the operator suffixes on filter parameters. Code written against one endpoint mostly moves to the next one unchanged.

Failures come back as the same type as successes

A bad parameter, a missing key, a disabled subscription or a rate limit returns the endpoint's own response type with the data empty, the error string filled in, and a cost of zero. A strongly typed client parses one struct on both paths and reads one field to find out which it got. Failed requests are never billed.

There is one deliberate exception. A URL that matches no endpoint at all has no response type to fill in, so it returns a small object carrying just the error and a link back to this documentation.

Unknown parameters are rejected, not ignored

A misspelled or unsupported parameter fails the request, and the error names the parameters you probably meant. A typo that silently returns unfiltered data costs far more than an error does, so nothing is quietly dropped.

Built for AI assistants, not only for people

There are two ways in, and they do different jobs. The Model Context Protocol (MCP) server lets an assistant query the data directly inside a conversation, which suits research and prototyping.

The skill file teaches a coding assistant to write the integration for you, including how to keep requests cheap. It follows the open Agent Skills standard, so the same file works in Claude Code, Cursor, Gemini CLI and others without modification. The skill walkthrough covers setup for each.

Addressed by location, not by ID

Properties are addressed by a hierarchy of location strings rather than by an ID, which keeps front-end URLs readable and indexable. Consider this one:

https://houski.ca/property/ca/ab/calgary

The country, province and city are enough for the API to retrieve every property in that area. The hierarchy is deterministic, so the API derives the IDs itself and hands them back in the response. The two per-property endpoints, predict and the valuation endpoint, are the exception: both take a property_id, which you get from any of the other endpoints.

Opinionated link structure

Responses can include relative links to where each resource belongs in your interface, such as a property's detail URL. Select the links you want as fields.

The properties endpoint includes the ui_info object

ui_info carries the context of the query (community, city, address, province, country) even when no results come back. That gives your interface a stable resource for things like breadcrumbs on an empty result page.

Responses contain a pagination object

Where applicable, responses include a standard pagination object. It is identical across endpoints, so pagination logic is written once and reused.