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.
Value a listing
Turn a structured listing, stock record or lead form into a valuation request, send it, and read the result correctly. This is the most common integration and the one that gives the most precise results.
What you need
- A key with the
valuations:writescope. Use a test key while you build. See authentication & keys. - The vehicle's market. Every valuation is for one
country, such asDK,SE,DEorGB. - As many of the vehicle's attributes as your source reliably knows. Mileage is required unless you explicitly opt in to an assumption.
1. Map your fields
Send what you know and omit what you do not know. An omitted field is treated as unknown; a guessed value is treated as a fact and can pull the price in the wrong direction.
| Your listing has | Send it as | Notes |
|---|---|---|
| Market or site country | country |
ISO 3166-1 alpha-2, for example DK. See markets. |
| Make and model text | vehicle.make, vehicle.model |
Free text is matched against the catalogue. |
| Version or trim text, such as "1.5 TSI Life" | vehicle.variant |
Helps pick the right drivetrain. |
| First registration date | vehicle.first_registration |
YYYY-MM-DD. Takes precedence over model_year. |
| Model or registration year only | vehicle.model_year |
Four-digit integer. |
| Odometer | vehicle.mileage |
Always with a unit: km, mi or mil (Scandinavian mile, 10 km). |
| Fuel | vehicle.fuel |
Prefer the values from /v1/catalogue/enums. |
| Gearbox | vehicle.transmission |
manual or automatic. Omit when unknown; it is not assumed to be manual. |
| Power | vehicle.power_hp |
Horsepower. Convert kW first (1 kW = 1.35962 hp), rounded. |
| Engine size | vehicle.engine_size_l |
Litres, for example 1.5. |
| Body, doors, seats, colour | vehicle.body, vehicle.doors, vehicle.seats, vehicle.color |
Help separate similar variants. |
| Equipment list | vehicle.equipment |
Feature keys from the enums endpoint, such as INFOTAINMENT_NAVIGATION. |
| Damage, leasing price and similar | vehicle.flags |
For example {"is_damaged": true}. See refusals. |
| Asking price | pricing.asking_price |
In the market currency. Returns a price rating. |
| Dealer or private seller | pricing.price_basis |
dealer_retail (default) or private_sale. |
The vehicle object describes every field, and the request fields table lists every constraint.
Note: On this version, sending
vehicle.drive_sidereturns500 internal_error. Omit the field until a fix is announced in the changelog.
2. Send the request
A complete listing for a Danish dealer:
curl https://data-services.autouncle.com/v1/valuations \
-H "Authorization: Bearer $AUTOUNCLE_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: valuation-listing-001' \
-d @- <<'JSON'
{
"country": "DK",
"vehicle": {
"make": "Volkswagen",
"model": "Golf",
"variant": "1.5 TSI Life",
"model_year": 2021,
"first_registration": "2021-03-15",
"mileage": {
"value": 45000,
"unit": "km"
},
"fuel": "petrol",
"transmission": "manual",
"body": "hatchback",
"power_hp": 130,
"engine_size_l": 1.5,
"doors": 5,
"color": "grey",
"equipment": [
"INFOTAINMENT_NAVIGATION",
"CAMERA_PARKING_REAR"
]
},
"pricing": {
"price_basis": "dealer_retail",
"asking_price": 189900
}
}
JSON
require "json"
require "net/http"
uri = URI("https://data-services.autouncle.com/v1/valuations")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("AUTOUNCLE_API_KEY")}"
request["Content-Type"] = "application/json"
request["Idempotency-Key"] = "valuation-listing-001"
request.body = JSON.generate({
"country" => "DK",
"vehicle" => {
"make" => "Volkswagen",
"model" => "Golf",
"variant" => "1.5 TSI Life",
"model_year" => 2021,
"first_registration" => "2021-03-15",
"mileage" => {
"value" => 45000,
"unit" => "km"
},
"fuel" => "petrol",
"transmission" => "manual",
"body" => "hatchback",
"power_hp" => 130,
"engine_size_l" => 1.5,
"doors" => 5,
"color" => "grey",
"equipment" => [
"INFOTAINMENT_NAVIGATION",
"CAMERA_PARKING_REAR"
]
},
"pricing" => {
"price_basis" => "dealer_retail",
"asking_price" => 189900
}
})
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
puts JSON.pretty_generate(JSON.parse(response.body))
import json
import os
import requests
response = requests.post(
"https://data-services.autouncle.com/v1/valuations",
headers={
"Authorization": f"Bearer {os.environ['AUTOUNCLE_API_KEY']}",
"Idempotency-Key": "valuation-listing-001",
},
json={
"country": "DK",
"vehicle": {
"make": "Volkswagen",
"model": "Golf",
"variant": "1.5 TSI Life",
"model_year": 2021,
"first_registration": "2021-03-15",
"mileage": {
"value": 45000,
"unit": "km"
},
"fuel": "petrol",
"transmission": "manual",
"body": "hatchback",
"power_hp": 130,
"engine_size_l": 1.5,
"doors": 5,
"color": "grey",
"equipment": [
"INFOTAINMENT_NAVIGATION",
"CAMERA_PARKING_REAR"
]
},
"pricing": {
"price_basis": "dealer_retail",
"asking_price": 189900
}
},
timeout=30,
)
print(json.dumps(response.json(), indent=2))
const response = await fetch("https://data-services.autouncle.com/v1/valuations", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTOUNCLE_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "valuation-listing-001",
},
body: JSON.stringify({
country: "DK",
vehicle: {
make: "Volkswagen",
model: "Golf",
variant: "1.5 TSI Life",
model_year: 2021,
first_registration: "2021-03-15",
mileage: {
value: 45000,
unit: "km"
},
fuel: "petrol",
transmission: "manual",
body: "hatchback",
power_hp: 130,
engine_size_l: 1.5,
doors: 5,
color: "grey",
equipment: [
"INFOTAINMENT_NAVIGATION",
"CAMERA_PARKING_REAR"
]
},
pricing: {
price_basis: "dealer_retail",
asking_price: 189900
}
}),
});
console.log(JSON.stringify(await response.json(), null, 2));
Give every intended valuation its own Idempotency-Key, for example your listing ID plus a version or date (listing-48213-2026-10-26). Then a retry after a timeout returns the recorded result instead of valuing (and charging) twice. See idempotency.
3. Check the status first
status |
HTTP | What it means | What to do |
|---|---|---|---|
valued |
200 | A price was produced. | Read the result. Live keys use one credit. |
refused |
4xx, usually 422 | The input cannot be valued as sent. | Read error.code and error.fix, correct the input, use a new idempotency key. Free. |
failed |
5xx | A service failed. | Back off and retry later with a new key. Free. |
Requests rejected before anything is recorded, such as an invalid body or a rate limit, return a Problem instead of a valuation envelope. Branch on HTTP status and code, never on message text. See errors & retries.
4. Read the result
Read these parts together. A price on its own is not enough to act on.
valuation.price,currencyandprice_basis. The price is an expected asking price for that basis in that market, not a trade-in or transaction price.valuation.intervals. The 80%, 95% and 99% ranges around the estimate. Show at least the 80% range when you show a price.precision.gradeandprecision.summary.high,medium,loworindicative. See precision & intervals.vehicle. The Vehicle that was actually valued: an AVS vehicle document with its catalogue identity, specification, registration and odometer.identificationsays how it was identified, with where each value came from inidentification.fields. Check it matches your listing. If the model reads "Golf VII" when your listing is a Golf VIII, send the catalogue ID instead.warningsandidentification.status. What was ambiguous, unrecognized or assumed. Anambiguousvehicle lists the competing catalogue records inidentification.candidates, andassumedvalues are marked inidentification.fields.improve_precision. What to send next time for a tighter result. See improve precision.price_ratings. When you sentpricing.asking_price,asking_price_rating(5 is Super price, 1 is Expensive) andstable_within_80pct_intervaltell you whether the rating holds across the uncertainty.notesandattributions. Keep them with the result. See show notes & attributions.
The returned vehicle uses the public vocabulary, so you can store it and post it back unchanged as the vehicle of a later request, for example to value the same car again with a new mileage.
5. Store what you need
Store at least request_id, status, country, mode, the price block, precision.grade, notes and attributions. The request_id (val_…) is in the response body and in the X-Valuation-Id header; the X-Request-Id response header is the HTTP request ID, which is different. You can always read the recorded result back later with GET /v1/valuations/{id}; see retrieve, replay & reconcile.
Pitfalls
- Guessing to fill gaps. Do not default a missing gearbox to manual or a missing fuel to petrol. Omit them.
- Unit mix-ups.
mileage.valuemust be in theunityou send. Do not convert miles to kilometres and then sendmi. - Wrong market. A Danish price in DKK does not apply to a car listed in Sweden. Value it in
SE. - Ignoring the resolved vehicle. Names like "Golf" can match several generations. The
generation_ambiguouswarning tells you when the best match was chosen for you. - Showing test prices. Test keys return simulated prices with a
synthetic_resultnote. Never show them as market values.
Next steps
- Build a catalogue picker to pin the exact vehicle.
- Improve precision with hints.
- Batch & bulk valuations for whole stock lists.