Valuation API
Our valuation,
as a service
One call returns the value and its range with a confidence grade, and on the plans that include them the comparable cars and their market, for an Australian used car. The same engine the dealer platform runs on.
Send make, model, year and kilometres, plus more detail if you have it. VIN and number plate lookup is available on request. Each value is worked out when you call, from market data we refresh every night.
- Up to 100
- cars valued in one call
- 99.2%
- of test cars given a value
- 4.4%
- median error on 7,314 recent dealer sales. Each car’s own advertisement was still among the evidence, so this reads better than a test with it taken out.
- Nightly
- market data refreshed after midnight, Perth time, then each value worked out when you call
- On request
- VIN and number plate lookup
{ "warnings": [ "variant_without_series" ], "confidence": { "label": "High", "score": 0.92 }, "make_canon": "TOYOTA", "final_price": 52239, "model_canon": "HILUX", "series_canon": null, "response_type": "valuation", "variant_canon": "SR5", "prediction_interval": { "basis": "EGC", "low_p10": 44148, "high_p90": 58225 } }
What you get back
The answer, and what it is built on.
The value, its range and a confidence grade, with any warnings. Depending on your plan you also get the comparable cars themselves, still for sale and sold, and their market: how many are for sale, how fast they sell and the days of supply. Each answer says which parts it carries in response_type, and a key only ever returns the parts its plan covers.
A real response for a 2021 Toyota HiLux SR5, diesel, automatic, ute, 4x4, 2.8L, 80,000 km in WA. The warning says the series wasn’t given, so the variant carried the match. Send the series (GUN126R for this car) and it goes.
| Key | Description |
|---|---|
| response_type | Which parts your key returns |
| make_canon | The car as we understood it: make |
| model_canon | Model |
| series_canon | Series, or null when none was matched |
| variant_canon | Variant |
| final_price | The value, EGC. null when we can’t value the car |
| prediction_interval | Its range |
| low_p10 | The 10th percentile |
| high_p90 | The 90th percentile |
| basis | Always EGC |
| confidence | A confidence grade |
| label | High, Medium, Low or Very Low |
| score | From 0 to 1 |
| warnings | How the value was reached, as codes (explained below) |
| market | Their market |
| live | Cars for sale now: how many, and their average and median days on market |
| sold | Cars sold in the window: how many, how many a month, and their average and median days to sell |
| scope | Where they are counted: a state, or Australia |
| years | The build years counted |
| days_of_supply | The cars for sale against the rate they sell |
| sold_window_days | How many days of sales are counted |
| comparables | The cars behind the value: up to 10 still for sale and 10 sold |
| year, variant, km, price | Each car’s year, variant, kilometres and EGC price |
| state, status | Its state as a code, and live or sold |
| days_listed, sold_days_ago | How long it has been listed, and how many days ago it sold (null while for sale) |
| spec | Its body, fuel, doors, drive, seats, series, gearbox, variant, cylinders and engine_litres |
| match | “exact”, or what differs, such as “differs: engine 2.4L vs 2.8L” |
| not_stated | The parts the ad doesn’t state. They count as a match |
| comparables_exact | How exact the list is |
| rule | What “exact” means, in words |
| listed | How many cars in each list are exact |
| target | The list size aimed for |
| widened | true when the list had to include cars that differ |
| in_scope | How many exact cars there are in scope |
| window_days | The days of history used for each list |
| comparables_scope | Where the comparable cars were drawn from |
| comparables_price_basis | EGC |
| comparables_subject_left_out | 1 when the car you sent was itself on the market and was left out of its own comparables, otherwise 0 |
Response types
Take the parts you use.
A key is issued for the parts you need, and answers with only those. Ask for the value alone and you get a few lines. Ask for the market and the comparable cars and you get the evidence without a number, for a system that does its own pricing.
| Plan | response_type | You get |
|---|---|---|
| Valuation | valuation | The car as we understood it, the value, its range, the confidence grade and any warnings. |
| Valuation and market | valuation + market | All of the above, plus the market block. |
| Market and comparables | market + comparables | The market block and the comparable cars, with no value. |
| All three | valuation + market + comparables | The value, the market and the comparable cars. |
{ "market": { "live": { "count": 77, "avg_days_on_market": 62, "median_days_on_market": 37 }, "sold": { "count": 37, "per_month": 37.0, "avg_days_to_sell": 55, "median_days_to_sell": 39 }, "scope": "WA", "years": [ 2020, 2022 ], "days_of_supply": 62, "sold_window_days": 30 }, "warnings": [ "variant_without_series" ], "confidence": { "label": "High", "score": 0.92 }, "make_canon": "TOYOTA", "final_price": 52239, "model_canon": "HILUX", "series_canon": null, "response_type": "valuation + market", "variant_canon": "SR5", "prediction_interval": { "basis": "EGC", "low_p10": 44148, "high_p90": 58225 } }
{ "market": { "live": { "count": 77, "avg_days_on_market": 62, "median_days_on_market": 37 }, "sold": { "count": 37, "per_month": 37.0, "avg_days_to_sell": 55, "median_days_to_sell": 39 }, "scope": "WA", "years": [ 2020, 2022 ], "days_of_supply": 62, "sold_window_days": 30 }, "make_canon": "TOYOTA", "comparables": [ { "km": 78727, "spec": { "body": null, "fuel": "DIESEL", "doors": "4", "drive": "4X4", "seats": "5", "series": "GUN126R", "gearbox": "AUTOMATIC", "variant": "SR5", "cylinders": "4", "engine_litres": 2.8 }, "year": 2021, "match": "exact", "price": 49999, "state": "WA", "status": "live", "variant": "SR5", "not_stated": [ "body" ], "days_listed": 63, "sold_days_ago": null }, { "km": 78483, "spec": { "body": null, "fuel": "DIESEL", "doors": "4", "drive": "4X4", "seats": "5", "series": "GUN126R", "gearbox": "AUTOMATIC", "variant": "SR5", "cylinders": "4", "engine_litres": 2.8 }, "year": 2022, "match": "exact", "price": 54981, "state": "WA", "status": "live", "variant": "SR5", "not_stated": [ "body" ], "days_listed": 32, "sold_days_ago": null }, { "km": 77427, "spec": { "body": null, "fuel": "DIESEL", "doors": "4", "drive": "4X4", "seats": "5", "series": "GUN126R", "gearbox": "AUTOMATIC", "variant": "SR5", "cylinders": "4", "engine_litres": 2.8 }, "year": 2021, "match": "exact", "price": 57997, "state": "WA", "status": "sold", "variant": "SR5", "not_stated": [ "body" ], "days_listed": 30, "sold_days_ago": 9 } ], "model_canon": "HILUX", "series_canon": null, "response_type": "market + comparables", "variant_canon": "SR5", "comparables_exact": { "rule": "exact = the same body shape, doors, seats, drive, fuel, gearbox, cylinders and engine (in litres) as the car asked about, within its variant and series; a part an ad does not state counts as a match and is listed under not_stated", "listed": { "live": 10, "sold": 10 }, "target": 10, "widened": false, "in_scope": { "live": 67, "sold": 33 }, "window_days": { "live": null, "sold": 30 } }, "comparables_scope": "WA", "comparables_price_basis": "EGC", "comparables_subject_left_out": 0 }
Prices and exact matches
Every price is EGC. Every comparable says how it matches.
- Every price in an answer, the value, the range and each comparable’s, is EGC: excluding government charges. The range and the comparables carry the label.
- The value doesn’t change by state. Our figures match the dealer app’s only where the app is showing EGC, because the app can also show drive-away prices.
- Comparables are exact-first: the same body, doors, seats, drive, fuel, gearbox, cylinders and engine size, in the same variant and series. Exact cars come first, nearest in kilometres.
- Only when there are too few exact cars to fill the list does it widen, to the cars that differ in the fewest parts. Each says what differs, such as “differs: engine 2.4L vs 2.8L”, and comparables_exact says whether the list widened.
- A part an ad doesn’t state counts as a match and is listed under not_stated. Send engine_size, for example “2.0L”, to make the engine part of the match.
- Where the car you sent can be told apart from the rest, it is left out of its own comparables.
One comparable that isn’t an exact match, from a 2019 HiLux Workmate, 2.8L, automatic, 4x4, asked about in Tasmania. There are too few exact Workmates there, so the list widened to all of Australia and to cars that differ. The comparable’s part comes first, then yours.
{ "km": 48712, "spec": { "body": null, "fuel": "DIESEL", "doors": "4", "drive": "4X4", "seats": "5", "series": "GUN125R", "gearbox": "AUTOMATIC", "variant": "WORKMATE", "cylinders": "4", "engine_litres": 2.4 }, "year": 2018, "match": "differs: engine 2.4L vs 2.8L", "price": 35399, "state": "VIC", "status": "live", "variant": "WORKMATE", "not_stated": [ "body" ], "days_listed": 45, "sold_days_ago": null }
When there isn’t enough evidence
A clear no, not a guess
With too few comparable dealer cars the engine returns no price, no range, no comparable cars and no market, says why, and gives the lowest confidence. A car we can’t value is a normal answer, not an error, and it isn’t charged. Your system can send the car to a person instead of acting on a number the market can’t support. Small groups of comparable cars can also move from day to day, so read the confidence label: Low means treat the number with care.
A real response for a 2016 Alfa Romeo 4C at 30,000 km in WA. The engine stops before it reads the car, so the make, model, series and variant come back empty too.
{ "warnings": [ "v3_insufficient_cohort_data" ], "confidence": { "label": "Very Low", "score": 0.05 }, "make_canon": null, "final_price": null, "model_canon": null, "series_canon": null, "response_type": "valuation", "variant_canon": null, "prediction_interval": null }
What you send
Make, model, year and kilometres. More detail, a tighter answer.
Send one car as a JSON object. Upper or lower case doesn’t matter, except where noted. A value we don’t recognise isn’t an error: it’s simply not used. Variant matters most, then series. Location only chooses where the comparables and the market come from, the car’s state when it holds enough cars, otherwise all of Australia. It doesn’t change the value.
| Field | Required | Format | Example |
|---|---|---|---|
make | Yes | Text | "Toyota" |
model | Yes | Text | "HiLux" |
year | Yes | Whole number, the build year | 2021 |
kilometres | Yes | Number, the odometer | 80000 |
variant | No | The badge | "SR5" |
series | No | The model series or code | "GUN126R" |
fuel | No | PETROL, DIESEL, HYBRID, ELECTRIC or PHEV | "DIESEL" |
transmission | No | AUTOMATIC, MANUAL or CVT | "AUTOMATIC" |
body_type | No | SUV, UTE, CAB CHASSIS, HATCH, SEDAN, WAGON, VAN, PEOPLE MOVER, COUPE or CONVERTIBLE. A ute’s cab wording, such as “Dual Cab Ute”, is read too. | "UTE" |
drive_type | No | 4X4, FRONT WHEEL DRIVE or REAR WHEEL DRIVE. All-wheel drive is 4X4. | "4X4" |
engine_size | No | Litres with one decimal and an L. Must match exactly. | "2.8L" |
cylinders | No | A number, as text. Must match exactly. | "4" |
doors | No | A number, as text | "4" |
seats | No | A number, as text | "5" |
location | No | The state code: NSW, VIC, QLD, WA, SA, TAS, ACT or NT | "WA" |
input_id | No, batches only | Your own reference. It comes back on the answer. | "stock-1234" |
Values are dealer retail, priced only from dealer stock. Private and auction prices never feed them. Where the variant has 15 or more comparable dealer cars covering the kilometres, the value comes off that variant’s own curve.
Requests and batches
One car, or up to 100 at a time.
- Send a POST with your key in the x-api-key header and Content-Type: application/json. No other header is needed. We send you the address with your key.
- One car: send its object. The answer is one object.
- A batch: send {"vehicles": [ ... ]} with up to 100 cars. The answer is {"results": [ ... ]}, in the order you sent. Each result starts with input_id: yours if you sent one, otherwise the car’s position as text ("0", "1"). Cars are valued 5 at a time, and each car counts as one valuation.
- A car that fails inside a batch doesn’t stop the batch. Its result is the one shown, with a short error message. Give every car in a batch make, model, year and kilometres: unlike a single call, a batch doesn’t refuse a car that is missing one, and that car comes back without a value.
{ "make": "Toyota", "model": "HiLux", "year": 2021, "kilometres": 80000, "variant": "SR5", "fuel": "DIESEL", "transmission": "AUTOMATIC", "body_type": "UTE", "drive_type": "4X4", "engine_size": "2.8L", "location": "WA" }
{ "vehicles": [ { "input_id": "stock-1234", "make": "Toyota", "model": "HiLux", "year": 2021, "kilometres": 80000 }, { "input_id": "stock-1235", "make": "Mazda", "model": "CX-5", "year": 2018, "kilometres": 95000 } ] }
{ "input_id": "7", "final_price": null, "method": "error", "error": "<message>" }
Errors
When the whole call is refused.
A missing, wrong or switched-off key is refused with a 401 and nothing is valued. These are the answers for the whole call. A car that can’t be valued, or one that fails inside a batch, is covered above.
| Status | Body | When |
|---|---|---|
401 | {"error": "API key required in the x-api-key header"} | No key was sent. |
401 | {"error": "Invalid or inactive API key"} | The key is wrong or switched off. In a batch, it stops at the first car. |
400 | {"error": "Body must be JSON"} | The body isn’t JSON. |
400 | {"error": "Required fields: make, model, year, kilometres"} | A single car is missing one of those. |
400 | {"error": "vehicles must be a non-empty array"} | vehicles is empty or isn’t a list. |
400 | {"error": "Batch size exceeds 100 vehicles"} | More than 100 cars in one batch. |
405 | {"error": "Use POST"} | Any method but POST. |
500 | {"error": "<message>"} | Something failed on our side. |
Warnings
How the value was reached, in plain words.
Warnings explain how a value was reached. A value with warnings is still a value: the confidence label says how far to trust it. A code that ends in <n> or similar carries a number or a name in place of the brackets. Two names start with v3_ for historical reasons.
| The car couldn’t be valued | |
v3_insufficient_cohort_data | Too few cars like this one in our market data to value it. |
v3_no_curve_data | No price curve could be drawn for this make and model. |
| What was matched | |
variant_without_series | A variant was given but no series, so the variant was matched across all series of the model. |
variant_unobserved_in_cohort | We haven’t seen that variant for sale or sold, so the value comes from the model as a whole. |
variant_uplift_unknown_no_series | No reliable premium is known for the variant without a series, so none was added. |
no_series_or_variant_cohort_<n>_variants | Neither series nor variant was given. The value is the model’s middle across n variants and is capped at Low confidence. |
no_variant_series_cohort_<n>_variants | A series but no variant was given. The value is the series’ middle across n variants and is capped at Low. |
cohort_dominated_by_<variant> | Most cars of this model we see are the named variant, so the model’s value leans toward it. |
very_low_rests_on_similar_variants | The value leans mostly on similar variants rather than this one, so it is labelled Very Low. The figure itself is unchanged. |
spec_sibling_anchor_cyl<c>_n<n> | The value leans on n sales of similar variants with the same cylinder count (c). |
sparse_variant_anchor_n<n> | Only n sales of this exact variant were available to anchor the value. |
| Years and kilometres | |
year_window_fallback_<n> | Too few cars of that exact year, so we used n years either side. |
km_above_curve_slope_extrapolated | The odometer is past the highest kilometres we see for this car, so the value continues the curve’s trend. |
km_above_curve_decay_<tier> | As above, with the value easing off at a set rate for very high kilometres. |
km_below_curve_slope_extrapolated | The odometer is below the lowest kilometres we see for this car, so the value continues the curve’s trend. |
variant_km_out_of_range_fell_back_to_cohort | The variant’s own prices don’t reach these kilometres, so the model’s curve was used. |
variant_km_oor_offset_carried | As above, with the variant’s usual premium over the model carried across. |
variant_below_min_trim_curve_kept | A variant priced well below the model keeps its own curve rather than being lifted to the model’s. |
| Spec adjustments | |
transmission_uplift_capped_<n>pct | The gearbox difference was capped at n percent. |
drive_vs_cohort_mix | Few cars like this one have this drive, so the drive adjustment allows for that. |
cab_step_within_trim | A ute’s cab type (single, extra, dual) was allowed for within the same trim. |
seats_<n>_not_offered_by_catalogue | The seat count given isn’t one the catalogue lists for this car, so it wasn’t used. |
spec_step_one_build | Only one build of this car is known, so no separate engine or seat adjustment was made. |
monotone_clamp_heavy_<n>pct_of_steps | The price curve needed smoothing at n percent of its steps (thin or uneven data). |
What’s available
One engine, and the data behind it
The data behind each of these is live today. Tell us what you need and we’ll scope it with you.
| Available now | |
|---|---|
| Valuation | Value, range, confidence grade, the comparable cars behind it (still for sale and sold) and their market, for one car or up to 100 at a time. |
| Vehicle catalogue | From make, model and variant to the full spec: engine, transmission, brakes, tyres and options, from a catalogue matched to specification rows. As a data extract or lookup we set up with you; an API call to follow. |
| On request | |
| Salvage check | Whether a VIN has been through a national salvage auction we monitor since 27 August 2026. |
| Market data feed | A separate weekly feed: days to sell, days of supply, price movement and cut rate, by segment and state. |
Market data feed: a real segment
More →{ "state": "WA", "week_to": "2026-10-11", "segment": "Medium SUV", "price_vs_market_pct": -0.7, "cut_rate_14d_pct": 26.1, "days_of_supply": 81, "days_to_sell": 37, "typical_price": 33000, "for_sale_now": 6419, "sold_90_days": 7764 }
Medium SUV in WA, the week to 2026-10-11. This is the separate weekly feed, not the market block that comes back with each valuation.
Vehicle catalogue: a real record
More →{ "entry_id": "MM-021620-2020", "year": 2020, "badge": "CRUISER", "body": "SUV", "drive": "FRONT WHEEL DRIVE", "gearbox": "CVT", "engine": { "capacity_cc": 2487, "cylinders": 4, "power_kw": 131, "fuel": "Battery Plus Internal Combustion", "induction": "Natural" }, "body_detail": { "doors": 5, "seats": "5" }, "brakes": { "front": "Disc Ventilated 305mm", "rear": "Disc Non-ventilated 281mm" }, "tyres": { "varies": ["225/60R18", "225/65R17"] }, "towing_kg": { "braked": 480, "unbraked": 480 }, "tare_kg": { "varies": [1640, 1655] } }
A 2020 Toyota RAV4 Cruiser, from our catalogue matched to specification rows. Where the variants on record disagree, as the tyres do here, we give the options rather than pick one.
Who it’s for
Anyone who needs a dealer retail value they can check
Finance providers, insurers, marketplaces, brokers, fleets, dealer groups, OEMs and data platforms.
Access and pricing
Keys issued by hand
We’re in early access, so we issue each key ourselves, with a worked sample for your use case. Pricing is per call and quoted on request.
See it on your own stock
Book a 30-minute demo and we’ll pull up your yard. If we already monitor your website, your cars are in the app the moment you’re approved.
Early access for dealers and data partners. We onboard by hand, and your first 14 days are free.