Data
Everything on this page exists to answer one question: does this number mean what you think it means?
Read it before the first integration goes out. Every rule below has produced a wrong report somewhere.
The figures describe one period, not today
"Current" means the newest period that has been built. It is never a live price.
| Resolution | One period is |
|---|---|
| 4–6 | one calendar month |
| 7–8 | a rolling three-month window |
The window widens at the fine resolutions because a single month is too thin to fill a cell that small — there would not be enough listings in it to say anything.
The table is rebuilt monthly, and a period is published only once it is complete. So
as_of can be up to 34 days old. Between the 1st and the 5th of a month, the newest
built period is the month before last.
Every response carries a snapshot block stating exactly how its figures were built, read
from the pipeline's own constants:
"snapshot": {
"as_of": "2026-07-01",
"built": "monthly",
"max_as_of_age_days": 34,
"window_months": 1,
"outlier_trim_pct": 2,
"min_listings_by_res": { "4": 5, "5": 6, "6": 8, "7": 10, "8": 10 }
}
The response also states period, window_start, window_end and fx_date.
Write the period into the sentence
The sentence to write is "in February 2026, over 1 December to 28 February". Not
"the median price", and never "the median price today". Cite period over
window_start..window_end — those fields exist so you do not have to guess.
Read the fields, not this page. outlier_trim_pct has already moved once, from 5 to 2.
Anything you hard-code from prose here can go stale; the snapshot block cannot.
Outliers are trimmed
Each country × property type × rooms group is trimmed to the 2nd–98th percentile band before the figures are computed. A palace and a parking space do not drag the median of a neighbourhood.
The exact quantile is in snapshot.outlier_trim_pct.
estimated: true means the figures are borrowed
A row in stats can carry "estimated": true. When it does, the figures are not that
cell's own market.
Too few listings fell in the cell, so the values are pooled from its six immediate neighbours — roughly 1.2 km out — by kRing smoothing.
{ "h3": "613498079269617663", "estimated": true, "median_price": 238000 }
Report that as an estimate for the area. Never as that cell's own figure. The per-
resolution floor below which a cell is withheld or smoothed is in
snapshot.min_listings_by_res.
A cell with too few listings and no usable neighbours is absent from the response entirely. An absent cell is not a cell worth zero.
Price filters are always USD
currency is a display setting. It converts the figures on the way out. It does not
change which listings were selected.
| Parameter | Effect |
|---|---|
min_price_usd, max_price_usd |
filter the underlying USD bins |
min_price, max_price |
refused, not ignored |
currency |
display only |
The bare names are refused deliberately. A filter that was silently dropped would hand you a complete, plausible, unfiltered answer that you would then report as a filtered one — the worst possible failure, because nothing about it looks wrong.
Every response restates the unit in filters.units, and echoes filters as applied,
defaults included. A filter you omitted still has a value: ad_sub_type defaults to buy,
so you get sale prices, not rents, unless you say otherwise. Cite the population the response
describes, not the one you thought you asked for.
Coverage: which markets can be answered
/coverage is computed live, and it costs
nothing to call. Use it before spending a metered request finding out a market is empty.
Two fields matter most.
prices_available — whether /stats/current
can answer for that country at all.
last_ad_parsed_at — how current that market's inventory is: when the country last
ingested listings. This is about the raw listings, not about the built statistics.
A null last_ad_parsed_at does not mean an empty market
It is null when no source targets that market directly. The API may still hold data for it. "We have no ingestion job pointed here" and "there is nothing here" are different statements, and the field only makes the first one.
A country can also be present in /coverage but missing from
/geo. That combination —
prices_available: true, searchable: false — means the API holds listings there but cannot
name places inside it, so you address it by coordinates rather than by name. Check
/coverage before concluding a market does not exist.
Geography has the full response shape, and the four states those two booleans make between them.
prices_available is not one field, it is two
On a /coverage country row it means some source ingested listings for this market
in the last 365 days. On a place from /geo, /geo/search or /geo/lookup it
means this place holds listings. Same name, different grain. Do not carry a value from
one into the other.
History
/stats/history is the same query over the
same table; the only difference is whether you name a period. The newest point of a history
series and /stats/current are identical by construction — not merely consistent.
snapshot.earliest_period tells you how far back the table goes.