AutoUncle Data Services is in beta. The API, MCP tools and agent skill may change often, including breaking changes, until version 1.0. Read the changelog before you upgrade an integration.
How valuations work
This page explains what happens between sending POST /v1/valuations and reading the result: how the vehicle is resolved, which outcomes are possible, how credits move and how long results are kept. For every field, see the valuations reference.
Anatomy of a request
A valuation request describes one vehicle in one market:
{
"country": "DK",
"vehicle": {
"make": "Volkswagen",
"model": "Golf",
"model_year": 2020,
"mileage": { "value": 60000, "unit": "km" }
},
"pricing": { "price_basis": "dealer_retail" },
"options": { "resolution": "auto" }
}
| Part | Required | Purpose |
|---|---|---|
country |
Yes | The market. It sets the vehicle data, currency, mileage unit and price model. See markets. |
vehicle |
One of these three | Structured attributes and catalogue IDs. The most reliable input. See the vehicle object. |
description |
Listing text, up to 20,000 characters. | |
images |
Up to eight photos by HTTPS URL or inline base64. On a live key, one extra credit per request when a value was read from them; see credits. | |
pricing |
No | price_basis (dealer_retail, the default, or private_sale), an optional asking_price to rate, and seller_region. |
options |
No | resolution, min_precision, allow_mileage_estimation, allow_equipment_estimation, and include for optional sections: comparable listings, a trade-in price and a link to similar cars. |
Send it as application/json, at most 1 MB, with an Idempotency-Key header. Unknown fields are rejected with 400 invalid_request and a pointer to the field, so typos never pass silently.
Resolution: from input to a vehicle
Before it can be priced, the input is identified as a Vehicle: a catalogue identity (brand, model, generation, drivetrain and optionally equipment variant), specs, a registration year and a mileage. Normalization and the vehicle lookups run the same identification; see how a vehicle is identified.
- VIN or plate, with a live key, is looked up first, and what it finds fills the attributes you left out. Your own values always win. See VIN and registration plate.
- Catalogue IDs you send are used as given and must describe one consistent hierarchy. A lower level fills in its parents: a
drivetrain_idalone gives the brand, model and generation too. - Structured names and attributes (
make,model,variant,fuel,power_hpand so on) are matched against the catalogue. Explicit attributes always win over anything interpreted from text or photos. - Text and photos are read by deterministic rules and, for live keys when the deployment has it configured, by automated interpretation. Interpretation runs only when identity, registration year or core drivetrain attributes are still missing.
- Missing values are either refused or, where a documented default exists, assumed: marked
assumedinidentification.fieldsand reported inwarnings.
options.resolution controls how far this may go:
| Value | Behavior |
|---|---|
auto (default) |
Deterministic matching plus configured automated interpretation (live keys only). May assume a missing registration year. Refuses missing mileage unless you opt in to the baseline. |
no_ai |
Deterministic matching only. Same year and mileage policy as auto. |
strict |
Deterministic matching only, and refuses a missing registration year or mileage even when allow_mileage_estimation is true. Assumes no equipment even when allow_equipment_estimation is true. |
When vehicle.mileage is omitted but a description (or a photographed odometer) states the reading, live automatic resolution reads it instead of refusing. Its entry in identification.fields has source ai_text and basis extracted, and an ai_interpreted hint asks you to confirm it. Test mode, no_ai and strict never read mileage from text.
Assumed equipment
Equipment counts in the price, and a car whose equipment nobody states is valued as a bare one. If your source has no equipment list, you can set options.allow_equipment_estimation: true to let AutoUncle assume it, the way its own trade-in and valuation forms prefill equipment:
- The identified trim. When the vehicle's generation is settled and its equipment variant is known (identified, or sent as
catalogue.equipment_variant_id), the equipment the catalogue lists for that trim. - Similar vehicles. Otherwise, the equipment at least 70% of comparable vehicles on the market have. Live keys only: test keys never read market data, so a sandbox result stays deterministic.
Assumed equipment is only ever added. It never replaces or contradicts what you send in vehicle.equipment or what is read from your description or photos, and a no in the description (ohne AHK, ingen anhængertræk) is a no. If you send some equipment, only equipment of other kinds is assumed: a fixed towbar you send is not joined by an assumed detachable one.
Each assumed feature has source: "imputed", basis: "assumed" and status: "assumed" in identification.fields. The result carries an equipment_assumed warning that says which source was used, and an improve_precision hint with reason equipment_assumed asking you to confirm the equipment. Like an assumed mileage, assumed equipment caps precision.grade at low. When nothing could be assumed you get an equipment_not_assumed warning instead. The option is off by default.
Test keys never call automated interpretation, whatever the resolution. Every result tells you how each value was established, through source, basis and status in identification.fields. See the returned vehicle.
How supplied attributes check the catalogue
vehicle.fuel, transmission, drive and power_hp are evidence about the drivetrain. Use the values from GET /v1/catalogue/enums. A drivetrain that contradicts them is never valued:
- When the closest catalogue match contradicts a supplied value, the one drivetrain of the same generation that fits them all is used instead, with the warning
drivetrain_reselected. - When the catalogue match alone cannot pick a drivetrain but the supplied values single one out, that drivetrain is used.
- In both cases
identification.fields["/identity/drivetrain"].selected_byiscaller_evidence. - A supplied fuel outranks power. A CNG, LPG or ethanol car is matched to a drivetrain of that fuel, not to a petrol one, even when only the petrol drivetrain has the supplied power. The catalogue's power is then used,
identification.fields["/specification/powertrain/powerHp"].statusisconflict, and the warningspec_conflictnamespower_hp(precision is at mostmedium). When no drivetrain of the supplied fuel fits, the closest drivetrain of a compatible fuel (petrol, for an LPG, CNG or ethanol car) is valued with the supplied fuel, andspec_conflictsays so. A fuel of another kind (diesel or electric on a petrol drivetrain) is never valued that way: the warning isdrivetrain_conflict. A value that contradicts the drivetrain is neverconfirmed. - When several different drivetrains fit, for example a manual gearbox without power, the drivetrain is left open, the vehicle is valued at generation level, and the warning is
drivetrain_ambiguous. Supplypower_hporvehicle.catalogue.drivetrain_id. - When no drivetrain of the generation fits, the warning is
drivetrain_conflict. Check the values, or select the drivetrain from the catalogue. - An exact
vehicle.catalogue.drivetrain_idalways wins. Supplied values that contradict it are replaced by the catalogue's, with the warningspec_conflict, and precision is at mostmedium.
Power matches within 10% or 10 hp, whichever is larger.
Where configured, the description is also read for two further purposes. When several catalogue generations or drivetrains fit equally well, the description can decide between them; supplied catalogue IDs are never put to that question and always win. When vehicle.equipment or vehicle.condition is omitted, equipment and condition the description states are added, with source ai_text and basis extracted in identification.fields, with an ai_interpreted hint asking you to confirm them; a supplied list or condition is never asked about or changed. A catalogue level chosen this way is marked selected_by: "ai_text". Both are covered by the automated_interpretation note and attribution. Contact details are redacted before any description leaves the valuation service.
Outcomes
Every recorded valuation ends with one of three statuses:
status |
Meaning | HTTP | Billed |
|---|---|---|---|
valued |
A price was produced. | 200 |
One credit, live keys only |
refused |
The input cannot be valued as sent, for example missing_mileage, vehicle_not_identified or precision_below_minimum. Fix the input. |
The error's status, usually 422 (404 for unknown_catalogue_id) |
No |
failed |
A service failed, for example a scorer timeout. Try again later. | The error's status: 500, 502, 503 or 504 |
No |
Refused and failed results use the same envelope as a success, with a request_id and a nested error, and they are replayable with the same idempotency key.
Some problems are found before anything is recorded: invalid JSON or schema errors, authentication, scopes, countries, credits, rate and concurrency limits and idempotency conflicts. These return a Problem document as application/problem+json, with no val_… ID. See errors & retries.
Test and live
The same request works with both kinds of key:
- Test keys return a deterministic, synthetic price from a simulator, always with
precision.grade: "indicative",model.synthetic: true, intervalmethod: "synthetic"and asynthetic_resultnote. They use the real catalogue, validation, refusals, limits and error codes, so they exercise your integration fully, but the price is not a market value. - Live keys call AutoUncle's valuation model for the market. If the live service is unavailable the valuation fails visibly; it never falls back to a simulated price.
Comparable listings
A price on its own is hard to defend. Claims handlers, credit officers and auditors want to see the market behind it. Add "include": ["comparables"] to options and a valued result also carries comparables: up to five similar vehicles on sale now and up to five that left the market in the last 30 days, all from the same market as the valuation.
{
"country": "SE",
"vehicle": { "make": "Volvo", "model": "XC60", "model_year": 2021, "mileage": { "value": 6500, "unit": "mil" } },
"options": { "include": ["comparables"] }
}
How they are chosen. Listings of the same make, model and AutoUncle model group, a model year within one year of the vehicle (the same year in Germany and Italy), the same fuel, body and engine size when those are known, and the same gearbox when the vehicle is known to be an automatic. In Germany and Italy mileage is also limited to a band around the vehicle's. comparables.criteria states exactly what each listing had to match. Within that, listings at a typical price rating come first, then the nearest model year and mileage. Leasing rates are never included.
What a listing shows. Top-level facts only: make, model, model year, mileage rounded to the nearest 5,000 km or mi (500 in Swedish mil), the asking price rounded to three significant figures, the currency, AutoUncle's price rating and how many days it has been, or was, for sale. Fuel, gearbox, body and engine size are not repeated per listing; criteria states what every listing had to match. A comparable never identifies a listing or its seller: no seller names, contact details or region, no listing text, dates, links, registration plates, VINs, catalogue IDs or photos.
What they are not. Comparables are evidence, not the basis of the price. The valuation model scores the vehicle first, from far more market data, and the comparables are looked up afterwards; requesting them never changes the price, the intervals or precision. Their prices are asking prices, and for a recently sold listing it is the last asking price before the listing left the market, not the transaction price. A comparables_are_evidence note says so, and live comparables are attributed to AutoUncle market listings in attributions. Keep the note with the listings when you show them.
Outcomes. comparables.status is included with at least one listing, none_found when nothing matched (common for rare vehicles; the valuation still stands), or unavailable:
unavailable_reason |
When | What you get |
|---|---|---|
market_restricted |
Denmark. AutoUncle's Danish listing-data agreements do not allow listings to be passed on through an API. | Empty lists and a comparables_unavailable_in_market note. Request it anyway if you serve several markets; the valuation is unaffected. |
temporarily_unavailable |
The lookup failed or the request's processing budget ran out. | Empty lists and a comparables_unavailable warning. The valuation is still valued and billed. A new request with a new Idempotency-Key tries again; a replay returns the recorded result. |
Cost. Comparables cost one extra credit on a live key. Both credits are reserved when the valuation starts; the comparables credit is captured only when listings are returned (status: "included"). With none_found, unavailable (Denmark, a timeout) or a refused or failed valuation, it is released, and usage.charges shows what was charged, for example { "base": 1, "comparables": 1 }. If your balance cannot cover both credits, the request is rejected with 402 insufficient_credits. Test keys return fixed synthetic comparables around the simulated price, with synthetic: true, so you can build your display without spending credits. In Denmark a test key gets market_restricted, like a live key.
Stored with the result. Comparables are recorded with the valuation, so GET /v1/valuations/{id} returns the same listings for as long as the result is kept, even after the listings themselves have changed.
Trade-in price
Add "trade_in_price" to options.include and a valued result also carries trade_in_price: AutoUncle's estimate of a fair price for a dealer to pay when taking the vehicle in trade, with a range.
{
"trade_in_price": {
"status": "included",
"unavailable_reason": null,
"synthetic": false,
"price": 17800,
"low": 17400,
"high": 18200,
"currency": "EUR"
}
}
What it is. An estimate, not an offer. A dealer's actual offer also depends on the vehicle's condition, its history and the dealer's own stock. A trade_in_price_is_estimate note says so; keep it with the price when you show it. Live trade-in prices are attributed to the AutoUncle valuation model.
Price basis. A trade-in price always relates to the vehicle's dealer retail market value: that is the market a dealer takes the vehicle in for. With pricing.price_basis: "private_sale", the valuation keeps its private-sale price and the trade-in price still relates to the dealer retail value, so it can be compared with the private price directly.
Markets. Available in Austria, Denmark, France, Germany, Italy, the Netherlands, Poland, Portugal, Spain, Sweden, Switzerland and the United Kingdom. In every other market, such as Finland, Romania and Belgium, status is unavailable with unavailable_reason: "market_unsupported", price, low and high are null, and a trade_in_price_unavailable_in_market note says so. If it could not be calculated for this request, unavailable_reason is temporarily_unavailable with a trade_in_price_unavailable warning; the valuation is still valued.
Cost. One extra credit on a live key, reserved with the valuation and captured only when the trade-in price is returned (status: "included"); otherwise it is released. usage.charges shows it as trade_in_price. Test keys return a fixed synthetic example derived from the simulated price, with synthetic: true, for free.
Link to similar cars
Add "similar_cars_link" to options.include and a valued result also carries similar_cars_url: a link to cars similar to the valued vehicle for sale on the market's own AutoUncle site, such as https://www.autouncle.de/…, in the market's language. The search uses the same criteria as comparable listings. Use it to let your user look at the market themselves.
The link is free, available in every market including Denmark, and the same for test and live keys. It is a link to a live search page, so what it shows changes with the market; it is not stored evidence like comparables. If the link cannot be built, similar_cars_url is null with a similar_cars_link_unavailable warning.
Credits: reserve, capture, release
For a live key, one credit is reserved when the valuation starts, plus one for each requested add-on. When it finishes:
valued: the credit is captured.usage.billableistrueandusage.credits_usedis1, plus one for each add-on returned, such as comparable listings or a trade-in price.refusedorfailed: the credit is released back to your balance.usage.credits_usedis0.
With comparables or a trade-in price requested, one more credit each is reserved alongside the first and captured only when that add-on is returned. usage.charges breaks credits_used down, for example { "base": 1, "comparables": 1, "trade_in_price": 1 }.
Requests rejected before they start (rate or concurrency limits, missing credits, permissions) never reserve anything. An idempotent replay never charges again: usage.credits_used is 0 and usage.original_credits_used shows what the original call used. If a process stops in the middle, a recovery job settles the reservation from the recorded outcome. See credits & billing.
Processing budget
Each valuation runs within one eight-second processing budget, measured from the start of the operation, with half a second reserved for recording the result and settling credits.
- A VIN or plate lookup has a 2.5-second cap.
- Image DNS lookups and downloads share a three-second cap.
- Automated interpretation has a four-second cap.
- Scoring has a 2.5-second cap.
- Every step receives only what is left of the common budget, so the caps never add up to a longer request.
- Interactive retries to providers are disabled.
Network steps have hard wall-clock limits. Database work is checked between stages rather than interrupted mid-transaction, so recording and refunds may finish slightly after the budget. Waiting for a concurrency slot (up to about two seconds) happens within the same deadline. This is a processing policy, not a guaranteed response time: set your client timeout to 10 to 15 seconds.
When a dependency fails
Interpretation and images are called only when they are needed: an exact catalogue drivetrain plus registration year, or complete structured core attributes, skip them. Test keys, no_ai and strict never call interpretation.
Once interpretation or image retrieval is invoked, a timeout, an outage or an invalid response stops the valuation. Scoring does not run, the result is failed with the failing service named (vehicle_resolution, image_fetch or valuation_engine), and no credit is used. A successful interpretation that simply finds nothing useful is different: it is not a failure, and the valuation continues with what it has, reporting unused input in warnings.
A VIN or plate lookup is different: when it times out or is unavailable, the valuation continues with the attributes you sent and a registry_lookup_failed warning. It fails (with service: "vehicle_registry", no credit used) only when the identifier was all the request said about the vehicle. See VIN and registration plate.
To avoid these dependencies, send structured attributes or catalogue IDs. To retry, follow the retry rules.
Reading results back
GET /v1/valuations/{id} returns a recorded valuation, including refusals and failures, with the notes and attributions that applied when it was produced. It needs valuations:read, is free, and omits the usage block. Results are private to your workspace, and test and live results are separate: a test key cannot read a live result and vice versa.
Recorded results are kept for 30 days for test keys and 13 months for live keys. Raw descriptions, photos, VINs and registration plates are not stored in valuation records.