---
title: "Vehicle details"
description: "Fetch a full source payload from cache or, when needed, from the upstream source."
canonical: "https://thecarapi.com/docs/car-details"
contract_version: "2026-08-19"
api_base: "https://api.thecarapi.com"
source: "https://thecarapi.com/docs/car-details.md"
---

# Vehicle details

Fetch a full source payload from cache or, when needed, from the upstream source.

## GET | POST /api/car-details

Fetch full vehicle detail by source and listing identifier.

**Scope:** `details`

### Parameters

| Parameter | Send in | Type | Required | Example | Where the value comes from | Description |
| --- | --- | --- | --- | --- | --- | --- |
| `site` | Query or JSON body | string | yes | `encar` | /api/sites -> sites[].name | schadeautos, auto1, openlane, copart, encar, ecarstrade, or japanauction. |
| `id / link / identifier` | Query or JSON body | string | yes | `38112900` | /api/search -> results[].auction_id, or the source listing URL | Provide any one source id or listing URL. For auto1 and japanauction this is the offer id/UUID, not the numeric auction id. |
| `search_id` | Query or JSON body | string | no | `vehicle-page-42` | Optional correlation id generated by your application. | Optional correlation id. |

### Example requests

```http
GET | POST https://api.thecarapi.com/api/car-details?site=encar&id=38112900
```

```http
POST https://api.thecarapi.com/api/car-details
{
  "site": "openlane",
  "identifier": "11125938",
  "search_id": "vehicle-page-42"
}
```

### Example response

```json
{
  "success": true,
  "site": "openlane",
  "auction_id": 11409652,
  "current_price": 25900,
  "current_final": 33566,
  "public_price_eur": 33926,
  "vehicle_details": {},
  "auction": {
    "extracted_fields": {
      "images": []
    }
  },
  "live_price": {
    "price": 25900,
    "currency": "EUR",
    "source": "openlane",
    "fetched_at": 1786659750
  }
}
```

### Response fields

| Field | Type | Meaning |
| --- | --- | --- |
| `vehicle_details` | object \| null | The same normalized block /api/auction/{site}/{id} returns, so the two detail endpoints agree. Null when the listing has no fetched details yet. This is the only part of the response with a stable cross-source contract — the remaining keys are source-shaped (data, auction, images, details depending on the source). |
| `details_pending` | boolean | True while the upstream fetch is still running. Poll rather than retrying in a tight loop; X-Details-Fetch carries the same signal in the headers. |
| `current_price / current_final / public_price_eur` | number | The same price fields as /api/auction/{site}/{id}, under the same names and with the same JSON types — but at the top level here, because this body is source-shaped and has no auction wrapper. The two detail endpoints therefore cannot disagree about what a car costs. |
| `live_price / live_price_pending` | object \| boolean | Identical contract to /api/auction/{site}/{id}, and attached the same way when this response is served from stored auction data — the normal case. A first-ever fetch of a listing we hold no row for returns the source’s own fresh payload anyway. |
| `auction` | object | Not the vehicle record. For openlane this is { extracted_fields: { images: […] } }, an image container that shares a name and nothing else. Read prices from the top level on this endpoint, and from inside auction on /api/auction/{site}/{id}. |
| `estimated_value_eur` | number \| null | Same field and same meaning as on /api/auction/{site}/{id}, at the top level here. The auction house own valuation — not a price you can pay, ecarstrade only, null everywhere else. |
| `steering` | enum \| null | Same derivation and spelling as the search cards and /api/auction/{site}/{id}. Null only when the vehicle is not in our inventory at all, because there is then no registration country to derive a side from. On the paths that fetch straight from the source, deriving it is advisory — a failure to compute it is swallowed rather than turning a working detail response into an error, so its absence there does not mean the lookup failed. |

**Notes.** Parameters may be sent in the query string or a JSON body. This endpoint can be slower than canonical auction detail. Fee, transport, delivery and account-scoped fields are stripped here exactly as they are on auction detail. When no details are stored yet it fetches from the source during the request — read details_pending in the body and X-Details-Fetch in the headers, and poll rather than retrying in a tight loop. Live prices apply here too when the response comes from stored auction data; note the one trap that catches people — this body’s auction key is an image container, not the vehicle record, so prices are read from the top level.

## GET | POST /api/listVehicles

Catalog-shaped listing feed — a compatibility alias for search.

**Scope:** `details`

### Parameters

| Parameter | Send in | Type | Required | Example | Where the value comes from | Description |
| --- | --- | --- | --- | --- | --- | --- |
| `manufacturer_slug / manufacturer / brand` | Query or JSON body | string | no | `bmw` | /api/catalog/manufacturers -> results[].slug | Brand, under any of the three accepted spellings. |
| `model_group_slug / model_group / model` | Query or JSON body | string | no | `320d` | /api/catalog/model-groups?manufacturer__slug=bmw -> results[].slug | Model group, under any of the three accepted spellings. |
| `fuel_type / fuel` | Query or JSON body | string | no | `Diesel` | /api/fuels -> fuels[] | Canonical fuel group. |
| `steering` | Query or JSON body | enum | no | `left` | left \| lhd \| right \| rhd — any other value is a 400. | Left- or right-hand drive. |
| `min_year / max_year` | Query or JSON body | integer | no | `2018 / 2024` | Year bounds chosen by your user. | Registration-year range. |
| `max_mileage` | Query or JSON body | integer | no | `120000` | Mileage ceiling chosen by your user. | Mileage ceiling. |
| `ordering` | Query or JSON body | string | no | `-created_at` | One of -created_at, price, -price, year, -year. | Sort order. A leading minus reverses it. |
| `limit / offset` | Query or JSON body | integer | no | `50 / 0` | Pagination state in your application. | Or page_size / page. Default limit 50. |

### Example requests

```http
GET | POST https://api.thecarapi.com/api/listVehicles?manufacturer_slug=bmw&model_group_slug=320d&max_mileage=120000
```

```http
GET | POST https://api.thecarapi.com/api/listVehicles?brand=audi&min_year=2019&ordering=price&limit=50
```

### Example response

```json
{
  "success": true,
  "vehicles": [],
  "results": [],
  "total": 210,
  "limit": 50,
  "offset": 0,
  "total_pages": 5,
  "max_page": 5
}
```

### Response fields

| Field | Type | Meaning |
| --- | --- | --- |
| `vehicles / results` | object[] | The same array under two keys, so either spelling works. Cards are augmented search result cards. |
| `total / limit / offset / total_pages / max_page` | integer \| null | Standard pagination fields, exactly as on /api/search. |

**Notes.** A compatibility alias kept for older integrations, also reachable at /listVehicles. It takes catalog-shaped parameter names and returns the same cards /api/search does. For anything new, use /api/search — it has the full filter surface, ETags and the deeper paging policy, and this route does not.
