Valuation API

Versioned, keyed and rate limited. It returns what the screen shows: the range, its comparables and adjustments, the confidence, days to turn and a buy price. Never a number without its evidence.

Request

curl -X POST https://spotlot.io/api/v1/value \
  -H "Authorization: Bearer sk_spotlot_..." \
  -H "Content-Type: application/json" \
  -d '{
    "make": "Ford",
    "model": "Ranger",
    "year": 2019,
    "badge": "XLT",
    "odometer_km": 95000,
    "state": "WA"
  }'

make and model are required; everything else sharpens the comparable set.

Response

A real answer to the request, computed 25 Sept, 05:39 pm AWST as an internal check; 58 comparables in the response, two shown; valuation_id is null because a check stores nothing.

{
  "ok": true,
  "valuation_id": null,
  "model_version": "spotlot-val-0.14.0",
  "range": {
    "low": 29903,
    "mid": 32188,
    "high": 33990,
    "currency": "AUD",
    "basis": "asking prices restated excluding government charges; each comparable carries the price_basis it was advertised at"
  },
  "confidence": {
    "score": 0.839,
    "label": "high",
    "parts": {
      "sample": 1,
      "tightness": 0.58,
      "recency": 0.83
    },
    "veto_reason": null
  },
  "trims": null,
  "days_to_turn": {
    "estimate": 68,
    "basis": "used 2018–2020 Ford Ranger cars seen to sell in WA — a sold marker or a page gone, aged by the seller's own published listing date",
    "n": 47,
    "cutShare": 0.91,
    "scope": "year_state"
  },
  "sold": {
    "n": 15,
    "medianFinalAsk": 31564,
    "p25": 28403,
    "p75": 33413,
    "shareCutFirst": 0.36,
    "medianDays": 24,
    "basis": "final asks of cars seen to sell within 120 days (seller marked sold, or page gone), adjusted to this car's kilometres and year and weighted like the range; a final ask is the ceiling of a deal we cannot see, never the price paid"
  },
  "buy_price": {
    "value": 27150,
    "workings": [
      "start from the middle of the range: $32,188 (weighted median of adjusted asks)",
      "target gross margin 10% (model parameter, not market data)",
      "range is 13% wide, so an uncertainty discount of −3.2% (a quarter of the width, capped at 5%)",
      "slow cohort: 68 days to turn > 45, so the margin requirement rises by +2.5%"
    ]
  },
  "comparables": [ /* 58 in the response; 2 shown */
    {
      "url": "https://www.laneford.com.au/cars/used-magnetic-2018-ford-ranger-1010328",
      "source": "dealer:laneford",
      "year": 2019,
      "badge": "XLT",
      "trim": "xlt",
      "odometer_km": 41305,
      "price": 29977,
      "price_basis": "excl_govt_charges",
      "adjusted_price": 26156,
      "weight": 4.1,
      "status": "sold",
      "exit_basis": "gone",
      "days_on_market": 4.9,
      "price_changes": 0
    },
    {
      "url": "https://www.motormall.com.au/cars/used-grey-2019-ford-ranger-8994",
      "source": "dealer:motormall",
      "year": 2019,
      "badge": "XLT",
      "trim": "xlt",
      "odometer_km": 134112,
      "price": 29990,
      "price_basis": "excl_govt_charges",
      "adjusted_price": 32774,
      "weight": 3.41,
      "status": "live",
      "exit_basis": null,
      "days_on_market": 45.5,
      "price_changes": 6
    }
  ],
  "adjustments": [
    {
      "label": "comparable set narrowed",
      "detail": "58 of 759 comparables kept — 2019 xlt only. A model year or trim with enough of its own listings is compared against itself rather than corrected across, because the correction is capped at 35% of a comparable's ask and a facelift year can move more than that."
    },
    {
      "label": "odometer slope",
      "detail": "Theil–Sen fit within model years over 55 comparables: -712 $/10,000 km. Fitted within years rather than across them, so it measures kilometres and not the age that comes with them. Each comparable's price is shifted to the subject's 95,000 km."
    },
    {
      "label": "price basis",
      "detail": "Range excludes government charges. 30 of 58 comparables were advertised that way; 16 were advertised drive-away and have had their state's stamp duty removed; 12 do not state a basis and are taken as advertised; 0 could not be converted and are down-weighted. Registration and CTP remain inside converted prices — they depend on term, vehicle class and insurer, so they are not estimated, which leaves this figure a little above a true excluding-charges price."
    }
  ],
  "evidence": {
    "comparablesFound": 759,
    "liveCount": 39,
    "delistedCount": 4,
    "soldCount": 15,
    "effectiveSampleSize": 147,
    "iqr": 4087,
    "subjectCondition": "used",
    "comparableConditions": {
      "used": 58
    },
    "priceBasis": "excl_govt_charges",
    "split": false,
    "restrictedTo": {
      "trim": true,
      "year": true,
      "condition": true
    },
    "priceBasisMix": {
      "excl_govt_charges": 30,
      "drive_away": 16,
      "unknown": 12
    }
  },
  "context": {
    "ancap": {
      "stars": 5,
      "ratingYear": 2015,
      "makeModel": "Ford Ranger",
      "window": "Sep 2015 to Jul 2022",
      "match": "window"
    },
    "gvg": {
      "variants": 38,
      "bestFuelCombined": 6.9,
      "co2Range": [
        182,
        262
      ],
      "year": 2022,
      "match": "nearest"
    },
    "fleet": {
      "make": "Ford",
      "vehiclesOnRegister": 869688,
      "year": 2025
    },
    "recalls": {
      "available": false,
      "count": 0,
      "latest": null,
      "latestDate": null
    },
    "listedNow": 9606,
    "datasetsJoined": [
      "ANCAP",
      "Green Vehicle Guide",
      "BITRE fleet"
    ]
  },
  "units": {
    "range": "AUD, asking prices restated excluding government charges, never settlements",
    "odometer_km": "kilometres as advertised",
    "days_on_market": "days since our first observation of the listing, not the seller's own age",
    "days_to_turn": "median days advertised at exit, by the seller's own listing age, over the matching cohort's proved sales (basis says which cohort answered)",
    "sold": "final asks of comparables seen to sell within 120 days, adjusted to the subject; a final ask is the ceiling of a deal we cannot see, never the price paid"
  },
  "quota_remaining_today": 499
}

When the evidence is thin, it says so

{
  "ok": false,
  "reason": "insufficient_comparables",
  "comparables_found": 1,
  "needed": 3
}

Below three comparables: HTTP 200, ok: false and the real count. Treat it as an answer.

Auth

Authorization: Bearer <key>; unknown or disabled keys get 401. Keys are stored hashed and shown once, at issue.

Issued by hand while the API is young: email for a key with a line on what you are building.

Rate limit

A rolling 24-hour quota per key; over it is 429. Every answer carries RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset, and the body carries quota_remaining_today.

Corpus behind it

237,367 live listings · 20,936,437 observations · 8 public datasets joined, as at 25 Sept, 05:30 pm AWST. Answers are as good as the coverage, so the coverage is on screen.

Series

The daily rollups behind the market page and the reports, as data. Public, no key.

curl "https://spotlot.io/api/v1/series?series=state&scope=WA&from=2026-08-18&to=2026-08-31"

# or, as a file
curl "https://spotlot.io/api/v1/series?format=csv" -o spotlot-market.csv

series is market, state or fuel; scope narrows to one; from and to are UTC days; format=csv gives one row per day with a gap column. A missing day is a gap, never interpolated; a series break carries the register’s own words; every column is named for its unit.