changedOutput schema / (root)
Previous value: -{
- "properties": {
- "available": {
- "anyOf": [
- {
- "type": "boolean"
- },
- {
- "type": "null"
- }
- ],
- "description": "`false` on no-data responses. Omitted on success — branch on `data !== null` if you want a single discriminator.",
- "title": "Available"
- },
- "data": {
- "anyOf": [
- {
- "additionalProperties": true,
- "description": "Projected house-price paths for the streets of one suburb, 2, 4 and\n8 years out.\n\nTwo suburbs can share a median and still be made of streets that behave\nvery differently; this endpoint is the street-by-street breakdown behind\nthe suburb-level number. Each row gives a street's current median, where\nthe model expects it in 2/4/8 years (in dollars and as a per-year growth\nrate), the year-by-year path it took to get here, and a little context\nabout the street itself — size, rent, how often it turns over.\n\nCoverage is deliberately partial: a street only appears if there is a\nreal sold median to anchor it to, so `streets` is a subset of the\nsuburb's streets, and `total` counts only those.",
- "example": {
- "area_level": "suburb",
- "area_name": "Belmont North",
- "metric": "street_price_forecasts",
- "streets": [
- {
- "annual_2y": 8,
- "annual_4y": 6.3,
- "annual_8y": 5,
- "current_price": 1159000,
- "history": [
- {
- "price": 1038603.34,
- "suburb_med": 866399,
- "year": 2024
- },
- {
- "price": 1083975.34,
- "suburb_med": 948908,
- "year": 2025
- },
- {
- "price": 1159000,
- "suburb_med": 1040068,
- "year": 2026
- }
- ],
- "houses_on_street": 146,
- "median_house_rent_week": 791.2,
- "n_sales": 289,
- "rental_turnover": "Every 5.9 years (quite tightly held)",
- "renters_pct": "18%",
- "sale_turnover": "Every 12.0 years (average turnover)",
- "street": "Wommara Ave",
- "target_2y": 1352652.97,
- "target_4y": 1480849.45,
- "target_8y": 1718217.61,
- "units_on_street": 4
- }
- ]
- },
- "properties": {
- "area_level": {
- "description": "Geographic level of `area_name`. Always 'suburb' here; present so responses across the area endpoints share one shape.",
- "title": "Area Level",
- "type": "string"
- },
- "area_name": {
- "description": "Suburb these streets belong to, as the canonical ABS SAL name — the resolved form of whatever suburb was requested, so echo this back rather than the caller's input.",
- "title": "Area Name",
- "type": "string"
- },
- "metric": {
- "description": "Identifies which dataset this payload is, for callers routing several area responses through common code. Always 'street_price_forecasts'.",
- "title": "Metric",
- "type": "string"
- },
- "streets": {
- "description": "One entry per forecastable street. Order is the stored order — stable between calls (so `offset` paging is safe) but not sorted by price, growth or name; sort client-side if you need a ranking.",
- "items": {
- "additionalProperties": true,
- "description": "Projected house-price path for one street in the suburb.\n\n**How to read a row.** `current_price` is where the street is today\n(an observed sold median). The three `target_*` fields are that same\nquantity projected 2, 4 and 8 years out, in dollars. The three\n`annual_*` fields are the same three projections expressed as a\ncompound annual growth rate in percent — they are a restatement of\nthe targets, not extra information, so\n`target_2y ≈ current_price × (1 + annual_2y/100) ** 2` (8.0 in\n`annual_2y` means 8% a year, not 0.08 and not 8% in total). The\nhorizons are cumulative from today, so `annual_4y` covers years 1–4\nincluding the years `annual_2y` already covered; they are three views\nof one path, not three consecutive segments.\n\n**Everything in dollars is anchored to the real sold median.** The\nforecast model carries its own estimate of what a street is worth\ntoday, and on tightly-held high-end streets that estimate can sit far\nbelow the price houses actually change hands at. So every dollar\nfigure in this row — `current_price`, the targets, and\n`history[].price` — is rescaled by one factor per street\n(`sold median ÷ model estimate`), which leaves the growth *shape*\nexactly as the model produced it while putting the levels on the real\nprice scale. The percentages are untouched by that rescale, because\na ratio cancels it out.",
- "example": {
- "annual_2y": 8,
- "annual_4y": 6.3,
- "annual_8y": 5,
- "current_price": 1159000,
- "history": [
- {
- "price": 1038603.34,
- "suburb_med": 866399,
- "year": 2024
- },
- {
- "price": 1083975.34,
- "suburb_med": 948908,
- "year": 2025
- },
- {
- "price": 1159000,
- "suburb_med": 1040068,
- "year": 2026
- }
- ],
- "houses_on_street": 146,
- "median_house_rent_week": 791.2,
- "n_sales": 289,
- "rental_turnover": "Every 5.9 years (quite tightly held)",
- "renters_pct": "18%",
- "sale_turnover": "Every 12.0 years (average turnover)",
- "street": "Wommara Ave",
- "target_2y": 1352652.97,
- "target_4y": 1480849.45,
- "target_8y": 1718217.61,
- "units_on_street": 4
- },
- "properties": {
- "annual_2y": {
- "anyOf": [
- {
- "type": "number"
- },
- {
- "type": "null"
- }
- ],
- "description": "The `target_2y` projection expressed as a compound annual growth rate, in percent per year — `8.0` means 8% a year (a decimal fraction like 0.08 is not what this field carries), compounding to roughly 16.6% in total over the two years. Same growth as `target_2y`, stated per-annum.",
- "title": "Annual 2Y"
- },
- "annual_4y": {
- "anyOf": [
- {
- "type": "number"
- },
- {
- "type": "null"
- }
- ],
- "description": "The `target_4y` projection as a compound annual growth rate, in percent per year, averaged across all four years (not the growth in years 3–4 alone). Typically lower than `annual_2y`: near-term momentum is assumed to fade toward a long-run rate.",
- "title": "Annual 4Y"
- },
- "annual_8y": {
- "anyOf": [
- {
- "type": "number"
- },
- {
- "type": "null"
- }
- ],
- "description": "The `target_8y` projection as a compound annual growth rate, in percent per year, averaged across all eight years. This is the closest thing here to the street's long-run trend rate.",
- "title": "Annual 8Y"
- },
- "current_price": {
- "description": "The street's current median house price in AUD, and the base every `target_*` and `annual_*` figure below is measured from. This is an observed sold median — what houses on the street actually sold for — not the forecast model's own estimate of present value. Streets with no sold-median on record are dropped from `streets` entirely rather than falling back to a model estimate, so this field is never a guess and never null.",
- "title": "Current Price",
- "type": "number"
- },
- "history": {
- "description": "Where the street has come from: one entry per year, oldest first, each pairing the street's modelled price with the suburb median for that year. The final entry is the present and its `price` equals `current_price`, so `history` and the `target_*` fields join into one continuous line through today.",
- "items": {
- "additionalProperties": true,
- "description": "One year of the street's modelled price history, with the suburb\nmedian alongside it as a baseline.\n\nTwo series, two different things. `price` is *this street* — a\nmodelled house-price level, because most streets do not sell enough\nhouses in a year to have a real median of their own. `suburb_med` is\nthe whole suburb's median for the same year, included so you can see\nwhether the street ran ahead of or behind its suburb. Compare the two\nas a *shape* over time, not as a like-for-like pair of medians.",
- "example": {
- "price": 970000,
- "suburb_med": 1040068,
- "year": 2026
- },
- "properties": {
- "price": {
- "anyOf": [
- {
- "type": "number"
- },
- {
- "type": "null"
- }
- ],
- "description": "Modelled median house price for this street in `year`, in AUD. Not an observed median — the street model's yearly level, rescaled by the same `current_price / model_estimate` factor applied to the targets, so the final year of `history` equals `current_price` and the chart line lands on the headline figure. Null when the model has no level for that year.",
- "title": "Price"
- },
- "suburb_med": {
- "anyOf": [
- {
- "type": "number"
- },
- {
- "type": "null"
- }
- ],
- "description": "Median house price for the whole suburb in `year`, in AUD. A context baseline only: it is the suburb's own observed median and is NOT rescaled, so it is on a different footing from `price`. Use it to judge relative direction (street outpacing the suburb or not), not to compute a precise street-vs-suburb premium.",
- "title": "Suburb Med"
- },
- "year": {
- "description": "Calendar year the two prices below refer to.",
- "title": "Year",
- "type": "integer"
- }
- },
- "required": [
- "year"
- ],
- "title": "StreetHistoryPoint",
- "type": "object"
- },
- "title": "History",
- "type": "array"
- },
- "houses_on_street": {
- "anyOf": [
- {
- "type": "integer"
- },
- {
- "type": "null"
- }
- ],
- "description": "Number of separate houses on the street — the size of the pool the median and turnover figures describe. A street with a dozen houses will have noisier numbers than one with two hundred.",
- "title": "Houses On Street"
- },
- "median_house_rent_week": {
- "anyOf": [
- {
- "type": "number"
- },
- {
- "type": "null"
- }
- ],
- "description": "Median advertised rent for a house on this street in AUD per week (Australian convention) — multiply by 52 for an annual figure. Houses only, and independent of the price forecast.",
- "title": "Median House Rent Week"
- },
- "n_sales": {
- "description": "Count of sales the street's price model was fitted on. Read it as a confidence weight — a street with a handful of sales behind it has a much softer forecast than one with hundreds — rather than as sales in any particular period.",
- "title": "N Sales",
- "type": "integer"
- },
- "rental_turnover": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "The same idea for tenancies rather than sales — how often rentals on the street turn over, as display text, e.g. 'Every 5.9 years (quite tightly held)'. A long interval suggests tenants who stay.",
- "title": "Rental Turnover"
- },
- "renters_pct": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Share of dwellings on the street occupied by renters rather than owners, as a preformatted string including the '%' sign (e.g. '18%') — not a number, and not a fraction. Strip the sign before doing arithmetic with it.",
- "title": "Renters Pct"
- },
- "sale_turnover": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "How often a typical house on the street changes hands, already written out for display — e.g. 'Every 12.0 years (average turnover)'. A sentence, not a number: the interval and its plain-language reading (tightly held vs. average vs. frequently traded) are baked into the one string. Parse it only if you must; the wording is not a stable enum.",
- "title": "Sale Turnover"
- },
- "street": {
- "description": "Street name as stored, e.g. 'Wommara Ave'. May be a shortened form of the full name (leading words only), so match it loosely rather than as an exact address component.",
- "title": "Street",
- "type": "string"
- },
- "target_2y": {
- "anyOf": [
- {
- "type": "number"
- },
- {
- "type": "null"
- }
- ],
- "description": "Projected median house price for this street two years from now, in AUD. A price level, not a change and not a multiplier: compare it directly against `current_price` to see the implied gain. Two years runs from the latest year in `history` (which equals today's `current_price`). Null when the model produced no 2-year figure.",
- "title": "Target 2Y"
- },
- "target_4y": {
- "anyOf": [
- {
- "type": "number"
- },
- {
- "type": "null"
- }
- ],
- "description": "Projected median house price for this street four years from now, in AUD — same basis as `target_2y`, longer horizon. Cumulative from today, so it includes the two years `target_2y` covers.",
- "title": "Target 4Y"
- },
- "target_8y": {
- "anyOf": [
- {
- "type": "number"
- },
- {
- "type": "null"
- }
- ],
- "description": "Projected median house price for this street eight years from now, in AUD — same basis as `target_2y`. The longest horizon offered and correspondingly the least certain.",
- "title": "Target 8Y"
- },
- "units_on_street": {
- "anyOf": [
- {
- "type": "integer"
- },
- {
- "type": "null"
- }
- ],
- "description": "Number of units/apartments on the street. Note that the price fields in this row are house prices; a high unit count tells you the street's character but does not feed the forecast.",
- "title": "Units On Street"
- }
- },
- "required": [
- "street",
- "current_price",
- "n_sales",
- "history"
- ],
- "title": "StreetForecastRow",
- "type": "object"
- },
- "title": "Streets",
- "type": "array"
- },
- "total": {
- "description": "How many forecastable streets the suburb has in all — counted before `limit`/`offset` are applied, so it is the figure to page against and will exceed `len(streets)` on a paged request. Streets with no sold median are already excluded, so this is usually fewer than the suburb's true street count.",
- "title": "Total",
- "type": "integer"
- }
- },
- "required": [
- "area_name",
- "area_level",
- "metric",
- "total",
- "streets"
- ],
- "title": "StreetForecasts",
- "type": "object"
- },
- {
- "type": "null"
- }
- ],
- "description": "The endpoint's payload, or `null` when Microburbs has no value."
- },
- "message": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Human-readable explanation. Omitted on success.",
- "title": "Message"
- },
- "reason": {
- "anyOf": [
- {
- "type": "string"
- },
- {
- "type": "null"
- }
- ],
- "description": "Machine-readable slug naming the no-data condition (e.g. `no_avm_for_GANSW704074813`). Stable per endpoint. Omitted on success.",
- "title": "Reason"
- }
- },
- "title": "ApiResponse[StreetForecasts]",
- "type": "object",
- "x-fastmcp-top-level-schema": "ApiResponse_StreetForecasts_"
-}New value: +null