# API reference

Generated from the AutoUncle Data Services OpenAPI contract. Do not edit this file by hand.

Base URL: `https://data-services.autouncle.com`. Authenticate every request with `Authorization: Bearer $AUTOUNCLE_API_KEY`.
Canonical schemas: https://data-services.autouncle.com/openapi.yaml. Human-readable reference: https://data-services.autouncle.com/docs/api-reference

## Valuation request fields

| Field | Type | Description |
| --- | --- | --- |
| `country` | string | Valuation market as an ISO 3166-1 alpha-2 code, such as DK, DE or GB. The market selects its own vehicle data, currency and mileage conventions. 2 to 10 characters. |
| `vehicle` | object | A vehicle as a request describes it: either an AVS vehicle document (any `vehicle` an endpoint returned, posted back unchanged, or one you build), recognized by its `avs` member, or the vehicle's attributes (VehicleAttributes). Omit unknown values instead of guessing. |
| `vehicle.make` | string | Vehicle manufacturer or make, such as VW or BMW. Catalogue brand_id avoids ambiguous names. At most 200 characters. |
| `vehicle.model` | string | Model name as supplied by your source, such as Golf. Catalogue model_id avoids name mapping and spelling ambiguity. At most 200 characters. |
| `vehicle.variant` | string | Free-text engine, trim or version designation, such as 1.5 TSI DSG. This can help resolve a more precise catalogue identity. At most 200 characters. |
| `vehicle.body` | string | Body style or source label, such as hatchback, estate or SUV. Unknown labels may remain unresolved. At most 200 characters. |
| `vehicle.fuel` | string | Fuel or electrification type: petrol, diesel, electric, hybrid (a full hybrid that cannot be plugged in), plug_in_hybrid_petrol, plug_in_hybrid_diesel, lpg, cng, ethanol or hydrogen, as listed by /v1/catalogue/enums. Source labels are also normalized when recognized. At most 200 characters. |
| `vehicle.color` | string | Exterior colour or colour family from your source. Colour is normalized when possible. At most 200 characters. |
| `vehicle.catalogue` | object | Stable AutoUncle catalogue UUIDs. Supply any known levels; IDs must describe one consistent vehicle hierarchy. |
| `vehicle.catalogue.brand_id` | string | Make UUID returned by the brands catalogue endpoint. All lower-level IDs must belong to this make. 1 to 100 characters. |
| `vehicle.catalogue.model_id` | string | Model UUID returned by the models catalogue endpoint. Virtual model aliases are resolved to their canonical model for scoring. 1 to 100 characters. |
| `vehicle.catalogue.generation_id` | string | Generation UUID returned for the selected model. This identifies the vehicle generation and body variant. 1 to 100 characters. |
| `vehicle.catalogue.drivetrain_id` | string | Drivetrain UUID returned for the selected generation. Identifies the engine and transmission variant and improves identity precision. 1 to 100 characters. |
| `vehicle.catalogue.equipment_variant_id` | string | Equipment or trim variant UUID returned for the make. It must belong to the same make as the other catalogue IDs. 1 to 100 characters. |
| `vehicle.model_year` | integer | Known registration or model year as a four-digit integer. first_registration takes precedence when both are supplied. 1900 to 2100. |
| `vehicle.first_registration` | string (date) | First registration date in YYYY-MM-DD format. The current valuation payload uses its year; do not derive a registration date from a photograph. At most 10 characters. |
| `vehicle.mileage` | object | Odometer value with an explicit unit. Values are converted to the requested market convention before scoring. |
| `vehicle.mileage.value` **required** | number | Non-negative odometer reading in the accompanying unit. Do not convert it twice when changing the unit. 0 to 10000000. |
| `vehicle.mileage.unit` **required** | string | Odometer unit: km means kilometres, mi means miles, and mil means Scandinavian miles of ten kilometres. One of `km`, `mi`, `mil`. |
| `vehicle.transmission` | string | Known transmission type, automatic or manual. Omit it when unknown; an omitted gearbox is not treated as manual. One of `manual`, `automatic`. |
| `vehicle.drive` | string | Driven wheels: fwd, rwd, awd or 4wd, or 2wd when only two-wheel drive is known (the value catalogue drivetrains return for most cars). Use the value supported by the vehicle specification. One of `fwd`, `rwd`, `2wd`, `awd`, `4wd`. |
| `vehicle.power_hp` | number | Engine or drivetrain power in horsepower. Convert a source value in kilowatts before submitting it here. 0 to 3000. |
| `vehicle.engine_size_l` | number | Combustion engine displacement in litres, such as 1.5. Omit for a fully electric vehicle. 0 to 30. |
| `vehicle.battery_kwh` | number | Known traction battery capacity in kilowatt-hours. Omit when the source does not report a capacity. 0 to 500. |
| `vehicle.electric_range_km` | number | Known electric driving range in kilometres, regardless of the odometer unit or valuation market. 0 to 3000. |
| `vehicle.doors` | integer | Number of doors reported by the vehicle specification. Helps distinguish otherwise similar body variants. 1 to 10. |
| `vehicle.seats` | integer | Number of seats reported by the vehicle specification. 1 to 20. |
| `vehicle.condition` | number | Known numeric vehicle condition grade from 0 through 4. Omit unknown condition rather than inventing a grade. 0 to 4. |
| `vehicle.drive_side` | string | Steering wheel position: left for left-hand drive and right for right-hand drive. This is not the side of the road used by traffic. One of `left`, `right`. |
| `vehicle.flags` | object | Boolean risk and eligibility attributes. Only the documented keys have an effect: when one is true, the vehicle is outside the market's model and the valuation is refused with unsupported_vehicle (some keys only in the markets they name). false has the same effect as leaving the key out. Any other key is ignored with a flags_not_recognized warning, and a market-specific key sent for another market is ignored with a flags_not_applicable warning. At most 30 entries. |
| `vehicle.flags.is_damaged` | boolean | The vehicle is damaged. When true the vehicle is refused with unsupported_vehicle in every market. |
| `vehicle.flags.has_new_engine` | boolean | The engine has been replaced. When true the vehicle is refused with unsupported_vehicle in every market. |
| `vehicle.flags.is_leasing_price` | boolean | The price is a leasing price, not a sale price. When true the vehicle is refused with unsupported_vehicle in every market. |
| `vehicle.flags.has_no_battery` | boolean | An electric vehicle sold without its traction battery, for example under battery rental. When true the vehicle is refused with unsupported_vehicle in every market. |
| `vehicle.flags.is_auction_car` | boolean | The vehicle is sold at auction. When true the vehicle is refused with unsupported_vehicle in every market. |
| `vehicle.flags.is_commercial_car` | boolean | The vehicle is registered or sold as a commercial vehicle. When true the vehicle is refused with unsupported_vehicle in every market. |
| `vehicle.flags.price_is_leasing_rate` | boolean | The price is a periodic leasing rate, not a sale price. When true the vehicle is refused with unsupported_vehicle in every market. |
| `vehicle.flags.has_no_tax` | boolean | The price excludes registration tax. Applies in DK, SE, DE, ES, AT and PT, where true is refused with unsupported_vehicle. |
| `vehicle.flags.has_yellow_plates` | boolean | Registered on Danish yellow (commercial) plates. Applies in DK only, where true is refused with unsupported_vehicle. |
| `vehicle.flags.is_camper_version` | boolean | A camper conversion. Applies in DK only, where true is refused with unsupported_vehicle. |
| `vehicle.equipment` | array | Known equipment as feature keys from /v1/catalogue/enums, such as `EXTERIOR_TOWBAR_FIXED` or `INFOTAINMENT_NAVIGATION`, as strings or as the items of a returned Vehicle. The earlier keys such as `has_tow_bar` are still accepted. Unrecognized keys produce a warning. At most 150 items. |
| `vehicle.vin` | string | Optional vehicle identification number; the same as `registration.vin`. Live keys look it up: in DK in the Danish Motor Register, elsewhere with VIN decoding (make, model and model year). Never looked up in DE, IT or ES, or with test keys. Looked-up values only fill attributes you leave out and are identified against the catalogue like your own; their provenance in `identification.fields` has source registry and a source_id. A value that disagrees with one you supplied gives a registry_conflict warning while yours is used. If the lookup cannot be used, your other attributes are used and a warning says why. Included in the request's credit. The raw VIN is not retained. At most 30 characters. |
| `vehicle.registration_plate` | string | Optional registration plate; the same as `registration.registration_plate`. Live keys look it up in the national register where one is connected (DK, the Danish Motor Register); elsewhere it gives a registry_lookup_not_available warning, and a vin sent with it is still decoded. Looked-up values only fill attributes you leave out, as for vin. The odometer reading of the last inspection is never used as the mileage. Included in the request's credit. The raw plate is not retained. At most 30 characters. |
| `vehicle.identity` | object | Canonical identity: a catalogue ID per level, or a brand and model name. Canonical form of `make`, `model`, `variant` and `catalogue`. |
| `vehicle.identity.level` | string | Read-only part of a returned Vehicle. Accepted and ignored. |
| `vehicle.identity.<level>` | object | An identity level: `brand`, `model`, `generation`, `drivetrain` or `equipment_variant`. Send an `id`, or a `name` for `brand` and `model`. |
| `vehicle.identity.<level>.id` | string or null | Catalogue ID from the catalogue API or a returned Vehicle. Wins over `name`. All IDs must describe one consistent catalogue hierarchy. |
| `vehicle.identity.<level>.name` | string | Name as your source spells it. Used for `brand` and `model` when there is no `id`; ignored at the other levels. At most 200 characters. |
| `vehicle.identity.<level>.from_year` | integer | Read-only part of a returned generation. Ignored. |
| `vehicle.identity.<level>.to_year` | integer | Read-only part of a returned generation. Ignored. |
| `vehicle.identity.variant_text` | string | Free-text engine, trim or version designation; the same as `variant`. At most 200 characters. |
| `vehicle.specs` | object | Canonical technical facts: `energy.fuel` for `fuel`, `power.hp` or `power.kw` for `power_hp`, `transmission.type` for `transmission`, `traction` for `drive`, and `body`, `doors`, `seats`, `engine_size_l`, `battery_kwh` and `electric_range_km` as named. |
| `vehicle.specs.body` | string | Body type. One of `hatchback`, `estate`, `suv`, `sedan`, `mpv`, `convertible`, `coupe`. |
| `vehicle.specs.doors` | integer | Number of doors. 1 to 10. |
| `vehicle.specs.seats` | integer | Number of seats. 1 to 20. |
| `vehicle.specs.energy` | object | Energy source. |
| `vehicle.specs.energy.fuel` | string | Fuel or electrification type, from the public vocabulary of /v1/catalogue/enums. One of `petrol`, `diesel`, `electric`, `hybrid`, `plug_in_hybrid_petrol`, `plug_in_hybrid_diesel`, `lpg`, `cng`, `ethanol`, `hydrogen`. |
| `vehicle.specs.power` | object | Engine or drivetrain power. Returned in both units; on input `hp` wins over `kw`. |
| `vehicle.specs.power.hp` | number | Power in horsepower. 0 to 3000. |
| `vehicle.specs.power.kw` | number | Power in kilowatts, rounded. On input it is converted to horsepower (1 kW = 1.35962 hp) when `hp` is absent. 0 to 2300. |
| `vehicle.specs.engine_size_l` | number | Combustion engine displacement in litres, such as 1.5. 0 to 30. |
| `vehicle.specs.transmission` | object | Gearbox. Absent when unknown; absent does not mean manual. |
| `vehicle.specs.transmission.type` | string | Gearbox type. One of `manual`, `automatic`. |
| `vehicle.specs.traction` | string | Driven wheels. `2wd` means two-wheel drive with the driven axle not recorded, which is what the catalogue knows for most cars. One of `fwd`, `rwd`, `2wd`, `awd`, `4wd`. |
| `vehicle.specs.battery_kwh` | number | Traction battery capacity in kilowatt-hours. 0 to 500. |
| `vehicle.specs.electric_range_km` | number | Electric driving range in kilometres. 0 to 3000. |
| `vehicle.registration` | object | Canonical registration facts and identifiers. A VIN, plate or HSN/TSN pair is looked up as described for `vin`. |
| `vehicle.registration.country` | string | Read-only part of a returned Vehicle. Ignored: the request's `country` is the market. At most 10 characters. |
| `vehicle.registration.first_registration` | string (date) | First registration date (YYYY-MM-DD); the same as `first_registration`. At most 10 characters. |
| `vehicle.registration.model_year` | integer | Model or registration year; the same as `model_year`. 1900 to 2100. |
| `vehicle.registration.vin` | string | Vehicle identification number; the same as `vin`. At most 30 characters. |
| `vehicle.registration.registration_plate` | string | Registration plate; the same as `registration_plate`. At most 30 characters. |
| `vehicle.registration.hsn` | string | German manufacturer code (HSN, field 2.1 of the registration document). Looked up with `tsn` in the Kraftfahrt-Bundesamt type snapshot. At most 8 characters. |
| `vehicle.registration.tsn` | string | The first three characters of the German type code (TSN, field 2.2). Looked up with `hsn`. At most 8 characters. |
| `vehicle.registration.original_market` | string | The car's original sales market (ISO 3166-1 alpha-2), only when you know it independently. Used when a VIN is decoded. At most 10 characters. |
| `vehicle.registration.production_year` | integer | Read-only part of a returned Vehicle. Ignored. |
| `vehicle.listing` | object | Canonical facts about this particular car: `mileage`, `colour.name` for `color`, `condition.grade` for `condition`, `drive_side` and `flags`. |
| `vehicle.listing.mileage` | object | Odometer reading; the same as `mileage`. |
| `vehicle.listing.mileage.value` **required** | number | Non-negative odometer reading in the accompanying unit. 0 to 10000000. |
| `vehicle.listing.mileage.unit` **required** | string | Odometer unit: km, mi or mil (Scandinavian mile, 10 km). One of `km`, `mi`, `mil`. |
| `vehicle.listing.mileage.read_on` | string (date) | Read-only date of a register's reading. Ignored. A register's past inspection reading is not today's mileage: replace it before you value the car. |
| `vehicle.listing.colour` | object | Exterior colour. |
| `vehicle.listing.colour.name` **required** | string | Colour from your source; the same as `color`. At most 200 characters. |
| `vehicle.listing.colour.family` | string | Read-only part of a returned Vehicle. Accepted and ignored. At most 100 characters. |
| `vehicle.listing.condition` | object | Condition. |
| `vehicle.listing.condition.grade` **required** | number | Condition grade from 0 through 4; the same as `condition`. 0 to 4. |
| `vehicle.listing.drive_side` | string | Steering wheel position; the same as `drive_side`. One of `left`, `right`. |
| `vehicle.listing.flags` | object | Boolean risk and eligibility attributes; the same keys and effect as `flags`. At most 30 entries. |
| `vehicle.object` | string | Read-only part of a returned Vehicle. Accepted and ignored. |
| `vehicle.status` | string | Read-only part of a returned Vehicle. Accepted and ignored. |
| `vehicle.catalogue_version` | string | Read-only part of a returned Vehicle. Accepted and ignored. |
| `vehicle.fields` | object | Read-only part of a returned Vehicle. Accepted and ignored. |
| `vehicle.candidates` | object | Read-only part of a returned Vehicle. Accepted and ignored. |
| `description` | string | Unstructured listing text describing the vehicle. Existing parsers and deployment-configured optional AI can propose attributes; the response identifies assumptions and unresolved inputs. 1 to 20000 characters. |
| `images` | array | Up to eight vehicle photos, each supplied by HTTPS URL or inline base64 data. AI image resolution is deployment-configured and never runs for test keys. Warnings identify unused images. On a live key, photos cost one extra credit per request (not per photo), charged only when the request succeeds and a value was read from them (`usage.charges.images`); skipped or unused photos are not charged. At most 8 items. |
| `images[].url` | string (uri) | Public HTTPS image URL on port 443, without credentials or fragments. Private network destinations and redirects are rejected. Remote images must be supported image types and at most 8 MB each. At most 2048 characters. |
| `images[].data` | string | Strict base64-encoded image bytes, without a data-URL prefix. Inline data must also fit the total 1 MB API request limit. At most 1000000 characters. |
| `images[].media_type` | string | MIME type for inline image bytes: image/jpeg, image/png, image/webp or image/gif. The actual image signature is checked. At most 100 characters. |
| `pricing` | object | The asking-price context for this valuation. The result explicitly states its currency and whether the expected asking price is dealer retail or private sale. |
| `pricing.price_basis` | string | dealer_retail estimates a freshly listed dealer asking price; private_sale estimates a private seller asking price. These are not guaranteed transaction or trade-in prices. One of `dealer_retail`, `private_sale`. |
| `pricing.seller_region` | string | Known seller region within the selected market. This is passed as regional pricing context when available. At most 120 characters. |
| `pricing.asking_price` | number | Optional asking price in the market currency. Used to calculate AutoUncle price ratings and rating stability across the uncertainty interval. 0 to 100000000. |
| `options` | object | Resolution and minimum precision controls. Missing optional values use the documented default behaviour. |
| `options.resolution` | string | auto uses deterministic resolution and optional configured AI; no_ai uses deterministic resolution only; strict disables AI and refuses missing registration year or mileage. Mileage is never assumed without allow_mileage_estimation=true, and strict mode overrides that permission. Configured live AI is invoked only for missing identity/year or core drivetrain attributes, catalogue candidates the deterministic matcher cannot separate, equipment or condition the request does not supply, and whenever images are sent (for the equipment, colour, condition and drive side they show). An image that cannot be read is skipped with an image_skipped warning. Once invoked, a dependency timeout or outage fails the valuation; it is never silently treated as successful enrichment. One of `auto`, `no_ai`, `strict`. |
| `options.min_precision` | string | Minimum acceptable precision grade. If the result falls below this grade, the request is refused without consuming a credit. Sandbox results are indicative. One of `high`, `medium`, `low`, `indicative`. |
| `options.include` | array | Optional response sections to add. A section never changes the price, intervals or precision. `comparables` adds up to five comparable listings on sale and five recently sold in the same market, with top-level facts only, as supporting evidence for the valuation (see `comparables` in the response). One extra credit on a live key, charged only when listings are returned (`comparables.status` `included`) and released otherwise. Unavailable in Denmark, where the response says so with a note instead. `trade_in_price` adds AutoUncle's estimate of a fair trade-in price with a range (see `trade_in_price` in the response). One extra credit on a live key, charged only when it is returned (`trade_in_price.status` `included`). Available in AT, CH, DE, DK, ES, FR, GB, IT, NL, PL, PT and SE; in other markets the response says so with a note and nothing is charged. `similar_cars_link` adds `similar_cars_url`, a link to similar cars for sale on the market's AutoUncle site. Free, in every market. At most 10 items. |
| `options.allow_mileage_estimation` | boolean | Explicitly allow a fixed 96,000 km baseline when mileage cannot be extracted or supplied. This is an assumption, not a vehicle-specific estimate; it lowers precision. Default false. Strict resolution still refuses missing mileage. Default `false`. |
| `options.allow_equipment_estimation` | boolean | Explicitly allow equipment the request does not state to be assumed: the catalogue's equipment for the identified trim when the catalogue lists it, otherwise the equipment at least 70% of comparable vehicles on the market have. Assumed equipment is only added, never against equipment the request, its description or its photos state or deny, and is marked source imputed, basis assumed in identification.fields (availability unknown in vehicle.equipment), with an equipment_assumed warning and an improve_precision hint. Like any assumption it lowers precision to low. Test keys use only the catalogue trim, never market data. Default false. Strict resolution ignores it. Default `false`. |

### POST /v1/valuations

Resolve and value a vehicle.

One credit per successful live valuation, plus one when requested comparable listings are returned, one when a requested trade-in price is returned and one when sent photos were used. Retry an unknown network outcome with the original Idempotency-Key and identical input. A confirmed recorded success, refusal or failure outcome is replayed; use a new key to execute a fresh attempt after a confirmed refusal or failure. Optional AI resolution is deployment-configured; warnings identify unused input. Sandbox never calls AI. Concurrent valuations are limited per workspace (429 concurrency_limited) and engine-wide or per market (503 engine_busy); these rejections happen before the request is started, carry Retry-After and retry_after, consume no credit and may be retried with the same Idempotency-Key.

- **Scope:** `valuations:write`
- **Cost:** One credit for a successful (`valued`) live valuation, plus one when requested comparables are returned, one when a requested trade-in price is returned and one when sent photos were used. The similar-cars link is free. Test-key valuations, refusals and failures are free.
- **Rate limit:** valuations bucket, default 60 requests per minute. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | string | No | Workspace- and mode-scoped retry key. Unknown network outcome: retry the same key. Confirmed recorded refusal/failure: new key for a fresh attempt. 1 to 200 characters. |

#### Request body

`application/json`, at most 1 MB. A [ValuationRequest](https://data-services.autouncle.com/docs/concepts/vehicle#valuation-request-fields): `country` plus at least one of `vehicle`, `description` or `images`. Unknown fields are rejected.

Structured example:

```json
{
  "country": "DK",
  "vehicle": {
    "make": "Volkswagen",
    "model": "Golf",
    "model_year": 2020,
    "mileage": {
      "value": 65000,
      "unit": "km"
    },
    "fuel": "petrol",
    "transmission": "automatic"
  }
}
```

Text example:

```json
{
  "country": "DK",
  "description": "Volkswagen Golf 1.5 TSI DSG, registered 2020, 65000 km"
}
```

Comparables example:

```json
{
  "country": "SE",
  "vehicle": {
    "make": "Volvo",
    "model": "XC60",
    "model_year": 2021,
    "mileage": {
      "value": 6500,
      "unit": "mil"
    },
    "fuel": "plug_in_hybrid_petrol",
    "transmission": "automatic"
  },
  "options": {
    "include": [
      "comparables"
    ]
  }
}
```

Trade in example:

```json
{
  "country": "DE",
  "vehicle": {
    "make": "Volkswagen",
    "model": "Golf",
    "model_year": 2021,
    "mileage": {
      "value": 48000,
      "unit": "km"
    },
    "fuel": "petrol",
    "transmission": "manual"
  },
  "options": {
    "include": [
      "trade_in_price",
      "similar_cars_link"
    ]
  }
}
```

#### Response

`application/json`: a [valuation result](https://data-services.autouncle.com/docs/reference/valuations#the-valuation-result). Refused and failed valuations return the same envelope with `status` and a nested `error`, using the error's HTTP status. Errors before a valuation is recorded return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |
| `X-Valuation-Id` | The recorded valuation's ID (`val_…`, or `stf_…` for a selling-time forecast), the same value as the body's `request_id`. Present whenever the response is a valuation result, including refused and failed outcomes and idempotent replays. Use it with GET /v1/valuations/{id}, the console and support. |
| `Retry-After` | Seconds to wait before retrying. Present on capacity and rate-limit rejections. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`invalid_request`](https://data-services.autouncle.com/docs/errors#invalid_request) | 400 | No | Send a request matching the documented schema. |
| [`country_required`](https://data-services.autouncle.com/docs/errors#country_required) | 400 | No | Include country, the valuation market, in the request. |
| [`unsupported_country`](https://data-services.autouncle.com/docs/errors#unsupported_country) | 400 | No | Choose a supported ISO country code. |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_credits`](https://data-services.autouncle.com/docs/errors#insufficient_credits) | 402 | No | The organization has no credits available. Contact sales for a package. |
| [`key_spend_limit_reached`](https://data-services.autouncle.com/docs/errors#key_spend_limit_reached) | 402 | No | This API key has reached its monthly credit limit. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`country_not_enabled`](https://data-services.autouncle.com/docs/errors#country_not_enabled) | 403 | No | This country is not enabled for this organization or key. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`unknown_catalogue_id`](https://data-services.autouncle.com/docs/errors#unknown_catalogue_id) | 404 | No | The catalogue ID is unknown. Fetch current IDs from the catalogue API. |
| [`idempotency_conflict`](https://data-services.autouncle.com/docs/errors#idempotency_conflict) | 409 | No | This idempotency key was used with different input. Choose a new key. |
| [`request_in_progress`](https://data-services.autouncle.com/docs/errors#request_in_progress) | 409 | Yes | A request with this idempotency key is still running. Retry later with the same key. |
| [`payload_too_large`](https://data-services.autouncle.com/docs/errors#payload_too_large) | 413 | No | The request exceeds the maximum supported size of 1 MB. |
| [`missing_mileage`](https://data-services.autouncle.com/docs/errors#missing_mileage) | 422 | No | Supply the actual mileage in vehicle.mileage, or explicitly set options.allow_mileage_estimation to true to use a fixed 96,000 km baseline assumption. |
| [`vehicle_not_identified`](https://data-services.autouncle.com/docs/errors#vehicle_not_identified) | 422 | No | Provide more vehicle attributes or select catalogue IDs. |
| [`catalogue_id_conflict`](https://data-services.autouncle.com/docs/errors#catalogue_id_conflict) | 422 | No | The catalogue IDs do not describe the same vehicle hierarchy. |
| [`vehicle_out_of_range`](https://data-services.autouncle.com/docs/errors#vehicle_out_of_range) | 422 | No | The vehicle is outside the supported valuation range. |
| [`unsupported_vehicle`](https://data-services.autouncle.com/docs/errors#unsupported_vehicle) | 422 | No | This type of vehicle is not supported. |
| [`precision_below_minimum`](https://data-services.autouncle.com/docs/errors#precision_below_minimum) | 422 | No | Provide more attributes or lower the requested minimum precision. |
| [`images_unreadable`](https://data-services.autouncle.com/docs/errors#images_unreadable) | 422 | No | Provide readable supported images. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |
| [`test_limit_reached`](https://data-services.autouncle.com/docs/errors#test_limit_reached) | 429 | Yes | This workspace has used its fair-use allowance of test-key requests for now. |
| [`concurrency_limited`](https://data-services.autouncle.com/docs/errors#concurrency_limited) | 429 | Yes | Too many valuations are running at the same time for this organization. |
| [`rate_limit_unavailable`](https://data-services.autouncle.com/docs/errors#rate_limit_unavailable) | 503 | Yes | Request limiting is temporarily unavailable. Retry later. |
| [`engine_busy`](https://data-services.autouncle.com/docs/errors#engine_busy) | 503 | Yes | The valuation engine is at capacity. Retry after a short delay. |
| [`engine_unavailable`](https://data-services.autouncle.com/docs/errors#engine_unavailable) | 503 | Yes | The valuation engine is temporarily unavailable. After a confirmed failed response, use a new idempotency key for a fresh attempt. |
| [`engine_misconfigured`](https://data-services.autouncle.com/docs/errors#engine_misconfigured) | 503 | No | The valuation service for this market is not configured correctly. |
| [`engine_timeout`](https://data-services.autouncle.com/docs/errors#engine_timeout) | 504 | Yes | The valuation service did not respond within its time budget. |
| [`engine_invalid_response`](https://data-services.autouncle.com/docs/errors#engine_invalid_response) | 502 | Yes | The valuation service returned an invalid response. |
| [`request_timeout`](https://data-services.autouncle.com/docs/errors#request_timeout) | 504 | Yes | The valuation request exhausted its processing time budget. |
| [`resolution_timeout`](https://data-services.autouncle.com/docs/errors#resolution_timeout) | 504 | Yes | Vehicle interpretation did not finish within its time budget. |
| [`resolution_unavailable`](https://data-services.autouncle.com/docs/errors#resolution_unavailable) | 503 | Yes | Vehicle interpretation is temporarily unavailable. |
| [`resolution_invalid_response`](https://data-services.autouncle.com/docs/errors#resolution_invalid_response) | 502 | Yes | Vehicle interpretation returned an invalid response. |
| [`image_timeout`](https://data-services.autouncle.com/docs/errors#image_timeout) | 504 | Yes | Image retrieval did not finish within its time budget. |
| [`image_unavailable`](https://data-services.autouncle.com/docs/errors#image_unavailable) | 503 | Yes | The image service is temporarily unavailable. |
| [`image_invalid_response`](https://data-services.autouncle.com/docs/errors#image_invalid_response) | 502 | Yes | The image service returned an invalid response. |
| [`internal_error`](https://data-services.autouncle.com/docs/errors#internal_error) | 500 | No | The valuation could not be completed. Contact support with the request ID. |

### GET /v1/valuations/{id}

Retrieve your workspace’s recorded valuation.

Returns the result exactly as it was recorded, including its notes and attributions, but without the `usage` block. A test key reads only test-mode results and a live key only live results.

- **Scope:** `valuations:read`
- **Cost:** Free. Counts towards the per-minute valuation rate limit.
- **Rate limit:** valuations bucket, default 60 requests per minute. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Identifier from a previous response. At most 200 characters. |

#### Response

`application/json`: a [valuation result](https://data-services.autouncle.com/docs/reference/valuations#the-valuation-result). Refused and failed valuations return the same envelope with `status` and a nested `error`, using the error's HTTP status. Errors before a valuation is recorded return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |
| `X-Valuation-Id` | The recorded valuation's ID (`val_…`, or `stf_…` for a selling-time forecast), the same value as the body's `request_id`. Present whenever the response is a valuation result, including refused and failed outcomes and idempotent replays. Use it with GET /v1/valuations/{id}, the console and support. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`country_not_enabled`](https://data-services.autouncle.com/docs/errors#country_not_enabled) | 403 | No | This country is not enabled for this organization or key. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`not_found`](https://data-services.autouncle.com/docs/errors#not_found) | 404 | No | The requested resource was not found. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |

### POST /v1/selling-times

Value a vehicle and forecast its selling time.

Values the vehicle exactly as POST /v1/valuations does and adds selling_time: the expected days to sell, and the chance of selling within 30, 60 and 90 days, for an asking price in the middle of each price-rating band and at pricing.asking_price when it is sent. Available in every Data Services market; a country Data Services does not serve to every workspace (such as BE, on request) is refused with selling_time_unsupported_market, and a market whose forecast model is temporarily missing fails with selling_time_unavailable; neither is charged. Two credits per successful live forecast, one for the valuation (usage.charges.base) and one for the forecast (usage.charges.selling_time), plus any requested add-on such as comparables or a trade-in price; when the forecast cannot be made the request fails (selling_time_unavailable or selling_time_timeout) and nothing is charged. Test keys return fixed synthetic forecasts for free. Idempotency, admission limits and replays work as for valuations, and the result is read back with GET /v1/valuations/{id}.

Available in every Data Services market; only a country Data Services does not serve to every workspace, such as Belgium, is refused with `selling_time_unsupported_market`. When a market's forecast model is temporarily missing, the request fails with `selling_time_unavailable` (503) and nothing is charged. The response is a valuation with `selling_time` added, and the same valuation ID reads it back with GET /v1/valuations/{id}. A credit grant must hold both credits. Counts against the valuation rate limit and needs a valuation concurrency slot, like POST /v1/valuations.

- **Scope:** `valuations:write`
- **Cost:** Two credits for a successful (`valued`) live forecast: one for the valuation and one for the forecast, plus one when requested comparables are returned. Test keys, refusals and failures, including a forecast that could not be made, are free.
- **Rate limit:** valuations bucket, default 60 requests per minute. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | string | No | Workspace- and mode-scoped retry key. Unknown network outcome: retry the same key. Confirmed recorded refusal/failure: new key for a fresh attempt. 1 to 200 characters. |

#### Request body

`application/json`, at most 1 MB. A [ValuationRequest](https://data-services.autouncle.com/docs/concepts/vehicle#valuation-request-fields): `country` plus at least one of `vehicle`, `description` or `images`. Unknown fields are rejected.

Structured example:

```json
{
  "country": "SE",
  "vehicle": {
    "make": "Volvo",
    "model": "XC60",
    "model_year": 2019,
    "mileage": {
      "value": 9000,
      "unit": "mil"
    },
    "fuel": "diesel",
    "transmission": "automatic"
  },
  "pricing": {
    "asking_price": 289000
  }
}
```

#### Response

`application/json`: a [valuation result](https://data-services.autouncle.com/docs/reference/valuations#the-valuation-result). Refused and failed valuations return the same envelope with `status` and a nested `error`, using the error's HTTP status. Errors before a valuation is recorded return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |
| `X-Valuation-Id` | The recorded valuation's ID (`val_…`, or `stf_…` for a selling-time forecast), the same value as the body's `request_id`. Present whenever the response is a valuation result, including refused and failed outcomes and idempotent replays. Use it with GET /v1/valuations/{id}, the console and support. |
| `Retry-After` | Seconds to wait before retrying. Present on capacity and rate-limit rejections. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`invalid_request`](https://data-services.autouncle.com/docs/errors#invalid_request) | 400 | No | Send a request matching the documented schema. |
| [`country_required`](https://data-services.autouncle.com/docs/errors#country_required) | 400 | No | Include country, the valuation market, in the request. |
| [`unsupported_country`](https://data-services.autouncle.com/docs/errors#unsupported_country) | 400 | No | Choose a supported ISO country code. |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_credits`](https://data-services.autouncle.com/docs/errors#insufficient_credits) | 402 | No | The organization has no credits available. Contact sales for a package. |
| [`key_spend_limit_reached`](https://data-services.autouncle.com/docs/errors#key_spend_limit_reached) | 402 | No | This API key has reached its monthly credit limit. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`country_not_enabled`](https://data-services.autouncle.com/docs/errors#country_not_enabled) | 403 | No | This country is not enabled for this organization or key. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`unknown_catalogue_id`](https://data-services.autouncle.com/docs/errors#unknown_catalogue_id) | 404 | No | The catalogue ID is unknown. Fetch current IDs from the catalogue API. |
| [`idempotency_conflict`](https://data-services.autouncle.com/docs/errors#idempotency_conflict) | 409 | No | This idempotency key was used with different input. Choose a new key. |
| [`request_in_progress`](https://data-services.autouncle.com/docs/errors#request_in_progress) | 409 | Yes | A request with this idempotency key is still running. Retry later with the same key. |
| [`payload_too_large`](https://data-services.autouncle.com/docs/errors#payload_too_large) | 413 | No | The request exceeds the maximum supported size of 1 MB. |
| [`missing_mileage`](https://data-services.autouncle.com/docs/errors#missing_mileage) | 422 | No | Supply the actual mileage in vehicle.mileage, or explicitly set options.allow_mileage_estimation to true to use a fixed 96,000 km baseline assumption. |
| [`vehicle_not_identified`](https://data-services.autouncle.com/docs/errors#vehicle_not_identified) | 422 | No | Provide more vehicle attributes or select catalogue IDs. |
| [`catalogue_id_conflict`](https://data-services.autouncle.com/docs/errors#catalogue_id_conflict) | 422 | No | The catalogue IDs do not describe the same vehicle hierarchy. |
| [`vehicle_out_of_range`](https://data-services.autouncle.com/docs/errors#vehicle_out_of_range) | 422 | No | The vehicle is outside the supported valuation range. |
| [`unsupported_vehicle`](https://data-services.autouncle.com/docs/errors#unsupported_vehicle) | 422 | No | This type of vehicle is not supported. |
| [`precision_below_minimum`](https://data-services.autouncle.com/docs/errors#precision_below_minimum) | 422 | No | Provide more attributes or lower the requested minimum precision. |
| [`images_unreadable`](https://data-services.autouncle.com/docs/errors#images_unreadable) | 422 | No | Provide readable supported images. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |
| [`test_limit_reached`](https://data-services.autouncle.com/docs/errors#test_limit_reached) | 429 | Yes | This workspace has used its fair-use allowance of test-key requests for now. |
| [`concurrency_limited`](https://data-services.autouncle.com/docs/errors#concurrency_limited) | 429 | Yes | Too many valuations are running at the same time for this organization. |
| [`rate_limit_unavailable`](https://data-services.autouncle.com/docs/errors#rate_limit_unavailable) | 503 | Yes | Request limiting is temporarily unavailable. Retry later. |
| [`selling_time_unsupported_market`](https://data-services.autouncle.com/docs/errors#selling_time_unsupported_market) | 422 | No | Selling-time forecasts are not available for this market. |
| [`selling_time_unavailable`](https://data-services.autouncle.com/docs/errors#selling_time_unavailable) | 503 | Yes | The selling-time forecast is temporarily unavailable. |
| [`selling_time_timeout`](https://data-services.autouncle.com/docs/errors#selling_time_timeout) | 504 | Yes | The selling-time forecast did not finish within its time budget. |
| [`engine_busy`](https://data-services.autouncle.com/docs/errors#engine_busy) | 503 | Yes | The valuation engine is at capacity. Retry after a short delay. |
| [`engine_unavailable`](https://data-services.autouncle.com/docs/errors#engine_unavailable) | 503 | Yes | The valuation engine is temporarily unavailable. After a confirmed failed response, use a new idempotency key for a fresh attempt. |
| [`engine_misconfigured`](https://data-services.autouncle.com/docs/errors#engine_misconfigured) | 503 | No | The valuation service for this market is not configured correctly. |
| [`engine_timeout`](https://data-services.autouncle.com/docs/errors#engine_timeout) | 504 | Yes | The valuation service did not respond within its time budget. |
| [`engine_invalid_response`](https://data-services.autouncle.com/docs/errors#engine_invalid_response) | 502 | Yes | The valuation service returned an invalid response. |
| [`request_timeout`](https://data-services.autouncle.com/docs/errors#request_timeout) | 504 | Yes | The valuation request exhausted its processing time budget. |
| [`resolution_timeout`](https://data-services.autouncle.com/docs/errors#resolution_timeout) | 504 | Yes | Vehicle interpretation did not finish within its time budget. |
| [`resolution_unavailable`](https://data-services.autouncle.com/docs/errors#resolution_unavailable) | 503 | Yes | Vehicle interpretation is temporarily unavailable. |
| [`resolution_invalid_response`](https://data-services.autouncle.com/docs/errors#resolution_invalid_response) | 502 | Yes | Vehicle interpretation returned an invalid response. |
| [`image_timeout`](https://data-services.autouncle.com/docs/errors#image_timeout) | 504 | Yes | Image retrieval did not finish within its time budget. |
| [`image_unavailable`](https://data-services.autouncle.com/docs/errors#image_unavailable) | 503 | Yes | The image service is temporarily unavailable. |
| [`image_invalid_response`](https://data-services.autouncle.com/docs/errors#image_invalid_response) | 502 | Yes | The image service returned an invalid response. |
| [`internal_error`](https://data-services.autouncle.com/docs/errors#internal_error) | 500 | No | The valuation could not be completed. Contact support with the request ID. |

### POST /v1/market

Market and demand figures for a car type.

Describes the market for a car type in one country: how many are on sale and at what prices and mileages, the price-rating mix, how fast listings arrive and leave the market, how long they take to leave, days of supply and a demand level relative to the whole market, and a 12-month trend of listings leaving the market. Send the same vehicle input as a valuation; at least a make and model must be recognised, and model year, mileage, fuel, gearbox and body narrow the segment exactly as the valuation's similar_cars_url does. Every figure is an aggregate over the listings AutoUncle tracks in that market (not registrations or confirmed sales); left the market means removed from sale. A figure built from fewer than 10 listings is withheld and listed in suppressed. One credit for a measured live result; partial and insufficient_data results, refusals, failures, idempotent replays and test keys are free. Needs the valuations:write scope and shares the valuation rate and concurrency limits. Nothing is stored: a replay with the same Idempotency-Key reads the market again without spending a credit.

Nothing is stored: a replay with the same Idempotency-Key reads the market again without spending a credit, and there is no read-back endpoint. Counts against the valuation rate limit and needs a valuation concurrency slot, like POST /v1/valuations.

- **Scope:** `valuations:write`
- **Cost:** One credit for a `measured` live result. `partial` and `insufficient_data` results, test keys, refusals, failures and idempotent replays are free.
- **Rate limit:** valuations bucket, default 60 requests per minute. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | string | No | Workspace- and mode-scoped retry key. A replay of a finished request spends no credit. 1 to 200 characters. |

#### Request body

`application/json`, a `MarketRequest`: A car type in one market: the same vehicle input as a valuation (a VehicleInput, a description or photos), of which at least a make and model must be recognised. Mileage and model year are optional and only narrow the segment as the similar-cars link does. Pricing does not apply. Unknown fields are rejected.

| Field | Type | Description |
| --- | --- | --- |
| `country` **required** | string | Market as an ISO 3166-1 alpha-2 code, such as DK, DE or GB. Every figure comes from that market's own listings only. 2 to 10 characters. |
| `vehicle` | [VehicleInput](https://data-services.autouncle.com/docs/reference/vehicles#vehicleinput-describing-a-vehicle) | The vehicle, as a VehicleInput: an AVS vehicle document (any `vehicle` an endpoint returned, posted back unchanged) or the vehicle's attributes as a listing gives them. |
| `description` | string | Unstructured listing text describing the vehicle. Existing parsers and deployment-configured optional AI can propose attributes; the response identifies assumptions and unresolved inputs. 1 to 20000 characters. |
| `images` | array | Up to eight vehicle photos, each supplied by HTTPS URL or inline base64 data, to identify the car type. AI image resolution is deployment-configured and never runs for test keys. Photos cost nothing extra on a market request. At most 8 items. |
| `images[].url` | string (uri) | Public HTTPS image URL on port 443, without credentials or fragments. Private network destinations and redirects are rejected. Remote images must be supported image types and at most 8 MB each. At most 2048 characters. |
| `images[].data` | string | Strict base64-encoded image bytes, without a data-URL prefix. Inline data must also fit the total 1 MB API request limit. At most 1000000 characters. |
| `images[].media_type` | string | MIME type for inline image bytes: image/jpeg, image/png, image/webp or image/gif. The actual image signature is checked. At most 100 characters. |
| `options` | object | How the vehicle is resolved. |
| `options.resolution` | string | auto uses deterministic resolution and optional configured AI; no_ai and strict use deterministic resolution only. One of `auto`, `no_ai`, `strict`. |

Structured example:

```json
{
  "country": "SE",
  "vehicle": {
    "make": "Volvo",
    "model": "XC60",
    "model_year": 2019,
    "fuel": "diesel",
    "transmission": "automatic"
  }
}
```

Text example:

```json
{
  "country": "DE",
  "description": "VW Golf 1.5 TSI 2020"
}
```

#### Response

`application/json`, a `MarketResponse`: Market & demand figures for a car type in one market: aggregates over the listings AutoUncle tracks there, never a listing. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| Field | Type | Description |
| --- | --- | --- |
| `request_id` | string | The request's ID, shown in the console request log. Pattern `^mkt_[A-Za-z0-9]+$`. |
| `object` | string | Always `market`. One of `market`. |
| `status` | string | measured: figures were published; one credit on a live key. partial: a data store could not answer, so some figures are missing (see warnings); not charged. insufficient_data: every figure was withheld because too few listings match; not charged. One of `measured`, `partial`, `insufficient_data`. |
| `country` | string | Market as an ISO 3166-1 alpha-2 code, normalized from your request (for example `SE`). Pattern `^[A-Z]{2}$`. |
| `mode` | string | `test` for a test key (synthetic figures) or `live` for a live key. One of `live`, `test`. |
| `synthetic` | boolean | True for test keys: deterministic example figures, no market data. |
| `vehicle` | [Vehicle](https://data-services.autouncle.com/docs/reference/vehicles#the-vehicle-object) | The identified vehicle. An AVS vehicle document; left out when the vehicle could not be identified to a brand and a model, with the reason in `identification`. |
| `identification` | [VehicleIdentification](https://data-services.autouncle.com/docs/reference/vehicles#identification) | How the vehicle was identified: status, depth, candidates and the provenance of every value in `vehicle`. |
| `segment` | object | The listings the figures describe. |
| `segment.criteria` **required** | object | What a listing must match to be in the segment, in the public vocabulary. Null means not restricted. |
| `segment.criteria.make` **required** | string | Make every listing in the segment has. |
| `segment.criteria.model` **required** | string | Model every listing in the segment has. |
| `segment.criteria.model_year` **required** | object or null | Model years the segment covers. Null when not restricted. |
| `segment.criteria.model_year.from` **required** | integer or null | Earliest model year. |
| `segment.criteria.model_year.to` **required** | integer or null | Latest model year. |
| `segment.criteria.mileage` **required** | object or null | Mileage band the segment covers (Germany and Italy only, when you send a mileage). Null when not restricted. |
| `segment.criteria.mileage.from` **required** | integer or null | Lowest mileage. |
| `segment.criteria.mileage.to` **required** | integer or null | Highest mileage. |
| `segment.criteria.mileage.unit` **required** | string | `km`, `mi` or `mil` (Scandinavian mil). One of `km`, `mi`, `mil`. |
| `segment.criteria.fuel` **required** | string or null | Fuel every listing has. Null when not restricted. |
| `segment.criteria.transmission` **required** | string or null | `automatic` or `manual` when the gearbox is restricted, otherwise null. One of `automatic`, `manual`. |
| `segment.criteria.body` **required** | string or null | Body type every listing has. Null when not restricted. |
| `segment.criteria.engine_size_l` **required** | number or null | Engine size in litres every listing has. Null when not restricted. |
| `segment.similar_cars_url` **required** | string or null (uri) | The same segment as a search on the market's own AutoUncle site. |
| `as_of` | string (date-time) | When the figures were read. On-sale and left-the-market figures can be up to three hours old (shared cache). |
| `supply` | object or null | Listings on sale now. Null when those figures could not be read (market_supply_unavailable warning). |
| `supply.on_sale` **required** | integer or null | Listings on sale now in the segment. Null when fewer than 10, with on_sale_band set. Minimum 0. |
| `supply.on_sale_band` **required** | string or null | fewer_than_10 when the count is withheld; every other supply figure is then left out. One of `fewer_than_10`. |
| `supply.price` | object | Asking prices of the listings on sale. |
| `supply.price.p5` **required** | integer or null | 5th percentile asking price, rounded to three significant figures. Minimum 0. |
| `supply.price.median` **required** | integer or null | Median asking price, rounded to three significant figures. Minimum 0. |
| `supply.price.p95` **required** | integer or null | 95th percentile asking price, rounded to three significant figures. Minimum 0. |
| `supply.price.currency` **required** | string | ISO 4217 currency of the market. Pattern `^[A-Z]{3}$`. |
| `supply.mileage` | object | Mileage of the listings on sale, in the market's unit. |
| `supply.mileage.p5` **required** | integer or null | 5th percentile mileage, rounded to 1,000 km or mi (100 Scandinavian mil). Minimum 0. |
| `supply.mileage.median` **required** | integer or null | Median mileage, rounded the same way. Minimum 0. |
| `supply.mileage.p95` **required** | integer or null | 95th percentile mileage, rounded the same way. Minimum 0. |
| `supply.mileage.unit` **required** | string | `km`, `mi` or `mil` (Scandinavian mil): the market's unit. One of `km`, `mi`, `mil`. |
| `supply.model_years` | object or null | Model years of the listings on sale. Null when the store returned none. |
| `supply.model_years.most_common` **required** | integer or null | The most listed model year. Minimum 1900. |
| `supply.model_years.from` **required** | integer or null | Earliest model year of all but the outer 2% of listings. Minimum 1900. |
| `supply.model_years.to` **required** | integer or null | Latest model year of all but the outer 2% of listings. Minimum 1900. |
| `supply.price_ratings` | object | Share of listings on sale in each AutoUncle price rating (5 is super price, 1 is expensive), to two decimals. |
| `supply.price_ratings.5` **required** | number or null | Share of listings on sale with price rating 5. 0 to 1. |
| `supply.price_ratings.4` **required** | number or null | Share of listings on sale with price rating 4. 0 to 1. |
| `supply.price_ratings.3` **required** | number or null | Share of listings on sale with price rating 3. 0 to 1. |
| `supply.price_ratings.2` **required** | number or null | Share of listings on sale with price rating 2. 0 to 1. |
| `supply.price_ratings.1` **required** | number or null | Share of listings on sale with price rating 1. 0 to 1. |
| `supply.price_ratings.unrated` **required** | number or null | Share of listings on sale without a price rating. 0 to 1. |
| `supply.share_with_price_drop` | number or null | Share of listings on sale whose asking price has been lowered. 0 to 1. |
| `supply.top_equipment_variants` | array | The three most listed equipment-variant names, most listed first. At most 3 items. |
| `flow` | object or null | Pace over the last 30 days. Null when withheld (fewer than 10 listings left the market in the window) or unavailable. |
| `flow.window_days` **required** | integer | Days the per-day rates are averaged over. Always 30. |
| `flow.left_market_per_day` **required** | number or null | Listings that left the market per day over the window (on sale at least one day). Left the market means removed from sale, usually but not always a sale. Minimum 0. |
| `flow.new_listings_still_on_sale_per_day` **required** | number or null | Listings that went on sale within the window and are still on sale, per day. Listings that came and went within the window are not counted, so this is not total inflow. Minimum 0. |
| `turnover` | object or null | How long listings of this type take to leave the market. Null when withheld or unavailable. |
| `turnover.window_days` **required** | integer | Days back the listings that left the market are taken from. Always 60. |
| `turnover.median_days_to_leave` **required** | integer or null | Median days from going on sale to leaving the market, for listings that left in the window. Minimum 0. |
| `turnover.mean_days_to_leave` **required** | integer or null | Mean of the same. Minimum 0. |
| `demand` | object or null | Derived demand measures. Null when on_sale or flow is withheld or unavailable. |
| `demand.days_of_supply` **required** | integer or null | Listings on sale ÷ listings leaving the market per day: how long today's stock lasts at the current pace. Minimum 0. |
| `demand.turnovers_per_year` **required** | number or null | 12 × listings that left in 30 days ÷ listings on sale. Minimum 0. |
| `demand.relative_to_market` **required** | number or null | days_of_supply ÷ the same measure for the market's whole used-car stock. Below 1 the type moves faster than the market. Minimum 0. |
| `demand.level` **required** | string or null | high below 0.8 relative_to_market, low above 1.25, otherwise average. Null when the whole market's figures could not be read. One of `high`, `average`, `low`. |
| `trend` | object or null | The last 12 complete months of listings that left the market. Null when it could not be read (market_trend_unavailable warning). |
| `trend.months` **required** | integer | Complete calendar months in series: 12, or fewer where the store holds less history. 0 to 12. |
| `trend.currency` **required** | string | ISO 4217 currency of `median_last_asking_price`. Pattern `^[A-Z]{3}$`. |
| `trend.series` **required** | array | Oldest month first. At most 12 items. |
| `trend.series[].month` **required** | string | Calendar month as `YYYY-MM`. Pattern `^[0-9]{4}-[0-9]{2}$`. |
| `trend.series[].left_market` **required** | integer or null | Listings that left the market that month (on sale at least one day). Minimum 0. |
| `trend.series[].median_days_to_leave` **required** | integer or null | Median days from going on sale to leaving the market. Minimum 0. |
| `trend.series[].median_last_asking_price` **required** | integer or null | Median last asking price before leaving the market, rounded to three significant figures. Not a transaction price. Minimum 0. |
| `trend.series[].suppressed` **required** | boolean | True when fewer than 10 listings left the market that month; its figures are then null. |
| `trend.current_month` **required** | object | The month in progress, which is never in series. |
| `trend.current_month.month` **required** | string | The month in progress, as `YYYY-MM`. Pattern `^[0-9]{4}-[0-9]{2}$`. |
| `trend.current_month.partial` **required** | boolean | Always `true`: the month in progress is never in `series`. |
| `suppressed` | array | Every block or trend month withheld because it would be built from fewer than 10 listings. |
| `suppressed[].section` **required** | string | `supply`, `flow`, `turnover`, `demand` or `trend`. One of `supply`, `flow`, `turnover`, `demand`, `trend`. |
| `suppressed[].month` | string | For `trend`, the month withheld, as `YYYY-MM`. Pattern `^[0-9]{4}-[0-9]{2}$`. |
| `suppressed[].reason` **required** | string | Why it was withheld. Always `fewer_than_10_listings`. One of `fewer_than_10_listings`. |
| `warnings` | array | Problems with this request, for example `market_flow_unavailable` (status `partial`) or `model_not_recognized`. Match on `code`. |
| `warnings[].code` **required** | string | Stable machine-readable warning code. Pattern `^[a-z][a-z0-9_]*$`. |
| `warnings[].message` **required** | string | Plain-language explanation. |
| `usage` | object | Billing for this call. |
| `usage.billable` **required** | boolean | `true` when this result captured a credit (status `measured` on a live key). |
| `usage.credits_used` **required** | integer | Credits this call consumed. Always 0 on an idempotent replay. 0 to 1. |
| `usage.original_credits_used` **required** | integer | Credits the original request consumed (0 or 1), also on a replay. 0 to 1. |
| `usage.charges` **required** | object | What `original_credits_used` paid for. Empty when nothing was charged. |
| `usage.charges.base` | integer | The market figures, 1 credit. Minimum 1. |
| `usage.credits_remaining` **required** | integer | Workspace credits left after this call. Minimum 0. |
| `usage.cache_hit` **required** | boolean | Reserved. Always false in this version. |
| `usage.idempotent_replay` **required** | boolean | `true` when the same Idempotency-Key and body were sent before; the market is read again for free. |
| `usage.mode` **required** | string | `test` or `live`. One of `live`, `test`. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Standing limitations and notices, including `market_figures_describe_listings`. Always present. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | Data sources that contributed to this result. Always present. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |
| `Retry-After` | Seconds to wait before retrying. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`invalid_request`](https://data-services.autouncle.com/docs/errors#invalid_request) | 400 | No | Send a request matching the documented schema. |
| [`country_required`](https://data-services.autouncle.com/docs/errors#country_required) | 400 | No | Include country, the valuation market, in the request. |
| [`unsupported_country`](https://data-services.autouncle.com/docs/errors#unsupported_country) | 400 | No | Choose a supported ISO country code. |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_credits`](https://data-services.autouncle.com/docs/errors#insufficient_credits) | 402 | No | The organization has no credits available. Contact sales for a package. |
| [`key_spend_limit_reached`](https://data-services.autouncle.com/docs/errors#key_spend_limit_reached) | 402 | No | This API key has reached its monthly credit limit. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`country_not_enabled`](https://data-services.autouncle.com/docs/errors#country_not_enabled) | 403 | No | This country is not enabled for this organization or key. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`unknown_catalogue_id`](https://data-services.autouncle.com/docs/errors#unknown_catalogue_id) | 404 | No | The catalogue ID is unknown. Fetch current IDs from the catalogue API. |
| [`idempotency_conflict`](https://data-services.autouncle.com/docs/errors#idempotency_conflict) | 409 | No | This idempotency key was used with different input. Choose a new key. |
| [`request_in_progress`](https://data-services.autouncle.com/docs/errors#request_in_progress) | 409 | Yes | A request with this idempotency key is still running. Retry later with the same key. |
| [`payload_too_large`](https://data-services.autouncle.com/docs/errors#payload_too_large) | 413 | No | The request exceeds the maximum supported size of 1 MB. |
| [`vehicle_not_identified`](https://data-services.autouncle.com/docs/errors#vehicle_not_identified) | 422 | No | Provide more vehicle attributes or select catalogue IDs. |
| [`catalogue_id_conflict`](https://data-services.autouncle.com/docs/errors#catalogue_id_conflict) | 422 | No | The catalogue IDs do not describe the same vehicle hierarchy. |
| [`vehicle_out_of_range`](https://data-services.autouncle.com/docs/errors#vehicle_out_of_range) | 422 | No | The vehicle is outside the supported valuation range. |
| [`images_unreadable`](https://data-services.autouncle.com/docs/errors#images_unreadable) | 422 | No | Provide readable supported images. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |
| [`test_limit_reached`](https://data-services.autouncle.com/docs/errors#test_limit_reached) | 429 | Yes | This workspace has used its fair-use allowance of test-key requests for now. |
| [`concurrency_limited`](https://data-services.autouncle.com/docs/errors#concurrency_limited) | 429 | Yes | Too many valuations are running at the same time for this organization. |
| [`rate_limit_unavailable`](https://data-services.autouncle.com/docs/errors#rate_limit_unavailable) | 503 | Yes | Request limiting is temporarily unavailable. Retry later. |
| [`engine_busy`](https://data-services.autouncle.com/docs/errors#engine_busy) | 503 | Yes | The valuation engine is at capacity. Retry after a short delay. |
| [`request_timeout`](https://data-services.autouncle.com/docs/errors#request_timeout) | 504 | Yes | The valuation request exhausted its processing time budget. |
| [`resolution_timeout`](https://data-services.autouncle.com/docs/errors#resolution_timeout) | 504 | Yes | Vehicle interpretation did not finish within its time budget. |
| [`resolution_unavailable`](https://data-services.autouncle.com/docs/errors#resolution_unavailable) | 503 | Yes | Vehicle interpretation is temporarily unavailable. |
| [`resolution_invalid_response`](https://data-services.autouncle.com/docs/errors#resolution_invalid_response) | 502 | Yes | Vehicle interpretation returned an invalid response. |
| [`image_timeout`](https://data-services.autouncle.com/docs/errors#image_timeout) | 504 | Yes | Image retrieval did not finish within its time budget. |
| [`image_unavailable`](https://data-services.autouncle.com/docs/errors#image_unavailable) | 503 | Yes | The image service is temporarily unavailable. |
| [`image_invalid_response`](https://data-services.autouncle.com/docs/errors#image_invalid_response) | 502 | Yes | The image service returned an invalid response. |
| [`market_data_unavailable`](https://data-services.autouncle.com/docs/errors#market_data_unavailable) | 503 | Yes | Market figures are temporarily unavailable. |
| [`internal_error`](https://data-services.autouncle.com/docs/errors#internal_error) | 500 | No | The valuation could not be completed. Contact support with the request ID. |

### POST /v1/vehicles/normalize

Resolve a vehicle without valuing it.

Identifies a vehicle against the AutoUncle catalogue without valuing it. Send a VehicleInput (catalogue IDs, names, specs, identifiers, or a Vehicle another endpoint returned), a description or images, the same as a valuation accepts, and get back the Vehicle: catalogue identity, specs, equipment, registration and listing, with provenance per field. A VIN or plate in the vehicle is looked up as for a valuation. When several catalogue records fit, the ambiguous level is left out of identity and the records are returned as candidates. One credit per successful live normalization; refusals, failures, idempotent replays and test keys are free. Needs the vehicles:read scope and counts against the vehicle rate limit; it shares the valuation concurrency limits. Retry an unknown network outcome with the same Idempotency-Key: a replay identifies the same input again without spending a credit.

- **Scope:** `vehicles:read`
- **Cost:** One credit for a successful (`normalized`) live normalization, plus one when sent photos were used. Test keys, refusals, failures and idempotent replays are free.
- **Rate limit:** vehicles bucket, default 60 requests per minute, counted separately from valuations. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | string | No | Workspace- and mode-scoped retry key. A replay of a finished normalization spends no credit. 1 to 200 characters. |

#### Request body

`application/json`, a `NormalizationRequest`: A normalization request for one market. It accepts the same vehicle (a VehicleInput, including a Vehicle returned by any endpoint), description and images as a valuation request. Nothing is valued and no year or mileage is assumed. Unknown fields are rejected.

| Field | Type | Description |
| --- | --- | --- |
| `country` **required** | string | Market as an ISO 3166-1 alpha-2 code, such as DK, DE or GB. The market selects its own catalogue scope and mileage conventions. 2 to 10 characters. |
| `vehicle` | [VehicleInput](https://data-services.autouncle.com/docs/reference/vehicles#vehicleinput-describing-a-vehicle) | The vehicle, as a VehicleInput: an AVS vehicle document (any `vehicle` an endpoint returned, posted back unchanged) or the vehicle's attributes as a listing gives them. |
| `description` | string | Unstructured listing text describing the vehicle. Existing parsers and deployment-configured optional AI can propose attributes; the response identifies assumptions and unresolved inputs. 1 to 20000 characters. |
| `images` | array | Up to eight vehicle photos, each supplied by HTTPS URL or inline base64 data. AI image resolution is deployment-configured and never runs for test keys. Warnings identify unused images. On a live key, photos cost one extra credit per request (not per photo), charged only when the request succeeds and a value was read from them (`usage.charges.images`); skipped or unused photos are not charged. At most 8 items. |
| `images[].url` | string (uri) | Public HTTPS image URL on port 443, without credentials or fragments. Private network destinations and redirects are rejected. Remote images must be supported image types and at most 8 MB each. At most 2048 characters. |
| `images[].data` | string | Strict base64-encoded image bytes, without a data-URL prefix. Inline data must also fit the total 1 MB API request limit. At most 1000000 characters. |
| `images[].media_type` | string | MIME type for inline image bytes: image/jpeg, image/png, image/webp or image/gif. The actual image signature is checked. At most 100 characters. |
| `options` | object | How the vehicle is resolved. |
| `options.resolution` | string | auto uses deterministic resolution and optional configured AI; no_ai and strict use deterministic resolution only. Normalization never assumes a year or mileage. Strict resolution also ignores allow_equipment_estimation. One of `auto`, `no_ai`, `strict`. |
| `options.allow_equipment_estimation` | boolean | Explicitly allow equipment the request does not state to be assumed: the catalogue's equipment for the identified trim when the catalogue lists it, otherwise the equipment at least 70% of comparable vehicles on the market have. Assumed equipment is only added, never against equipment the request, its description or its photos state or deny, and is marked source imputed, basis assumed in identification.fields (availability unknown in vehicle.equipment), with an equipment_assumed warning and an improve_precision hint. Test keys use only the catalogue trim, never market data. Default false. Strict resolution ignores it. Default `false`. |

Structured example:

```json
{
  "country": "DK",
  "vehicle": {
    "make": "Volkswagen",
    "model": "Golf",
    "model_year": 2019,
    "fuel": "diesel",
    "transmission": "automatic"
  }
}
```

Text example:

```json
{
  "country": "DK",
  "description": "VW Golf 2.0 TDI DSG Highline, 2019, 84.000 km"
}
```

Canonical example:

```json
{
  "country": "DK",
  "vehicle": {
    "identity": {
      "brand": {
        "name": "Volkswagen"
      },
      "model": {
        "name": "Golf"
      }
    },
    "specs": {
      "energy": {
        "fuel": "diesel"
      },
      "power": {
        "kw": 110
      },
      "transmission": {
        "type": "automatic"
      }
    },
    "registration": {
      "first_registration": "2019-05-14"
    },
    "listing": {
      "mileage": {
        "value": 84000,
        "unit": "km"
      }
    }
  }
}
```

#### Response

`application/json`, a `NormalizationResponse`: A normalized vehicle with its provenance, any candidates, hints, warnings, usage and the common notes and attributions. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| Field | Type | Description |
| --- | --- | --- |
| `request_id` | string | The normalization's request ID, shown in the console request log. Pattern `^nrm_[A-Za-z0-9]+$`. |
| `object` | string | Always `normalization`. One of `normalization`. |
| `status` | string | Always `normalized`. A vehicle that cannot be resolved returns a Problem instead. One of `normalized`. |
| `country` | string | Market as an ISO 3166-1 alpha-2 code, normalized from your request (for example `DK`). Pattern `^[A-Z]{2}$`. |
| `mode` | string | `test` for a test key or `live` for a live key. Normalization is not simulated in test mode; it is only free. One of `live`, `test`. |
| `ambiguous` | boolean | True when several catalogue records fit (identification.status is ambiguous); see identification.candidates. |
| `vehicle` | [Vehicle](https://data-services.autouncle.com/docs/reference/vehicles#the-vehicle-object) | The identified vehicle. An AVS vehicle document; left out when the vehicle could not be identified to a brand and a model, with the reason in `identification`. |
| `identification` | [VehicleIdentification](https://data-services.autouncle.com/docs/reference/vehicles#identification) | How the vehicle was identified: status, depth, candidates and the provenance of every value in `vehicle`. |
| `improve_precision` | array | Inputs that would identify the vehicle more precisely, most useful first. |
| `improve_precision[].field` **required** | string | Request field to supply, for example `vehicle.catalogue.drivetrain_id` or `vehicle.power_hp`. |
| `improve_precision[].reason` **required** | string | Machine-readable reason, for example `drivetrain_ambiguous`, `drivetrain_unresolved` or `ai_interpreted`. |
| `improve_precision[].expected_impact` **required** | string | `high`, `medium` or `low`: qualitative. One of `high`, `medium`, `low`. |
| `improve_precision[].message` **required** | string | Plain-language hint, suitable for display. |
| `improve_precision[].candidates` | array | Catalogue candidates to choose from, when the hint is about an ambiguous identity. |
| `improve_precision[].candidates[].id` **required** | string | Catalogue ID of the candidate. |
| `improve_precision[].candidates[].name` **required** | string | Catalogue name of the candidate. |
| `improve_precision[].candidates[].source` **required** | string | How the candidate was found. One of `provided`, `catalogue_id`, `catalogue_derived`, `text_parser`, `registry`, `catalogue_match`, `ai_text`, `ai_vision`, `imputed`, `default`. |
| `improve_precision[].candidates[].basis` | string | How the value was established: observed (supplied by the caller or read from a registry record), extracted (parsed or automatically interpreted from supplied text or photos), catalogue (deterministically derived from or matched against the AutoUncle catalogue) or assumed (a heuristic default or fixed baseline, not evidence about this vehicle). One of `observed`, `extracted`, `catalogue`, `assumed`. |
| `improve_precision[].candidates[].match_score` | number | Match strength from 0 to 1. |
| `improve_precision[].candidates[].ambiguous` | boolean | Whether the candidate itself is ambiguous. |
| `improve_precision[].candidates[].candidate_count` | integer | Number of fitting entries when ambiguous. Minimum 2. |
| `warnings` | array | Problems with this request's input, for example `drivetrain_ambiguous`, `generation_ambiguous`, `spec_conflict`, `model_not_recognized` or `vehicle_input_overridden`. Match on `code`. |
| `warnings[].code` **required** | string | Stable machine-readable warning code. Pattern `^[a-z][a-z0-9_]*$`. |
| `warnings[].message` **required** | string | Plain-language explanation. |
| `usage` | object | Billing for this call. |
| `usage.billable` **required** | boolean | `true` when this normalization captured a credit. |
| `usage.credits_used` **required** | integer | Credits this call consumed. Always 0 on an idempotent replay. 0 to 2. |
| `usage.original_credits_used` **required** | integer | Credits the original normalization consumed (0 to 2; 1 for the normalization, plus 1 for photos), also on a replay. 0 to 2. |
| `usage.charges` **required** | object | What `original_credits_used` paid for. Empty when nothing was charged. |
| `usage.charges.base` | integer | The normalization itself, 1 credit. Minimum 1. |
| `usage.charges.images` | integer | Image processing, 1 credit per request. Only when photos were sent and a value in `identification.fields` was read from them. Minimum 1. |
| `usage.credits_remaining` **required** | integer | Workspace credits left after this call. Minimum 0. |
| `usage.cache_hit` **required** | boolean | Reserved. Always false in this version. |
| `usage.idempotent_replay` **required** | boolean | `true` when the same Idempotency-Key and body were normalized before; the input is resolved again for free. |
| `usage.mode` **required** | string | `test` or `live`. One of `live`, `test`. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Standing limitations and legal notices. Always present. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | Data sources that contributed to this result. Always present. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |
| `Retry-After` | Seconds to wait before retrying. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`invalid_request`](https://data-services.autouncle.com/docs/errors#invalid_request) | 400 | No | Send a request matching the documented schema. |
| [`country_required`](https://data-services.autouncle.com/docs/errors#country_required) | 400 | No | Include country, the valuation market, in the request. |
| [`unsupported_country`](https://data-services.autouncle.com/docs/errors#unsupported_country) | 400 | No | Choose a supported ISO country code. |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_credits`](https://data-services.autouncle.com/docs/errors#insufficient_credits) | 402 | No | The organization has no credits available. Contact sales for a package. |
| [`key_spend_limit_reached`](https://data-services.autouncle.com/docs/errors#key_spend_limit_reached) | 402 | No | This API key has reached its monthly credit limit. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`country_not_enabled`](https://data-services.autouncle.com/docs/errors#country_not_enabled) | 403 | No | This country is not enabled for this organization or key. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`unknown_catalogue_id`](https://data-services.autouncle.com/docs/errors#unknown_catalogue_id) | 404 | No | The catalogue ID is unknown. Fetch current IDs from the catalogue API. |
| [`idempotency_conflict`](https://data-services.autouncle.com/docs/errors#idempotency_conflict) | 409 | No | This idempotency key was used with different input. Choose a new key. |
| [`request_in_progress`](https://data-services.autouncle.com/docs/errors#request_in_progress) | 409 | Yes | A request with this idempotency key is still running. Retry later with the same key. |
| [`payload_too_large`](https://data-services.autouncle.com/docs/errors#payload_too_large) | 413 | No | The request exceeds the maximum supported size of 1 MB. |
| [`vehicle_not_identified`](https://data-services.autouncle.com/docs/errors#vehicle_not_identified) | 422 | No | Provide more vehicle attributes or select catalogue IDs. |
| [`catalogue_id_conflict`](https://data-services.autouncle.com/docs/errors#catalogue_id_conflict) | 422 | No | The catalogue IDs do not describe the same vehicle hierarchy. |
| [`vehicle_out_of_range`](https://data-services.autouncle.com/docs/errors#vehicle_out_of_range) | 422 | No | The vehicle is outside the supported valuation range. |
| [`images_unreadable`](https://data-services.autouncle.com/docs/errors#images_unreadable) | 422 | No | Provide readable supported images. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |
| [`test_limit_reached`](https://data-services.autouncle.com/docs/errors#test_limit_reached) | 429 | Yes | This workspace has used its fair-use allowance of test-key requests for now. |
| [`concurrency_limited`](https://data-services.autouncle.com/docs/errors#concurrency_limited) | 429 | Yes | Too many valuations are running at the same time for this organization. |
| [`rate_limit_unavailable`](https://data-services.autouncle.com/docs/errors#rate_limit_unavailable) | 503 | Yes | Request limiting is temporarily unavailable. Retry later. |
| [`engine_busy`](https://data-services.autouncle.com/docs/errors#engine_busy) | 503 | Yes | The valuation engine is at capacity. Retry after a short delay. |
| [`request_timeout`](https://data-services.autouncle.com/docs/errors#request_timeout) | 504 | Yes | The valuation request exhausted its processing time budget. |
| [`resolution_timeout`](https://data-services.autouncle.com/docs/errors#resolution_timeout) | 504 | Yes | Vehicle interpretation did not finish within its time budget. |
| [`resolution_unavailable`](https://data-services.autouncle.com/docs/errors#resolution_unavailable) | 503 | Yes | Vehicle interpretation is temporarily unavailable. |
| [`resolution_invalid_response`](https://data-services.autouncle.com/docs/errors#resolution_invalid_response) | 502 | Yes | Vehicle interpretation returned an invalid response. |
| [`image_timeout`](https://data-services.autouncle.com/docs/errors#image_timeout) | 504 | Yes | Image retrieval did not finish within its time budget. |
| [`image_unavailable`](https://data-services.autouncle.com/docs/errors#image_unavailable) | 503 | Yes | The image service is temporarily unavailable. |
| [`image_invalid_response`](https://data-services.autouncle.com/docs/errors#image_invalid_response) | 502 | Yes | The image service returned an invalid response. |
| [`internal_error`](https://data-services.autouncle.com/docs/errors#internal_error) | 500 | No | The valuation could not be completed. Contact support with the request ID. |

### GET /v1/account

Inspect key permissions and available credits.

- **Scope:** `account:read`
- **Cost:** Free. Counts towards the per-minute valuation rate limit.
- **Rate limit:** valuations bucket, default 60 requests per minute. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Response

`application/json`, a `Account`: The workspace and API key that made the call. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| Field | Type | Description |
| --- | --- | --- |
| `object` | string | Always `account`. |
| `organization` | object | The workspace that owns the key. |
| `organization.id` **required** | string | Workspace ID (`org_…`). Pattern `^org_[A-Za-z0-9]+$`. |
| `organization.name` **required** | string | Workspace name. |
| `key` | object | The API key that made this call. |
| `key.id` **required** | string | Key ID (`key_…`). Safe to log; it is not the secret. Pattern `^key_[A-Za-z0-9]+$`. |
| `key.mode` **required** | string | `test` (simulated, free) or `live`. One of `test`, `live`. |
| `key.scopes` **required** | array | Scopes granted to the key. |
| `credits_remaining` | integer | Valuation credits available to the workspace now. Minimum 0. |
| `allowed_countries` | array | Markets this key can value, as the ISO codes requests use in `country` (for example `DK`, `GB`, `DE`): the workspace's markets narrowed by the key's own allowed countries. When neither restricts the markets, every market is listed; the list is empty only when the key's markets and the workspace's do not overlap. |
| `rate_limit_per_minute` | integer | Requests allowed per minute for the workspace in the valuations bucket, and separately in the vehicles bucket (default 60 each). Catalogue requests have their own limit. Minimum 1. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Always empty for account results. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | Always empty for account results. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |

### GET /v1/catalogue/brands

List vehicle makes.

- **Scope:** `catalogue:read`
- **Cost:** Free.
- **Rate limit:** catalogue bucket, default 120 requests per minute. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Response

`application/json`, a `CatalogueBrandList`: Vehicle makes. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| Field | Type | Description |
| --- | --- | --- |
| `object` | string | Always `list`. |
| `version` | string | Catalogue version, for example `5.6.7:NEW`. Refresh cached catalogue data when it changes. |
| `data` | object array | The items, sorted by name. Not paginated. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Notes for this result. Usually empty. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | The catalogue attribution, pointing at `/data`, when the list contains catalogue data. |

Each item in `data`, a `CatalogueBrand`:

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | Brand ID, for example `b-0957579dc5bca6de229d2f32`. Opaque: store it as returned. |
| `name` | string | Catalogue brand name, for example `VW`. |
| `object` | string | Always `brand`. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |

### GET /v1/catalogue/brands/{id}/models

List models for a make.

- **Scope:** `catalogue:read`
- **Cost:** Free.
- **Rate limit:** catalogue bucket, default 120 requests per minute. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Identifier from a previous response. At most 200 characters. |

#### Response

`application/json`, a `CatalogueModelList`: Models of one make. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| Field | Type | Description |
| --- | --- | --- |
| `object` | string | Always `list`. |
| `version` | string | Catalogue version, for example `5.6.7:NEW`. Refresh cached catalogue data when it changes. |
| `data` | object array | The items, sorted by name. Not paginated. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Notes for this result. Usually empty. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | The catalogue attribution, pointing at `/data`, when the list contains catalogue data. |

Each item in `data`, a `CatalogueModel`:

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | Model ID, for example `cm-6bb52590daf6d1b19108ec93`. |
| `name` | string | Model name without the brand, for example `Golf`. |
| `object` | string | Always `model`. |
| `brand_id` | string | Parent brand ID. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`unknown_catalogue_id`](https://data-services.autouncle.com/docs/errors#unknown_catalogue_id) | 404 | No | The catalogue ID is unknown. Fetch current IDs from the catalogue API. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |

### GET /v1/catalogue/models/{id}/generations

List generations for a model.

- **Scope:** `catalogue:read`
- **Cost:** Free.
- **Rate limit:** catalogue bucket, default 120 requests per minute. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Model ID from the models or search endpoint. A model alias returns the generations it stands for. At most 200 characters. |
| `year` | query | integer | No | Registration or model year. Returns only generations whose production years include it. Must be an integer from 1900 to next year. |

#### Response

`application/json`, a `CatalogueGenerationList`: Generations of one model, optionally narrowed by year. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| Field | Type | Description |
| --- | --- | --- |
| `object` | string | Always `list`. |
| `version` | string | Catalogue version, for example `5.6.7:NEW`. Refresh cached catalogue data when it changes. |
| `data` | object array | The items, sorted by name. Not paginated. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Notes for this result. Usually empty. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | The catalogue attribution, pointing at `/data`, when the list contains catalogue data. |

Each item in `data`, a `CatalogueGeneration`:

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | Generation ID, for example `mg-40c5d8de40bb48ae60fc0a6c`. |
| `name` | string | Generation name, including body variant where relevant, for example `Golf VIII Variant`. |
| `object` | string | Always `generation`. |
| `model_id` | string | Parent model ID. |
| `from_year` | integer | First production year. Omitted when unknown. |
| `to_year` | integer | Last production year. Omitted when unknown or still in production. |
| `body` | string | Catalogue body type. Omitted when unknown. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`invalid_request`](https://data-services.autouncle.com/docs/errors#invalid_request) | 400 | No | Send a request matching the documented schema. |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`unknown_catalogue_id`](https://data-services.autouncle.com/docs/errors#unknown_catalogue_id) | 404 | No | The catalogue ID is unknown. Fetch current IDs from the catalogue API. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |

### GET /v1/catalogue/generations/{id}/drivetrains

List engine and transmission variants.

- **Scope:** `catalogue:read`
- **Cost:** Free.
- **Rate limit:** catalogue bucket, default 120 requests per minute. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Generation ID from the generations endpoint. At most 200 characters. |
| `fuel` | query | string | No | Keep drivetrains with this fuel. Accepts the public fuel values from /v1/catalogue/enums, such as petrol or diesel. At most 200 characters. |
| `transmission` | query | string | No | Keep drivetrains with this transmission, manual or automatic. Case-insensitive. At most 200 characters. |
| `power_hp` | query | string | No | Keep drivetrains with exactly this power in horsepower. At most 200 characters. |
| `model_id` | query | string | No | Optional selected model UUID. Restricts drivetrain results to that model alias, such as GLC300e. |

#### Response

`application/json`, a `CatalogueDrivetrainList`: Drivetrains of one generation, optionally filtered. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| Field | Type | Description |
| --- | --- | --- |
| `object` | string | Always `list`. |
| `version` | string | Catalogue version, for example `5.6.7:NEW`. Refresh cached catalogue data when it changes. |
| `data` | object array | The items, sorted by name. Not paginated. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Notes for this result. Usually empty. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | The catalogue attribution, pointing at `/data`, when the list contains catalogue data. |

Each item in `data`, a `CatalogueDrivetrain`:

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | Drivetrain ID, for example `dv-947a3199394a5a4b41cb2869`. |
| `name` | string | Engine and transmission designation, for example `1.5 TSI (130 Hp)`. |
| `object` | string | Always `drivetrain`. |
| `generation_id` | string | Parent generation ID. |
| `fuel` | string | Fuel. Usually a public fuel value such as `petrol`, `diesel` or `plug_in_hybrid_petrol`; some catalogue values, such as `CNG_Hybrid`, are passed through unchanged. Omitted when unknown. |
| `power_hp` | number | Power in horsepower. Omitted when unknown. |
| `transmission` | string | Lowercase catalogue transmission, usually `manual` or `automatic`. Omitted when unknown. |
| `engine_size_l` | number | Engine displacement in litres. Omitted when unknown. |
| `battery_kwh` | number | Battery capacity in kWh for electrified drivetrains. Omitted when unknown. |
| `drive` | string | Catalogue traction label, for example `2WD` or `AWD`. Note that this is not the `fwd`/`rwd`/`awd`/`4wd` value used in `vehicle.drive`. Omitted when unknown. |
| `doors` | integer | Number of doors. Omitted when unknown. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`unknown_catalogue_id`](https://data-services.autouncle.com/docs/errors#unknown_catalogue_id) | 404 | No | The catalogue ID is unknown. Fetch current IDs from the catalogue API. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |

### GET /v1/catalogue/brands/{id}/equipment-variants

List equipment variants.

- **Scope:** `catalogue:read`
- **Cost:** Free.
- **Rate limit:** catalogue bucket, default 120 requests per minute. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Brand ID from the brands or search endpoint. At most 200 characters. |

#### Response

`application/json`, a `CatalogueEquipmentVariantList`: Equipment variants of one make. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| Field | Type | Description |
| --- | --- | --- |
| `object` | string | Always `list`. |
| `version` | string | Catalogue version, for example `5.6.7:NEW`. Refresh cached catalogue data when it changes. |
| `data` | object array | The items, sorted by name. Not paginated. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Notes for this result. Usually empty. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | The catalogue attribution, pointing at `/data`, when the list contains catalogue data. |

Each item in `data`, a `CatalogueEquipmentVariant`:

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | Equipment variant ID, for example `ev-227a3875b490f1310578b286`. |
| `name` | string | Trim or equipment line name, for example `Active`. |
| `object` | string | Always `equipment_variant`. |
| `brand_id` | string | Parent brand ID. Omitted when the catalogue has no brand for it. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`unknown_catalogue_id`](https://data-services.autouncle.com/docs/errors#unknown_catalogue_id) | 404 | No | The catalogue ID is unknown. Fetch current IDs from the catalogue API. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |

### GET /v1/catalogue/search

Search makes and models.

- **Scope:** `catalogue:read`
- **Cost:** Free.
- **Rate limit:** catalogue bucket, default 120 requests per minute. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `q` | query | string | Yes | Two to 200 characters. Case-insensitive substring match against brand names and "brand model" names as the catalogue spells them (for example VW, not Volkswagen). Returns up to 20 brands and 80 models. 2 to 200 characters. |

#### Response

`application/json`, a `CatalogueSearchResults`: Makes and models matching the search text: up to 20 brands, then up to 80 models. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| Field | Type | Description |
| --- | --- | --- |
| `object` | string | Always `list`. |
| `version` | string | Catalogue version, for example `5.6.7:NEW`. Refresh cached catalogue data when it changes. |
| `data` | object array | Matching brands first, then matching models. Not paginated. At most 100 items. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Notes for this result. Usually empty. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | The catalogue attribution, pointing at `/data`, when the list contains catalogue data. |

Each item in `data`, a `CatalogueSearchResult`:

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | Brand or model ID. |
| `name` | string | Brand name, or model name without the brand (for example `Golf Alltrack`). |
| `object` | string | `brand` or `model`. One of `brand`, `model`. |
| `brand_id` | string | Parent brand ID. Models only. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`invalid_request`](https://data-services.autouncle.com/docs/errors#invalid_request) | 400 | No | Send a request matching the documented schema. |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |

### GET /v1/catalogue/enums

List supported input values.

- **Scope:** `catalogue:read`
- **Cost:** Free.
- **Rate limit:** catalogue bucket, default 120 requests per minute. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Response

`application/json`, a `CatalogueEnums`: The values accepted by enumerated request fields. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| Field | Type | Description |
| --- | --- | --- |
| `object` | string | Always `enums`. |
| `data` | object | Accepted values per request field. |
| `data.fuel` **required** | array | Public fuel values accepted in `vehicle.fuel`. |
| `data.transmission` **required** | array | Values accepted in `vehicle.transmission`: `manual`, `automatic`. |
| `data.drive` **required** | array | Values accepted in `vehicle.drive`: `fwd`, `rwd`, `awd`, `4wd`. |
| `data.mileage_units` **required** | array | Values accepted in `vehicle.mileage.unit`: `km`, `mi`, `mil`. |
| `data.price_basis` **required** | array | Values accepted in `pricing.price_basis`: `dealer_retail`, `private_sale`. |
| `data.resolution` **required** | array | Values accepted in `options.resolution`: `auto`, `no_ai`, `strict`. |
| `data.precision` **required** | array | Precision grades, best first, accepted in `options.min_precision`: `high`, `medium`, `low`, `indicative`. |
| `data.equipment` **required** | array | Equipment feature keys accepted in `vehicle.equipment` and returned in a Vehicle's `equipment`, such as `EXTERIOR_TOWBAR_FIXED` or `BATTERY_HEAT_PUMP`. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Always empty. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | Always empty. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |

### GET /v1/catalogue/countries

List supported markets and mileage units.

- **Scope:** `catalogue:read`
- **Cost:** Free.
- **Rate limit:** catalogue bucket, default 120 requests per minute. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Response

`application/json`, a `CatalogueCountries`: Every market the service can value, and whether new workspaces can value it. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| Field | Type | Description |
| --- | --- | --- |
| `object` | string | Always `list`. |
| `data` | array | One entry per market. |
| `data[].id` **required** | string | Market code to send as `country`, an ISO 3166-1 alpha-2 code such as `DK` or `GB`. Pattern `^[A-Z]{2}$`. |
| `data[].mileage_unit` **required** | string | The market's mileage unit. One of `km`, `mi`, `mil`. |
| `data[].availability` **required** | string | `general`: enabled for every new workspace. `on_request`: listed for completeness, but a workspace can value it only after AutoUncle enables it; until then a valuation returns 403 country_not_enabled. GET /v1/account shows what your workspace may value. One of `general`, `on_request`. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Always empty. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | Always empty. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |

### GET /v1/catalogue/version

Get the catalogue version.

- **Scope:** `catalogue:read`
- **Cost:** Free.
- **Rate limit:** catalogue bucket, default 120 requests per minute. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Response

`application/json`, a `CatalogueVersion`: The current catalogue version. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| Field | Type | Description |
| --- | --- | --- |
| `version` | string | Catalogue version, for example `5.6.7:NEW`. Refresh cached catalogue data when it changes. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Always empty. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | Always empty. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |

### GET /v1/catalogue/{kind}/{id}

Get an item by catalogue UUID.

- **Scope:** `catalogue:read`
- **Cost:** Free.
- **Rate limit:** catalogue bucket, default 120 requests per minute. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `kind` | path | string | Yes | One of brands, models, generations, drivetrains or equipment-variants. Any other value returns not_found. At most 200 characters. |
| `id` | path | string | Yes | The catalogue ID of an item of that kind. At most 200 characters. |

#### Response

`application/json`, a `CatalogueItem`: One catalogue item with the same fields as in its list endpoint, plus notes and attributions. `object` tells which kind it is. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| `object` | Fields |
| --- | --- |
| `brand` | The fields of an item in [GET /v1/catalogue/brands](https://data-services.autouncle.com/docs/reference/catalogue#get-v1-catalogue-brands), plus `notes` and `attributions`. |
| `model` | The fields of an item in [GET /v1/catalogue/brands/{id}/models](https://data-services.autouncle.com/docs/reference/catalogue#get-v1-catalogue-brands-id-models), plus `notes` and `attributions`. |
| `generation` | The fields of an item in [GET /v1/catalogue/models/{id}/generations](https://data-services.autouncle.com/docs/reference/catalogue#get-v1-catalogue-models-id-generations), plus `notes` and `attributions`. |
| `drivetrain` | The fields of an item in [GET /v1/catalogue/generations/{id}/drivetrains](https://data-services.autouncle.com/docs/reference/catalogue#get-v1-catalogue-generations-id-drivetrains), plus `notes` and `attributions`. |
| `equipment_variant` | The fields of an item in [GET /v1/catalogue/brands/{id}/equipment-variants](https://data-services.autouncle.com/docs/reference/catalogue#get-v1-catalogue-brands-id-equipment-variants), plus `notes` and `attributions`. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`not_found`](https://data-services.autouncle.com/docs/errors#not_found) | 404 | No | The requested resource was not found. |
| [`unknown_catalogue_id`](https://data-services.autouncle.com/docs/errors#unknown_catalogue_id) | 404 | No | The catalogue ID is unknown. Fetch current IDs from the catalogue API. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |

### POST /v1/vehicles/decode

Decode a VIN into an AutoUncle vehicle.

Decodes a 17-character VIN and identifies what the decoder says against the AutoUncle catalogue. The result is the same Vehicle valuations and normalizations return, with catalogue identity, provenance per field, candidates, improvement hints, notes and source attributions; post it back as the vehicle of a valuation. One credit per live lookup that returns vehicle data (`resolved`, `suggested` or `ambiguous`); `no_match`, failures and test keys are free. A VIN never yields German HSN/TSN codes; use POST /v1/vehicles/hsn-tsn with codes from the registration document. Test keys return a fixed synthetic record without decoding; its catalogue identification is real.

- **Scope:** `vehicles:read`
- **Cost:** One credit for a live lookup that returns vehicle data (`resolved`, `suggested` or `ambiguous`). `no_match`, failures and test keys are free.
- **Rate limit:** vehicles bucket, default 60 requests per minute, counted separately from valuations. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Request body

`application/json`, a `VinDecodeRequest`: A VIN to decode. Unknown fields are rejected.

| Field | Type | Description |
| --- | --- | --- |
| `vin` **required** | string | The 17-character VIN. Spaces and lower case are accepted; look-alike characters (O for 0, I for 1) are never repaired, and a VIN containing I, O or Q is rejected. 17 to 40 characters. |
| `country` **required** | string | Your market for this lookup, as an ISO 3166-1 alpha-2 code from GET /v1/catalogue/countries. It scopes key permissions and logging; it is never treated as the car's original market. Pattern `^[A-Za-z]{2}$`. |
| `market` | string | The car's original sales market (ISO 3166-1 alpha-2), only when you know it independently. Never derive it from your market or the registration country. Pattern `^[A-Za-z]{2}$`. |
| `model_year` | integer | The model year, only when you know it independently. A first registration or production year does not establish it. 1886 to 2100. |

Vin example:

```json
{
  "vin": "WVWZZZ1KZ5P000001",
  "country": "DE"
}
```

#### Response

`application/json`, a `VehicleLookupResult`: The vehicle a lookup found, identified against the catalogue, with provenance, improvement hints, warnings, notes, attributions and billing. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| Field | Type | Description |
| --- | --- | --- |
| `object` | string | Always `vehicle_lookup`. |
| `request_id` | string | Lookup ID (`lkp_…`), also in the `X-Lookup-Id` header. Shown in the console request log. Pattern `^lkp_[A-Za-z0-9]+$`. |
| `lookup` | string | Which lookup ran. One of `vin`, `hsn_tsn`, `plate`. |
| `status` | string | The source's answer, separate from how well the catalogue identified the vehicle (`vehicle.status`). resolved: the source established vehicle data; suggested: only conditional answers (read the notes); ambiguous: the source holds competing answers; no_match: a valid input the source does not know (not billed); unsupported and invalid_input: the source could not answer this input (not billed). Test keys always get resolved. One of `resolved`, `suggested`, `ambiguous`, `no_match`, `unsupported`, `invalid_input`. |
| `country` | string | Your market for this lookup, normalized (ISO 3166-1 alpha-2). Pattern `^[A-Z]{2}$`. |
| `mode` | string | `test` for a test key, `live` for a live key. One of `live`, `test`. |
| `synthetic` | boolean | `true` for the fixed example a test key gets. A synthetic vehicle says nothing about your input. |
| `vehicle` | [Vehicle](https://data-services.autouncle.com/docs/reference/vehicles#the-vehicle-object) | What the source says, identified against the AutoUncle catalogue, as an AVS vehicle document: catalogue identity where the catalogue knows the make, and the source's values otherwise. Provenance and candidates are in `identification`. A make the catalogue does not know gives `identification.status: unidentified`, with the stated brand and model names and no IDs. It is left out when the vehicle could not be identified to a brand and a model, with the reason in `identification`. |
| `identification` | [VehicleIdentification](https://data-services.autouncle.com/docs/reference/vehicles#identification) | How the vehicle was identified: status, depth, candidates and the provenance of every value in `vehicle`. |
| `freshness` | [LookupFreshness](https://data-services.autouncle.com/docs/reference/vehicles#freshness) | How current the answer is. |
| `improve_precision` | array | Inputs that would identify the vehicle more precisely, most useful first. Send them with the vehicle to POST /v1/vehicles/normalize or POST /v1/valuations. |
| `improve_precision[].field` **required** | string | Request field to supply, for example `vehicle.catalogue.drivetrain_id` or `vehicle.power_hp`. |
| `improve_precision[].reason` **required** | string | Machine-readable reason, for example `drivetrain_ambiguous` or `drivetrain_unresolved`. |
| `improve_precision[].expected_impact` **required** | string | `high`, `medium` or `low`: qualitative. One of `high`, `medium`, `low`. |
| `improve_precision[].message` **required** | string | Plain-language hint, suitable for display. |
| `improve_precision[].candidates` | array | Catalogue candidates to choose from, when the hint is about an ambiguous identity. |
| `improve_precision[].candidates[].id` **required** | string | Catalogue ID of the candidate. |
| `improve_precision[].candidates[].name` **required** | string | Catalogue name of the candidate. |
| `improve_precision[].candidates[].source` **required** | string | How the candidate was found. One of `provided`, `catalogue_id`, `catalogue_derived`, `text_parser`, `registry`, `catalogue_match`, `ai_text`, `ai_vision`, `imputed`, `default`. |
| `improve_precision[].candidates[].basis` | string | How the value was established: observed (supplied by the caller or read from a registry record), extracted (parsed or automatically interpreted from supplied text or photos), catalogue (deterministically derived from or matched against the AutoUncle catalogue) or assumed (a heuristic default or fixed baseline, not evidence about this vehicle). One of `observed`, `extracted`, `catalogue`, `assumed`. |
| `improve_precision[].candidates[].match_score` | number | Match strength from 0 to 1. |
| `improve_precision[].candidates[].ambiguous` | boolean | Whether the candidate itself is ambiguous. |
| `improve_precision[].candidates[].candidate_count` | integer | Number of fitting entries when ambiguous. Minimum 2. |
| `warnings` | array | What the source or the catalogue could not use, for example `registry_no_match`, `registry_identifier_invalid`, `model_not_recognized` or `drivetrain_ambiguous`. Match on `code`. |
| `warnings[].code` **required** | string | Stable machine-readable warning code. Pattern `^[a-z][a-z0-9_]*$`. |
| `warnings[].message` **required** | string | Plain-language explanation. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Standing limitations of the source, and the assumptions behind any `assumed` value. Always present. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | Data sources behind the published values, with their licence and attribution text. Always present; show them with the data. |
| `usage` | object | Billing for this call. |
| `usage.billable` **required** | boolean | `true` when this lookup captured a credit. |
| `usage.credits_used` **required** | integer | Credits this call consumed (0 or 1). 0 to 1. |
| `usage.original_credits_used` **required** | integer | The same as `credits_used`: lookups are never replayed. 0 to 1. |
| `usage.charges` **required** | object | What `credits_used` paid for. Empty when nothing was charged. |
| `usage.charges.base` | integer | The lookup itself, 1 credit. Minimum 1. |
| `usage.credits_remaining` **required** | integer | Workspace credits left after this call. Minimum 0. |
| `usage.cache_hit` **required** | boolean | `true` when the answer came from AutoUncle's lookup cache. Cached answers are billed like fresh ones. |
| `usage.idempotent_replay` **required** | boolean | Always false: lookups are not replayed. |
| `usage.mode` **required** | string | `test` or `live`. One of `live`, `test`. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |
| `X-Lookup-Id` | The vehicle lookup's ID (`lkp_…`), the same value as the body's `request_id`. Present on every lookup that was started, including failed ones. Use it in the console request log and with support. Lookup results are not stored, so it cannot be read back. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`invalid_request`](https://data-services.autouncle.com/docs/errors#invalid_request) | 400 | No | Send a request matching the documented schema. |
| [`unsupported_country`](https://data-services.autouncle.com/docs/errors#unsupported_country) | 400 | No | Choose a supported ISO country code. |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_credits`](https://data-services.autouncle.com/docs/errors#insufficient_credits) | 402 | No | The organization has no credits available. Contact sales for a package. |
| [`key_spend_limit_reached`](https://data-services.autouncle.com/docs/errors#key_spend_limit_reached) | 402 | No | This API key has reached its monthly credit limit. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`country_not_enabled`](https://data-services.autouncle.com/docs/errors#country_not_enabled) | 403 | No | This country is not enabled for this organization or key. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`payload_too_large`](https://data-services.autouncle.com/docs/errors#payload_too_large) | 413 | No | The request exceeds the maximum supported size of 1 MB. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |
| [`test_limit_reached`](https://data-services.autouncle.com/docs/errors#test_limit_reached) | 429 | Yes | This workspace has used its fair-use allowance of test-key requests for now. |
| [`rate_limit_unavailable`](https://data-services.autouncle.com/docs/errors#rate_limit_unavailable) | 503 | Yes | Request limiting is temporarily unavailable. Retry later. |
| [`lookup_unavailable`](https://data-services.autouncle.com/docs/errors#lookup_unavailable) | 503 | Yes | The vehicle lookup service is temporarily unavailable. |
| [`lookup_timeout`](https://data-services.autouncle.com/docs/errors#lookup_timeout) | 504 | Yes | The vehicle lookup service did not respond within its time budget. |
| [`internal_error`](https://data-services.autouncle.com/docs/errors#internal_error) | 500 | No | The valuation could not be completed. Contact support with the request ID. |

### POST /v1/vehicles/hsn-tsn

Look up German HSN/TSN type codes.

Looks up the German manufacturer and type codes from a Zulassungsbescheinigung (HSN, field 2.1, and the first three characters of TSN, field 2.2) in the Kraftfahrt-Bundesamt type snapshot and identifies the brand and model names it gives against the AutoUncle catalogue. KBA type rows carry no technical data, so the vehicle rarely gets past the model. One credit per live lookup that returns vehicle data; `no_match`, failures and test keys are free.

- **Scope:** `vehicles:read`
- **Cost:** One credit for a live lookup that returns vehicle data (`resolved`, `suggested` or `ambiguous`). `no_match`, failures and test keys are free.
- **Rate limit:** vehicles bucket, default 60 requests per minute, counted separately from valuations. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Request body

`application/json`, a `HsnTsnRequest`: German type codes to look up. Unknown fields are rejected.

| Field | Type | Description |
| --- | --- | --- |
| `hsn` **required** | string | Herstellerschlüsselnummer, field 2.1: four digits, sent as a string so leading zeroes are kept. 4 to 8 characters. |
| `tsn` **required** | string | The first three characters of the Typschlüsselnummer, field 2.2. Longer codes are rejected rather than truncated. 3 to 8 characters. |
| `country` | string | Your market for this lookup (ISO 3166-1 alpha-2). Defaults to DE. The codes are always KBA codes. Pattern `^[A-Za-z]{2}$`. |

Hsn tsn example:

```json
{
  "hsn": "0603",
  "tsn": "BMT"
}
```

#### Response

`application/json`, a `VehicleLookupResult`: The vehicle a lookup found, identified against the catalogue, with provenance, improvement hints, warnings, notes, attributions and billing. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| Field | Type | Description |
| --- | --- | --- |
| `object` | string | Always `vehicle_lookup`. |
| `request_id` | string | Lookup ID (`lkp_…`), also in the `X-Lookup-Id` header. Shown in the console request log. Pattern `^lkp_[A-Za-z0-9]+$`. |
| `lookup` | string | Which lookup ran. One of `vin`, `hsn_tsn`, `plate`. |
| `status` | string | The source's answer, separate from how well the catalogue identified the vehicle (`vehicle.status`). resolved: the source established vehicle data; suggested: only conditional answers (read the notes); ambiguous: the source holds competing answers; no_match: a valid input the source does not know (not billed); unsupported and invalid_input: the source could not answer this input (not billed). Test keys always get resolved. One of `resolved`, `suggested`, `ambiguous`, `no_match`, `unsupported`, `invalid_input`. |
| `country` | string | Your market for this lookup, normalized (ISO 3166-1 alpha-2). Pattern `^[A-Z]{2}$`. |
| `mode` | string | `test` for a test key, `live` for a live key. One of `live`, `test`. |
| `synthetic` | boolean | `true` for the fixed example a test key gets. A synthetic vehicle says nothing about your input. |
| `vehicle` | [Vehicle](https://data-services.autouncle.com/docs/reference/vehicles#the-vehicle-object) | What the source says, identified against the AutoUncle catalogue, as an AVS vehicle document: catalogue identity where the catalogue knows the make, and the source's values otherwise. Provenance and candidates are in `identification`. A make the catalogue does not know gives `identification.status: unidentified`, with the stated brand and model names and no IDs. It is left out when the vehicle could not be identified to a brand and a model, with the reason in `identification`. |
| `identification` | [VehicleIdentification](https://data-services.autouncle.com/docs/reference/vehicles#identification) | How the vehicle was identified: status, depth, candidates and the provenance of every value in `vehicle`. |
| `freshness` | [LookupFreshness](https://data-services.autouncle.com/docs/reference/vehicles#freshness) | How current the answer is. |
| `improve_precision` | array | Inputs that would identify the vehicle more precisely, most useful first. Send them with the vehicle to POST /v1/vehicles/normalize or POST /v1/valuations. |
| `improve_precision[].field` **required** | string | Request field to supply, for example `vehicle.catalogue.drivetrain_id` or `vehicle.power_hp`. |
| `improve_precision[].reason` **required** | string | Machine-readable reason, for example `drivetrain_ambiguous` or `drivetrain_unresolved`. |
| `improve_precision[].expected_impact` **required** | string | `high`, `medium` or `low`: qualitative. One of `high`, `medium`, `low`. |
| `improve_precision[].message` **required** | string | Plain-language hint, suitable for display. |
| `improve_precision[].candidates` | array | Catalogue candidates to choose from, when the hint is about an ambiguous identity. |
| `improve_precision[].candidates[].id` **required** | string | Catalogue ID of the candidate. |
| `improve_precision[].candidates[].name` **required** | string | Catalogue name of the candidate. |
| `improve_precision[].candidates[].source` **required** | string | How the candidate was found. One of `provided`, `catalogue_id`, `catalogue_derived`, `text_parser`, `registry`, `catalogue_match`, `ai_text`, `ai_vision`, `imputed`, `default`. |
| `improve_precision[].candidates[].basis` | string | How the value was established: observed (supplied by the caller or read from a registry record), extracted (parsed or automatically interpreted from supplied text or photos), catalogue (deterministically derived from or matched against the AutoUncle catalogue) or assumed (a heuristic default or fixed baseline, not evidence about this vehicle). One of `observed`, `extracted`, `catalogue`, `assumed`. |
| `improve_precision[].candidates[].match_score` | number | Match strength from 0 to 1. |
| `improve_precision[].candidates[].ambiguous` | boolean | Whether the candidate itself is ambiguous. |
| `improve_precision[].candidates[].candidate_count` | integer | Number of fitting entries when ambiguous. Minimum 2. |
| `warnings` | array | What the source or the catalogue could not use, for example `registry_no_match`, `registry_identifier_invalid`, `model_not_recognized` or `drivetrain_ambiguous`. Match on `code`. |
| `warnings[].code` **required** | string | Stable machine-readable warning code. Pattern `^[a-z][a-z0-9_]*$`. |
| `warnings[].message` **required** | string | Plain-language explanation. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Standing limitations of the source, and the assumptions behind any `assumed` value. Always present. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | Data sources behind the published values, with their licence and attribution text. Always present; show them with the data. |
| `usage` | object | Billing for this call. |
| `usage.billable` **required** | boolean | `true` when this lookup captured a credit. |
| `usage.credits_used` **required** | integer | Credits this call consumed (0 or 1). 0 to 1. |
| `usage.original_credits_used` **required** | integer | The same as `credits_used`: lookups are never replayed. 0 to 1. |
| `usage.charges` **required** | object | What `credits_used` paid for. Empty when nothing was charged. |
| `usage.charges.base` | integer | The lookup itself, 1 credit. Minimum 1. |
| `usage.credits_remaining` **required** | integer | Workspace credits left after this call. Minimum 0. |
| `usage.cache_hit` **required** | boolean | `true` when the answer came from AutoUncle's lookup cache. Cached answers are billed like fresh ones. |
| `usage.idempotent_replay` **required** | boolean | Always false: lookups are not replayed. |
| `usage.mode` **required** | string | `test` or `live`. One of `live`, `test`. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |
| `X-Lookup-Id` | The vehicle lookup's ID (`lkp_…`), the same value as the body's `request_id`. Present on every lookup that was started, including failed ones. Use it in the console request log and with support. Lookup results are not stored, so it cannot be read back. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`invalid_request`](https://data-services.autouncle.com/docs/errors#invalid_request) | 400 | No | Send a request matching the documented schema. |
| [`unsupported_country`](https://data-services.autouncle.com/docs/errors#unsupported_country) | 400 | No | Choose a supported ISO country code. |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_credits`](https://data-services.autouncle.com/docs/errors#insufficient_credits) | 402 | No | The organization has no credits available. Contact sales for a package. |
| [`key_spend_limit_reached`](https://data-services.autouncle.com/docs/errors#key_spend_limit_reached) | 402 | No | This API key has reached its monthly credit limit. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`country_not_enabled`](https://data-services.autouncle.com/docs/errors#country_not_enabled) | 403 | No | This country is not enabled for this organization or key. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`payload_too_large`](https://data-services.autouncle.com/docs/errors#payload_too_large) | 413 | No | The request exceeds the maximum supported size of 1 MB. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |
| [`test_limit_reached`](https://data-services.autouncle.com/docs/errors#test_limit_reached) | 429 | Yes | This workspace has used its fair-use allowance of test-key requests for now. |
| [`rate_limit_unavailable`](https://data-services.autouncle.com/docs/errors#rate_limit_unavailable) | 503 | Yes | Request limiting is temporarily unavailable. Retry later. |
| [`lookup_unavailable`](https://data-services.autouncle.com/docs/errors#lookup_unavailable) | 503 | Yes | The vehicle lookup service is temporarily unavailable. |
| [`lookup_timeout`](https://data-services.autouncle.com/docs/errors#lookup_timeout) | 504 | Yes | The vehicle lookup service did not respond within its time budget. |
| [`internal_error`](https://data-services.autouncle.com/docs/errors#internal_error) | 500 | No | The valuation could not be completed. Contact support with the request ID. |

### POST /v1/vehicles/lookup

Look up a vehicle by registration plate.

Looks the plate up in the country's vehicle register and identifies the registered vehicle against the AutoUncle catalogue. Denmark (DK) only in this version, through the Danish Motor Register (DMR); other countries return lookup_country_unsupported before anything is reserved. One credit per live lookup that finds the vehicle; no_match, failures and test-key lookups are free. Send the plate only in the JSON body. The plate and the register's answer are never stored; the request log keeps the outcome only.

- **Scope:** `vehicles:read`
- **Cost:** One credit for a live lookup that finds the vehicle. `no_match`, failures, unsupported countries and test keys are free.
- **Rate limit:** vehicles bucket, default 60 requests per minute, counted separately from valuations. See [limits](https://data-services.autouncle.com/docs/concepts/limits).

#### Request body

`application/json`, a `PlateLookupRequest`: A registration-plate lookup. Unknown fields are rejected.

| Field | Type | Description |
| --- | --- | --- |
| `country` **required** | string | Country of the plate, ISO 3166-1 alpha-2. Only DK is supported in this version. 2 to 2 characters. |
| `plate` **required** | string | Registration plate as printed. Spaces, dashes and dots are ignored and letters are matched case-insensitively. Danish plates have 2 to 7 letters and digits, including personal plates. 1 to 20 characters. |

#### Response

`application/json`, a `VehicleLookupResult`: The vehicle a lookup found, identified against the catalogue, with provenance, improvement hints, warnings, notes, attributions and billing. Errors return a [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) as `application/problem+json`.

| Field | Type | Description |
| --- | --- | --- |
| `object` | string | Always `vehicle_lookup`. |
| `request_id` | string | Lookup ID (`lkp_…`), also in the `X-Lookup-Id` header. Shown in the console request log. Pattern `^lkp_[A-Za-z0-9]+$`. |
| `lookup` | string | Which lookup ran. One of `vin`, `hsn_tsn`, `plate`. |
| `status` | string | The source's answer, separate from how well the catalogue identified the vehicle (`vehicle.status`). resolved: the source established vehicle data; suggested: only conditional answers (read the notes); ambiguous: the source holds competing answers; no_match: a valid input the source does not know (not billed); unsupported and invalid_input: the source could not answer this input (not billed). Test keys always get resolved. One of `resolved`, `suggested`, `ambiguous`, `no_match`, `unsupported`, `invalid_input`. |
| `country` | string | Your market for this lookup, normalized (ISO 3166-1 alpha-2). Pattern `^[A-Z]{2}$`. |
| `mode` | string | `test` for a test key, `live` for a live key. One of `live`, `test`. |
| `synthetic` | boolean | `true` for the fixed example a test key gets. A synthetic vehicle says nothing about your input. |
| `vehicle` | [Vehicle](https://data-services.autouncle.com/docs/reference/vehicles#the-vehicle-object) | What the source says, identified against the AutoUncle catalogue, as an AVS vehicle document: catalogue identity where the catalogue knows the make, and the source's values otherwise. Provenance and candidates are in `identification`. A make the catalogue does not know gives `identification.status: unidentified`, with the stated brand and model names and no IDs. It is left out when the vehicle could not be identified to a brand and a model, with the reason in `identification`. |
| `identification` | [VehicleIdentification](https://data-services.autouncle.com/docs/reference/vehicles#identification) | How the vehicle was identified: status, depth, candidates and the provenance of every value in `vehicle`. |
| `freshness` | [LookupFreshness](https://data-services.autouncle.com/docs/reference/vehicles#freshness) | How current the answer is. |
| `improve_precision` | array | Inputs that would identify the vehicle more precisely, most useful first. Send them with the vehicle to POST /v1/vehicles/normalize or POST /v1/valuations. |
| `improve_precision[].field` **required** | string | Request field to supply, for example `vehicle.catalogue.drivetrain_id` or `vehicle.power_hp`. |
| `improve_precision[].reason` **required** | string | Machine-readable reason, for example `drivetrain_ambiguous` or `drivetrain_unresolved`. |
| `improve_precision[].expected_impact` **required** | string | `high`, `medium` or `low`: qualitative. One of `high`, `medium`, `low`. |
| `improve_precision[].message` **required** | string | Plain-language hint, suitable for display. |
| `improve_precision[].candidates` | array | Catalogue candidates to choose from, when the hint is about an ambiguous identity. |
| `improve_precision[].candidates[].id` **required** | string | Catalogue ID of the candidate. |
| `improve_precision[].candidates[].name` **required** | string | Catalogue name of the candidate. |
| `improve_precision[].candidates[].source` **required** | string | How the candidate was found. One of `provided`, `catalogue_id`, `catalogue_derived`, `text_parser`, `registry`, `catalogue_match`, `ai_text`, `ai_vision`, `imputed`, `default`. |
| `improve_precision[].candidates[].basis` | string | How the value was established: observed (supplied by the caller or read from a registry record), extracted (parsed or automatically interpreted from supplied text or photos), catalogue (deterministically derived from or matched against the AutoUncle catalogue) or assumed (a heuristic default or fixed baseline, not evidence about this vehicle). One of `observed`, `extracted`, `catalogue`, `assumed`. |
| `improve_precision[].candidates[].match_score` | number | Match strength from 0 to 1. |
| `improve_precision[].candidates[].ambiguous` | boolean | Whether the candidate itself is ambiguous. |
| `improve_precision[].candidates[].candidate_count` | integer | Number of fitting entries when ambiguous. Minimum 2. |
| `warnings` | array | What the source or the catalogue could not use, for example `registry_no_match`, `registry_identifier_invalid`, `model_not_recognized` or `drivetrain_ambiguous`. Match on `code`. |
| `warnings[].code` **required** | string | Stable machine-readable warning code. Pattern `^[a-z][a-z0-9_]*$`. |
| `warnings[].message` **required** | string | Plain-language explanation. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Standing limitations of the source, and the assumptions behind any `assumed` value. Always present. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | Data sources behind the published values, with their licence and attribution text. Always present; show them with the data. |
| `usage` | object | Billing for this call. |
| `usage.billable` **required** | boolean | `true` when this lookup captured a credit. |
| `usage.credits_used` **required** | integer | Credits this call consumed (0 or 1). 0 to 1. |
| `usage.original_credits_used` **required** | integer | The same as `credits_used`: lookups are never replayed. 0 to 1. |
| `usage.charges` **required** | object | What `credits_used` paid for. Empty when nothing was charged. |
| `usage.charges.base` | integer | The lookup itself, 1 credit. Minimum 1. |
| `usage.credits_remaining` **required** | integer | Workspace credits left after this call. Minimum 0. |
| `usage.cache_hit` **required** | boolean | `true` when the answer came from AutoUncle's lookup cache. Cached answers are billed like fresh ones. |
| `usage.idempotent_replay` **required** | boolean | Always false: lookups are not replayed. |
| `usage.mode` **required** | string | `test` or `live`. One of `live`, `test`. |

#### Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The HTTP request ID, on every response. Use it to correlate one HTTP exchange in proxy and application logs; it echoes a valid X-Request-Id you send. It is not the valuation ID. |
| `X-Lookup-Id` | The vehicle lookup's ID (`lkp_…`), the same value as the body's `request_id`. Present on every lookup that was started, including failed ones. Use it in the console request log and with support. Lookup results are not stored, so it cannot be read back. |

#### Errors

| Code | HTTP | Retryable | Meaning |
| --- | --- | --- | --- |
| [`invalid_request`](https://data-services.autouncle.com/docs/errors#invalid_request) | 400 | No | Send a request matching the documented schema. |
| [`unsupported_country`](https://data-services.autouncle.com/docs/errors#unsupported_country) | 400 | No | Choose a supported ISO country code. |
| [`lookup_country_unsupported`](https://data-services.autouncle.com/docs/errors#lookup_country_unsupported) | 422 | No | Registration-plate lookups are not available for this country. |
| [`unauthenticated`](https://data-services.autouncle.com/docs/errors#unauthenticated) | 401 | No | Supply an API key as a Bearer token. |
| [`invalid_api_key`](https://data-services.autouncle.com/docs/errors#invalid_api_key) | 401 | No | Supply a valid AutoUncle Data Services API key. |
| [`key_revoked`](https://data-services.autouncle.com/docs/errors#key_revoked) | 401 | No | This key has expired or been revoked. Create a new key. |
| [`insufficient_credits`](https://data-services.autouncle.com/docs/errors#insufficient_credits) | 402 | No | The organization has no credits available. Contact sales for a package. |
| [`key_spend_limit_reached`](https://data-services.autouncle.com/docs/errors#key_spend_limit_reached) | 402 | No | This API key has reached its monthly credit limit. |
| [`insufficient_scope`](https://data-services.autouncle.com/docs/errors#insufficient_scope) | 403 | No | Use a key with the required scope. |
| [`country_not_enabled`](https://data-services.autouncle.com/docs/errors#country_not_enabled) | 403 | No | This country is not enabled for this organization or key. |
| [`organization_pending`](https://data-services.autouncle.com/docs/errors#organization_pending) | 403 | No | This workspace is waiting for AutoUncle to approve it. |
| [`organization_suspended`](https://data-services.autouncle.com/docs/errors#organization_suspended) | 403 | No | This organization is inactive. Contact support. |
| [`payload_too_large`](https://data-services.autouncle.com/docs/errors#payload_too_large) | 413 | No | The request exceeds the maximum supported size of 1 MB. |
| [`rate_limited`](https://data-services.autouncle.com/docs/errors#rate_limited) | 429 | Yes | The request rate limit was reached. Retry after the current minute. |
| [`test_limit_reached`](https://data-services.autouncle.com/docs/errors#test_limit_reached) | 429 | Yes | This workspace has used its fair-use allowance of test-key requests for now. |
| [`rate_limit_unavailable`](https://data-services.autouncle.com/docs/errors#rate_limit_unavailable) | 503 | Yes | Request limiting is temporarily unavailable. Retry later. |
| [`lookup_unavailable`](https://data-services.autouncle.com/docs/errors#lookup_unavailable) | 503 | Yes | The vehicle lookup service is temporarily unavailable. |
| [`lookup_timeout`](https://data-services.autouncle.com/docs/errors#lookup_timeout) | 504 | Yes | The vehicle lookup service did not respond within its time budget. |
| [`internal_error`](https://data-services.autouncle.com/docs/errors#internal_error) | 500 | No | The valuation could not be completed. Contact support with the request ID. |

## Valuation result fields

| Field | Type | Description |
| --- | --- | --- |
| `request_id` | string | Valuation ID (`val_…`, or `stf_…` for a selling-time forecast), also sent in the `X-Valuation-Id` response header. Use it with GET /v1/valuations/{id}, in the console request log and when you contact support. It is not the `X-Request-Id` header, which is the HTTP request ID. Pattern `^(val\|stf)_[A-Za-z0-9]+$`. |
| `object` | string | Always `valuation`. |
| `status` | string | `valued` when a price was produced, `refused` when the input cannot be valued as sent (fix the input), `failed` when a service failed (retry later). Only `valued` live results are billed. One of `valued`, `refused`, `failed`. |
| `country` | string | Valuation market as an ISO 3166-1 alpha-2 code, normalized from your request (for example `DK`). Pattern `^[A-Z]{2}$`. |
| `mode` | string | `test` for a test key (simulated result) or `live` for a live key. One of `live`, `test`. |
| `vehicle` | [Vehicle](https://data-services.autouncle.com/docs/reference/vehicles#the-vehicle-object) | The vehicle the valuation used, identified against the AutoUncle catalogue, as an AVS vehicle document; provenance per value is in `identification.fields`. Present when `status` is `valued` and the vehicle is identified to a brand and a model. |
| `identification` | [VehicleIdentification](https://data-services.autouncle.com/docs/reference/vehicles#identification) | How the vehicle was identified: status, depth, candidates and the provenance of every value in `vehicle`. |
| `valuation` | object | The estimate. Present only when `status` is `valued`. |
| `valuation.price` **required** | number | Point estimate in `currency`, for the stated `price_basis`. |
| `valuation.currency` **required** | string | ISO 4217 currency of the market, for example `DKK`, `SEK`, `EUR` or `GBP`. Pattern `^[A-Z]{3}$`. |
| `valuation.price_basis` **required** | string | `dealer_retail` or `private_sale`. Always read the price together with its basis. One of `dealer_retail`, `private_sale`. |
| `valuation.price_basis_description` **required** | string | Plain-language description of the price basis, suitable for display. |
| `valuation.intervals` **required** | array | Uncertainty intervals around the estimate, one per coverage level (currently 0.8, 0.95 and 0.99). |
| `valuation.intervals[].coverage` **required** | number | Intended share of comparable vehicles whose market price falls inside the interval, for example 0.8. |
| `valuation.intervals[].low` **required** | number | Lower bound in `currency`. |
| `valuation.intervals[].high` **required** | number | Upper bound in `currency`. |
| `valuation.intervals[].method` **required** | string | How the interval was produced. `calibrated` when it is calibrated against observed market outcomes, `estimated` otherwise; test results use `synthetic`. |
| `valuation.valuation_date` **required** | string (date) | Date the estimate applies to (YYYY-MM-DD). |
| `precision` | object | How much to rely on this result. See the precision guide. |
| `precision.grade` **required** | string | `high`, `medium`, `low` or `indicative`. Test results are always `indicative`. One of `high`, `medium`, `low`, `indicative`. |
| `precision.summary` **required** | string | Plain-language summary of the grade, suitable for display. |
| `precision.identity_level` **required** | string | Most specific catalogue level that was resolved, for example `generation` or `drivetrain`. |
| `precision.interval_width_pct` **required** | number or null | Width of the 80% interval as a percentage of the price, or null. Minimum 0. |
| `precision.data_support` **required** | object | How much comparable market data stands behind the estimate. `comparable_vehicles` is a lower bound (0, 10, 30, 100, 300, 1000, 3000 or 10000), not an exact count. Empty for test results. |
| `precision.typical_error_pct` **required** | number or null | Typical error of comparable estimates as a percentage, or null when not available. Minimum 0. |
| `price_ratings` | object | AutoUncle's five price-rating bands for this vehicle, and the rating of your asking price. |
| `price_ratings.bands` **required** | array | Exactly five bands, from rating 5 (Super price) to 1 (Expensive). At most 5 items. |
| `price_ratings.bands[].rating` **required** | integer | Rating from 5 (best price for a buyer) to 1. 1 to 5. |
| `price_ratings.bands[].label` **required** | string | Display label, for example `Good price`. |
| `price_ratings.bands[].from` **required** | number | Lower price bound of the band in `currency`. Minimum 0. |
| `price_ratings.bands[].to` **required** | number | Upper price bound of the band in `currency`. Minimum 0. |
| `price_ratings.asking_price_rating` **required** | integer or null | Rating of `pricing.asking_price` from 1 to 5, or null when you did not send an asking price. 0 to 5. |
| `price_ratings.asking_price_label` **required** | string or null | Label of that rating, or null. |
| `price_ratings.stable_within_80pct_interval` **required** | boolean or null | `true` when the asking-price rating stays the same anywhere in the 80% interval, `false` when it could change; null without an asking price. |
| `comparables` | object | Comparable listings in the valuation market, as supporting evidence. Present on a `valued` result when `options.include` contains `comparables`. They are looked up after scoring and never change the valuation. At most five on sale and five recently sold, with top-level facts only; no seller details, listing text, plates, VINs, images, dates or links. |
| `comparables.status` **required** | string | `included` when at least one listing is returned, `none_found` when no listing matched the criteria, `unavailable` when comparables cannot be provided (see `unavailable_reason`). One of `included`, `none_found`, `unavailable`. |
| `comparables.unavailable_reason` **required** | string or null | `market_restricted` when the market's listing-data agreements do not allow passing listings on (Denmark; a `comparables_unavailable_in_market` note says so), `temporarily_unavailable` when the lookup failed or ran out of time (with a `comparables_unavailable` warning; request again). Null otherwise. One of `market_restricted`, `temporarily_unavailable`. |
| `comparables.synthetic` **required** | boolean | `true` for test keys: fixed examples around the simulated price, not market listings. |
| `comparables.criteria` **required** | object or null | What every listing had to match. Null when `status` is `unavailable`. |
| `comparables.criteria.make` **required** | string | Make of the valued vehicle. |
| `comparables.criteria.model` **required** | string | Model of the valued vehicle. |
| `comparables.criteria.model_year` **required** | object or null | Model year range, inclusive. |
| `comparables.criteria.model_year.from` **required** | integer or null | Earliest model year. |
| `comparables.criteria.model_year.to` **required** | integer or null | Latest model year. |
| `comparables.criteria.mileage` **required** | object or null | Mileage range, inclusive, or null when mileage was not limited. |
| `comparables.criteria.mileage.from` **required** | integer or null | Lowest mileage. |
| `comparables.criteria.mileage.to` **required** | integer or null | Highest mileage. |
| `comparables.criteria.mileage.unit` **required** | string | The market's mileage unit. One of `km`, `mi`, `mil`. |
| `comparables.criteria.fuel` **required** | string or null | Required fuel, or null when not limited. One of `petrol`, `diesel`, `electric`, `hybrid`, `plug_in_hybrid_petrol`, `plug_in_hybrid_diesel`, `lpg`, `cng`, `ethanol`, `hydrogen`. |
| `comparables.criteria.transmission` **required** | string or null | Required transmission, or null when not limited. Only a known automatic or manual gearbox limits it. One of `manual`, `automatic`. |
| `comparables.criteria.body` **required** | string or null | Required body type, or null when not limited. One of `hatchback`, `estate`, `suv`, `sedan`, `mpv`, `convertible`, `coupe`. |
| `comparables.criteria.engine_size_l` **required** | number or null | Required engine displacement in litres, or null when not limited. |
| `comparables.criteria.sold_within_days` **required** | integer | How recently a `recently_sold` listing left the market, in days. Minimum 1. |
| `comparables.on_sale` **required** | [ComparableListing](https://data-services.autouncle.com/docs/reference/valuations#comparable-listings) array | Up to five listings on sale now, most typical price rating first, then nearest model year and mileage. At most 5 items. |
| `comparables.recently_sold` **required** | [ComparableListing](https://data-services.autouncle.com/docs/reference/valuations#comparable-listings) array | Up to five listings that left the market within `criteria.sold_within_days`, in the same order. AutoUncle treats a listing that left the market as sold; its price is the last asking price. At most 5 items. |
| `trade_in_price` | object | AutoUncle's estimate of a fair price for a dealer to pay when taking the vehicle in trade, with a range. Present on a `valued` result when `options.include` contains `trade_in_price`. It is an estimate, not an offer, and it relates to the vehicle's dealer retail market value whatever `pricing.price_basis` the valuation uses. Looked up after scoring; it never changes the valuation. |
| `trade_in_price.status` **required** | string | `included` when a trade-in price is returned, `unavailable` when it cannot be provided (see `unavailable_reason`). One of `included`, `unavailable`. |
| `trade_in_price.unavailable_reason` **required** | string or null | `market_unsupported` in a market without trade-in prices (any market outside AT, CH, DE, DK, ES, FR, GB, IT, NL, PL, PT and SE, such as FI, RO and BE; a `trade_in_price_unavailable_in_market` note says so), `temporarily_unavailable` when it could not be calculated for this request (with a `trade_in_price_unavailable` warning; request again). Null otherwise. One of `market_unsupported`, `temporarily_unavailable`. |
| `trade_in_price.synthetic` **required** | boolean | `true` for test keys: a fixed example derived from the simulated price, not a trade-in estimate. |
| `trade_in_price.price` **required** | integer or null | Estimated fair trade-in price in `currency`, rounded. Null when `status` is `unavailable`. |
| `trade_in_price.low` **required** | integer or null | Lower end of the trade-in range in `currency`. Null when `status` is `unavailable`. |
| `trade_in_price.high` **required** | integer or null | Upper end of the trade-in range in `currency`. Null when `status` is `unavailable`. |
| `trade_in_price.currency` **required** | string | ISO 4217 currency of the market. Pattern `^[A-Z]{3}$`. |
| `similar_cars_url` | string or null (uri) | Link to cars similar to the valued vehicle for sale on the market's own AutoUncle site (autouncle.<country domain>), in the market's language. Present on a `valued` result when `options.include` contains `similar_cars_link`; null when the link could not be built (a `similar_cars_link_unavailable` warning says so). Free. |
| `selling_time` | object | The selling-time forecast. Present only on `valued` results of POST /v1/selling-times: how long the vehicle is expected to take to sell if listed now and its asking price is kept. See [selling-time forecasts](https://data-services.autouncle.com/docs/selling-time). |
| `improve_precision` | array | Specific inputs that would make the result more precise, most useful first. |
| `improve_precision[].field` **required** | string | Request field to supply, for example `vehicle.catalogue.drivetrain_id` or `vehicle.condition`. |
| `improve_precision[].reason` **required** | string | Machine-readable reason, for example `drivetrain_unresolved`, `condition_unknown`, `imputed` or `ai_interpreted`. |
| `improve_precision[].expected_impact` **required** | string | `high`, `medium` or `low`: qualitative, not a promise that the price or interval will change by a fixed amount. One of `high`, `medium`, `low`. |
| `improve_precision[].message` **required** | string | Plain-language hint, suitable for display. |
| `improve_precision[].candidates` | array | Catalogue candidates to choose from, when the hint is about an ambiguous identity. |
| `improve_precision[].candidates[].id` **required** | string | Catalogue ID of the candidate. |
| `improve_precision[].candidates[].name` **required** | string | Catalogue name of the candidate. |
| `improve_precision[].candidates[].source` **required** | string | How the candidate was found. One of `provided`, `catalogue_id`, `catalogue_derived`, `text_parser`, `registry`, `catalogue_match`, `ai_text`, `ai_vision`, `imputed`, `default`. |
| `improve_precision[].candidates[].basis` | string | How the value was established: observed (supplied by the caller or read from a registry record), extracted (parsed or automatically interpreted from supplied text or photos), catalogue (deterministically derived from or matched against the AutoUncle catalogue) or assumed (a heuristic default or fixed baseline, not evidence about this vehicle). One of `observed`, `extracted`, `catalogue`, `assumed`. |
| `improve_precision[].candidates[].match_score` | number | Match strength from 0 to 1. |
| `improve_precision[].candidates[].ambiguous` | boolean | Whether the candidate itself is ambiguous. |
| `improve_precision[].candidates[].candidate_count` | integer | Number of fitting entries when ambiguous. Minimum 2. |
| `warnings` | array | Problems with this request's input or its optional sections, for example `generation_ambiguous`, `equipment_not_recognized`, `flags_not_recognized`, `flags_not_applicable`, `images_not_used`, `km_imputed`, `registry_conflict`, `vehicle_input_overridden`, `comparables_unavailable`, `trade_in_price_unavailable` or `similar_cars_link_unavailable`. Match on `code`. |
| `warnings[].code` **required** | string | Stable machine-readable warning code. Pattern `^[a-z][a-z0-9_]*$`. |
| `warnings[].message` **required** | string | Plain-language explanation. |
| `model` | object | The public identity of the model that produced the result. Present when the request was scored. |
| `model.model_id` **required** | string | Opaque identifier of the model release, stable for one release and different for the next (for example `dk-3f9a1c0b7e2d`). Test results use `sandbox-v1`. |
| `model.trained_on` **required** | string or null (date-time) | When the model was trained (ISO 8601), or null. |
| `model.catalogue_version` **required** | string or null | Catalogue version the model was built against, or null. |
| `model.synthetic` **required** | boolean | `true` for simulated test-mode results. |
| `usage` | object | Billing for this call. Present on POST responses; GET read-backs omit it. |
| `usage.billable` **required** | boolean | `true` when this valuation captured a credit. |
| `usage.credits_used` **required** | integer | Credits this call consumed. Always 0 on an idempotent replay. 0 to 4. |
| `usage.original_credits_used` **required** | integer | Credits the original valuation consumed (0, 1, or more with add-ons for comparables, a trade-in price, photos or a selling-time forecast), also on a replay. 0 to 4. |
| `usage.charges` **required** | object | What `original_credits_used` paid for. Empty when nothing was charged (test keys, refused and failed valuations). |
| `usage.charges.base` | integer | The valuation itself, 1 credit. Minimum 1. |
| `usage.charges.comparables` | integer | Comparable listings, 1 credit. Only when they were requested and returned with `comparables.status` `included`. Minimum 1. |
| `usage.charges.images` | integer | Image processing, 1 credit per request. Only when photos were sent and a value in `identification.fields` was read from them. Minimum 1. |
| `usage.charges.selling_time` | integer | The selling-time forecast of POST /v1/selling-times, 1 credit. Only on a `valued` result, which always carries the forecast. Minimum 1. |
| `usage.charges.trade_in_price` | integer | Trade-in price, 1 credit. Only when it was requested and returned with `trade_in_price.status` `included`. Minimum 1. |
| `usage.credits_remaining` **required** | integer | Workspace credits left after this call. Minimum 0. |
| `usage.cache_hit` **required** | boolean | Reserved. Always false in this version. |
| `usage.idempotent_replay` **required** | boolean | `true` when this response replays an earlier recorded outcome for the same Idempotency-Key and body. |
| `usage.mode` **required** | string | `test` or `live`. One of `live`, `test`. |
| `error` | [Problem](https://data-services.autouncle.com/docs/reference/valuations#the-problem-object) | The error for a `refused` or `failed` valuation, in the same Problem format as request errors. |
| `notes` | [Note](https://data-services.autouncle.com/docs/notices#notes) array | Standing limitations, disclaimers and legal notices. Always present. |
| `attributions` | [Attribution](https://data-services.autouncle.com/docs/notices#attributions) array | Data sources that contributed to this result. Always present. |

## Vehicle

An [AutoUncle Vehicle Schema (AVS)](https://github.com/AutoUncle/avs) 0.3 `vehicle` document. The [AVS specification](https://github.com/AutoUncle/avs) describes every field.

| Block | Type | Description |
| --- | --- | --- |
| `avs` **required** | object | Document metadata. Always `version` `0.3` and `kind` `vehicle`. |
| `identity` **required** | object | Where the car sits in the catalogue: brand → series → model → generation → phase → body → drivetrain, plus the configuration that pairs a body with a drivetrain. Generation, body and drivetrain are independent facts: one drivetrain is shared by every body it was sold in. Only brand and model are required; levels that are not known are left out. `brand` and `model` always; `body` (AutoUncle's generation, which includes the body, with its `type`, `fromYear` and `toYear`) and `drivetrain` when they are identified. Each level carries its AutoUncle catalogue ID as `ids[{scheme: "autouncle"}]`; an unidentified vehicle has the names as stated, without IDs. |
| `specification` | object | Technical facts about the car type. Units are always in the field name (kW, Nm, mm, kg, kWh, g/km) so there is never a unit field to look up. `body` (`type`, `doors`, `seats`, `driveSide`) and `powertrain` (`energy`, `electrification`, `engine.displacementCc`, `powerHp`, `powerKw`, `transmission.type`, `traction`). With an identified drivetrain these are the catalogue's values. |
| `equipment` | object | What the car is equipped with. A trim, package or option is identified by its NAME; that is what buyers, adverts and valuation use, and a name alone is enough to price it. Its contents are described separately as `features`. Absence is only known when stated (`fitted: false` / `availability: absent`); a missing entry means unknown. `trim`, the equipment variant (`fitted: true`), and `features[]` with `key`, `name`, `ids`, `category` and `availability`: `fitted`, or `unknown` for equipment assumed with `allow_equipment_estimation`. |
| `vehicle` | object | One physical car. Everything here can differ between two cars of the same drivetrain. `vin`, `registration` (`plate`, `country`, `firstRegistrationDate`, `modelYear`, `originalCountry`, `isImported`), `odometer` (`km`, and `readAt` for a register's reading) and `colour` (`name`, `family`). |
| `extensions` | object | Vendor-specific data that has no AVS field yet. Keys are reverse-DNS namespaces, e.g. `com.autouncle`, `de.mobile`. `com.autouncle` holds what AVS has no field for yet: `battery_kwh` (gross or usable not known), `electric_range_km` (test cycle not known), `doors` above 6, `seats` above 9, `production_year`, `first_registration` without a full date, `hsn`, `tsn`, `condition_grade` (0 to 4) and `variant_text`. |

## Vehicle identification fields

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | identified: the catalogue drivetrain is known. partially_identified: identity stops at the brand, model or generation and nothing competes. ambiguous: several catalogue records fit at some level; that level is left out of identity and listed in candidates. unidentified: the catalogue does not know the make; the vehicle carries the brand and model names as stated, without IDs. One of `identified`, `partially_identified`, `ambiguous`, `unidentified`. |
| `level` | string | The deepest catalogue level identified. `generation` is AutoUncle's generation-with-body, published as AVS `identity.body`. One of `brand`, `model`, `generation`, `drivetrain`. |
| `catalogue_version` | string | The catalogue release that identified the vehicle, as GET /v1/catalogue/version reports it. |
| `candidates` | object | Catalogue records that fit when a level is ambiguous, at most ten per level; `fields./identity/body.candidate_count` or `fields./identity/drivetrain.candidate_count` has the total. Left out when nothing is ambiguous. |
| `candidates.generation` | [VehicleCandidate](https://data-services.autouncle.com/docs/reference/vehicles#candidates) array | Generations that fit, oldest first. At most 10 items. |
| `candidates.drivetrain` | [VehicleCandidate](https://data-services.autouncle.com/docs/reference/vehicles#candidates) array | Drivetrains of the identified generation that fit, closest to the supplied power first. At most 10 items. |
| `fields` | object | Provenance per value, keyed by JSON Pointer into `vehicle`, such as `/specification/powertrain/powerHp`, `/identity/drivetrain` or `/vehicle/odometer`. A value without provenance here was not stated by anyone; an ambiguous level appears without a value. |

## Problem fields

| Field | Type | Description |
| --- | --- | --- |
| `type` | string | URL of this error code's entry in the error reference. At most 200 characters. |
| `title` | string | Short human-readable title derived from the code. At most 200 characters. |
| `status` | integer | HTTP status code. |
| `code` | string | Stable machine-readable error code. Match on this, never on `detail`. At most 200 characters. |
| `detail` | string | Human-readable explanation. Wording can change; do not parse it. At most 2000 characters. |
| `request_id` | string or null | Request ID to share with support. A `val_…` ID when a valuation was recorded, otherwise the HTTP request ID. |
| `billable` | falseclass | Always false. Errors never consume credits. |
| `errors` | array | Affected request fields, when known. |
| `errors[].pointer` **required** | string | JSON Pointer (RFC 6901) into your request, for example `/vehicle/mileage/value`. |
| `errors[].message` **required** | string | What is wrong with that field. |
| `fix` | array | Actionable recovery steps, including replay guidance when relevant. |
| `docs_url` | string | Link to the error reference. At most 200 characters. |
| `retryable` | boolean | Whether retrying after the documented recovery steps may succeed. Follow fix for waiting, input changes and idempotency-key/replay semantics. |
| `service` | string | Safe public service identifier, never a private hostname or provider response. |
| `reason` | string | Safe enumerated domain refusal reason when known. |
| `retry_after` | integer | Seconds to wait before retrying, when known. Equals the Retry-After header on REST and is the only retry delay over MCP, which has no response headers. Minimum 1. |
