# 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:write` scope. Use a test key while you build. See [authentication & keys](/docs/authentication).
- The vehicle's market. Every valuation is for one `country`, such as `DK`, `SE`, `DE` or `GB`.
- 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](/docs/concepts/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](/docs/reference/catalogue#get-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](/docs/guides/refusals-and-mileage). |
| 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](/docs/concepts/vehicle) describes every field, and the [request fields table](/docs/reference/valuations#request-fields) lists every constraint.

> **Note:** On this version, sending `vehicle.drive_side` returns `500 internal_error`. Omit the field until a fix is announced in the [changelog](/docs/changelog).

## 2. Send the request

A complete listing for a Danish dealer:

**curl**

```bash
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
```

**Ruby**

```ruby
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))
```

**Python**

```python
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))
```

**JavaScript**

```javascript
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));
```

[Open this request in the console playground](https://data-services.autouncle.com/console/playground?example=valuation_listing)

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](/docs/concepts/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](/docs/reference/valuations#the-problem-object) instead of a valuation envelope. Branch on HTTP status and `code`, never on message text. See [errors & retries](/docs/errors).

## 4. Read the result

Read these parts together. A price on its own is not enough to act on.

1. **`valuation.price`, `currency` and `price_basis`.** The price is an expected asking price for that basis in that market, not a trade-in or transaction price.
2. **`valuation.intervals`.** The 80%, 95% and 99% ranges around the estimate. Show at least the 80% range when you show a price.
3. **`precision.grade` and `precision.summary`.** `high`, `medium`, `low` or `indicative`. See [precision & intervals](/docs/precision).
4. **`vehicle`.** The [Vehicle](/docs/reference/vehicles#the-vehicle-object) that was actually valued: an [AVS](https://github.com/AutoUncle/avs) vehicle document with its catalogue identity, specification, registration and odometer. `identification` says how it was identified, with where each value came from in `identification.fields`. Check it matches your listing. If the model reads "Golf VII" when your listing is a Golf VIII, send the catalogue ID instead.
5. **`warnings` and `identification.status`.** What was ambiguous, unrecognized or assumed. An `ambiguous` vehicle lists the competing catalogue records in `identification.candidates`, and `assumed` values are marked in `identification.fields`.
6. **`improve_precision`.** What to send next time for a tighter result. See [improve precision](/docs/guides/improve-precision).
7. **`price_ratings`.** When you sent `pricing.asking_price`, `asking_price_rating` (5 is Super price, 1 is Expensive) and `stable_within_80pct_interval` tell you whether the rating holds across the uncertainty.
8. **`notes` and `attributions`.** Keep them with the result. See [show notes & attributions](/docs/guides/notes-and-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}](/docs/reference/valuations#get-v1-valuations-id); see [retrieve, replay & reconcile](/docs/guides/polling-and-replay).

## 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.value` must be in the `unit` you send. Do not convert miles to kilometres and then send `mi`.
- **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_ambiguous` warning tells you when the best match was chosen for you.
- **Showing test prices.** Test keys return simulated prices with a `synthetic_result` note. Never show them as market values.

## Next steps

- [Build a catalogue picker](/docs/guides/catalogue-picker) to pin the exact vehicle.
- [Improve precision with hints](/docs/guides/improve-precision).
- [Batch & bulk valuations](/docs/guides/batch-valuations) for whole stock lists.
