Price is Right

API for partners

A calibrated time-to-sale and price-recommendation engine for your platform

The same engine that gives every seller on this platform a price recommendation: a hedonic value model (“what it's worth”), a hierarchical time-to-sale risk model (“how the asking price moves the time to sell”) and a decision layer that turns those two distributions into a wealth-maximising recommendation — with calibrated probabilities, not just a point estimate.

Apartments — all of Estonia, live today Architecture: any class of comparable assets Cars — sketched

How we prove it

Every number comes from a replay, not a pitch deck

The model is measured by a standing evaluation harness: a temporal train–test split with administrative censoring (no future leakage into training), weekly calibration checks and a decision replay in which the deployed recommender prices held-out listings and the outcomes unfold independently. Below are the numbers from its latest full run.

0,0032
Calibration error (ECE)

Calibration error of the weekly sale probability. When the model says “7% probability of selling this week”, that is what happens. The model captures 95% of the fair skill ceiling (one that cannot see seller urgency); discrimination C-index 0,678.

0,503 vs 0,504
Ex-ante forecast vs reality

P(sold within 26 weeks), forecast from the asking price known on day one, vs the share observed later (adjusted for drift). A horizon forecast that can only be made on a listing's first day — and it held.

+3 012 €
Expected extra wealth per listing
78%
Win rate
45%
Of the oracle's edge captured

Decision replay: the model's price recommendation vs typical seller behaviour on the same held-out listings (95% confidence interval 2 240…3 712 €). 45% of the edge that only an oracle knowing the true parameters would capture. Measured in the setting occupancy=empty, stigma 0,5.

Price levels and tax rules: real sources

Price levels are calibrated against actual transaction data from Maa-amet (the Estonian Land Board) (district table + decade price index). The rule for taxing sale proceeds is checked against §15 (5)–(6) of the Estonian Income Tax Act — the recommendation handles the tax exemption correctly, not approximately.

An honest limitation we are the first to state ourselves

All validation so far has been done against synthetic data whose structure the model shares. The held-out test rules out overfitting to noise, but not a deeper circularity: the model's form matches the generator's by construction. The evaluation harness is a fixed yardstick against which real data will be measured — not a claim that real-world numbers will match the ones above.

Measured and rejected

Negative results we publish

Every feature idea goes through the same replay before it reaches users. Two ideas failed the measurement and stayed out of production. This discipline is why the positive numbers above mean something — the same harness that approves can also reject.

Recommending a price-cut schedule
Did not ship

The idea: recommend the seller an upfront schedule of price cuts, not just an opening number. Replay result: a statistical tie — +10 € per listing, 95% confidence interval [−25, 39]. An effect indistinguishable from zero is not a feature, it is noise.

An anchor blended with comparable sales
Did not ship

The idea: blend the prices of comparable sold apartments into the recommendation's price anchor. Replay result: a monotonic loss of wealth — the larger the blending weight, the worse the outcome; the optimum turned out to be α = 0. Comparable sales stayed in the interface as an explanation, not in the decision model.

AI photo scoring (condition from photos)
Bounded to ±6%

A vision model assesses from the listing's photos what the hedonic model cannot see: finish quality, kitchen, bathroom, light, visible risk spots. The score is converted by a deterministic, documented formula into a shift of at most ±6% on the market anchor — half the spread two human assessors show on the same apartment. An honest limitation: in the synthetic world the same stock photos repeat across thousands of listings, so the photo→price relationship CANNOT be validated by replay here. The feature is in production as an informational layer; validation awaits real transaction data.

API quickstart

For your developers

JSON over HTTPS, four endpoints under /v1. Authenticate with an X-API-Key header (Authorization: Bearer is accepted for back-compat). Default rate limit 60 requests/min per key; a breach returns 429 with Retry-After.

POST /v1/market-price hedonic market value from raw listing features
curl -s "$API_BASE/v1/market-price" \
  -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
  -d '{
    "district_index": 0, "area_m2": 58.5, "renovated": true,
    "transit_minutes": 8.5, "school_score": 0.8,
    "top_floor_no_lift": false,
    "building_series": "1990s", "heating": "district"
  }'

→ {"market_price_cents": 14800000}
POST /v1/recommend the full advisory: optimal ask, indifference band, time-to-sale
curl -s "$API_BASE/v1/recommend" \
  -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
  -d '{
    "district_index": 0, "market_price_cents": 14800000,
    "seller_inputs": {
      "occupancy": "live_in", "monthly_rent": 0,
      "imputed_rent_monthly": 0, "horizon_weeks": 52,
      "deadline_week": 26, "deadline_prob": 0.9
    }
  }'

→ {
  "best_price_cents": 15340000,
  "indiff_lo_cents": 14970000, "indiff_hi_cents": 15760000,
  "expected_days": 64.3, "p_sold_within_horizon": 0.8712,
  "breakeven_carry_per_day_cents": 4120,
  "days_saved_per_1000": 1.92, "deadline_price_cents": 14760000,
  "market_price_cents": 14800000,
  "grid_boundary_hit": false, "grid_width_pct_used": 35.0,
  "curve": {"price_cents": [...], "expected_days": [...]},
  "viz": {...}   // chart-ready posterior grids; may evolve faster than the rest
}
POST /v1/comps weighted nearest sold comparables; only lat/lng/area required
curl -s "$API_BASE/v1/comps" \
  -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
  -d '{
    "lat": 59.4345, "lng": 24.809, "area_m2": 58.5, "rooms": 2,
    "building_series": "1990s", "renovated": true, "k": 25
  }'

→ {
  "anchor_price_cents": 14520000, "anchor_eur_m2_real": 2482.05,
  "n_comps": 25, "ess": 14.2, "local_median_weeks": 9.0,
  "comps": [
    {"listing": 4211, "district": 3, "lat": 59.4351, "lng": 24.8102,
     "distance_m": 214.0, "area_m2": 61.0, "rooms": 2,
     "series": "1990s", "sold_date": "2025-11-04",
     "realized_price_real_cents": 15100000,
     "realized_eur_m2_real": 2475.41, "weight": 0.0912},
    ...  // top 10
  ]
}
GET /health no auth
curl -s "$API_BASE/health"

→ {"status": "ok", "n_districts": 8, "model_version": "..."}
Versioning promise

/v1 response fields are additive-only: we add fields, we never rename, retype or remove them. A breaking change means /v2, with both versions served in parallel. The one exception is the viz block (chart-support data), which is explicitly documented as evolving faster.

Why it gets better over time

Every transaction on your platform makes the model more accurate

For every listing, the platform collects data in exactly the shape model retraining needs: attributes, opening price, price changes, final outcome and actual time to sell — with no personal data about the seller. The synthetic validation harness is a yardstick built ready for this dataset: as real outcomes accumulate, we will measure the model against them just as strictly as against synthetic data today. This is a flywheel a latecomer cannot buy their way into — with every partner the dataset grows, and every partner benefits from it.

Interested? mart@kollanekirss.ee We reply within one business day.