contract 2026-09-03
Endpoints

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.

Requires the details scope.

Parameters

sitestring · query string or JSON bodyrequired

schadeautos, auto1, openlane, copart, encar, kbchachacha, or ecarstrade. Japan has stored auction detail only and is rejected here.

Example encar·Where the value comes from /api/sites -> sites[].name

id / link / identifierstring · query string or JSON bodyrequired

Provide any one source id or listing URL. For auto1 use the source offer identifier. KB ChaChaCha requires numeric carSeq. For Japan use the stored auction detail endpoint instead.

Example 38112900·Where the value comes from /api/search -> results[].auction_id, or the source listing URL

search_idstring · query string or JSON body

Optional correlation id.

Example vehicle-page-42·Where the value comes from Optional correlation id generated by your application.

Example requests

Request
GET | POST https://api.thecarapi.com/api/car-details?site=encar&id=38112900
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
  }
}

What you get back

vehicle_detailsobject | 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_pendingboolean

True while the upstream fetch is still running — a fetch that outran the request time budget keeps running in the background. Poll rather than retrying in a tight loop. The X-Details-Fetch header carries the same signal as fetched, pending or miss, and is absent when the response was served from stored data. Cache-Control is max-age=5 while pending and max-age=60 once settled.

current_price / current_final / public_price_eurnumber

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. Updates between separate requests can change prices; compare listing timestamps and live_price.fetched_at.

live_price / live_price_pendingobject | 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, for a running openlane or ecarstrade auction. A first-ever fetch of a listing we hold no row for returns the source’s own fresh payload anyway.

auctionobject

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_eurnumber | 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.

steeringenum | null

Same derivation and spelling as the search cards and /api/auction/{site}/{id}, published at the top level here. Null only when the vehicle is not in our inventory at all, because there is then no registration country to derive a side from.

GET | POST

/api/listVehicles

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

Requires the details scope.

Parameters

page / page_sizeinteger · query string or JSON body

1-based page and rows per page, as alternatives to offset and limit. Do not combine page with offset or page_size with limit.

Example 1 / 50·Where the value comes from Pagination state in your application.

manufacturer_slug / manufacturer / brandstring · query string or JSON body

Brand, under any of the three accepted spellings.

Example bmw·Where the value comes from /api/catalog/manufacturers -> results[].slug

model_group_slug / model_group / modelstring · query string or JSON body

Model group, under any of the three accepted spellings.

Example 320d·Where the value comes from /api/catalog/model-groups?manufacturer__slug=bmw -> results[].slug

fuel_type / fuelstring · query string or JSON body

Canonical fuel group.

Example Diesel·Where the value comes from /api/fuels -> fuels[]

steeringenum · query string or JSON body

Left- or right-hand drive, in any of the spellings /api/search accepts.

Example left·Where the value comes from left | lhd | left-hand | left_hand, or right | rhd | right-hand | right_hand — any other value is a 400.

min_year / max_yearinteger · query string or JSON body

Registration-year range.

Example 2018 / 2024·Where the value comes from Year bounds chosen by your user.

max_mileageinteger · query string or JSON body

Mileage ceiling.

Example 120000·Where the value comes from Mileage ceiling chosen by your user.

orderingstring · query string or JSON body

Sort order. An unrecognised value silently falls back to the default (photo-first, then newest) rather than erroring.

Example -created_at·Where the value comes from created_at / created / published_at, price / price_eur, year / date_first_registration, each with an optional leading minus.

limit / offsetinteger · query string or JSON body

Or page_size / page. Default limit 50. No offset cap.

Example 50 / 0·Where the value comes from Pagination state in your application.

Example requests

Request
GET | POST https://api.thecarapi.com/api/listVehicles?manufacturer_slug=bmw&model_group_slug=320d&max_mileage=120000
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
}

What you get back

vehicles / resultsobject[]

The same array object served twice under two names for compatibility. Read either one, not both. Each row is a standard search result card plus four catalog-shaped keys: vehicle_id (the same value as auction_id — subject to the same 2^53 caveat, prefer auction_id_str), manufacturer_slug (slug of clean_make), model_group_slug (slug of clean_model), and fuel_type (normalized fuel, present only when the row carries one). Rows carry the same 8-photo images preview cap as /api/search.

total / limit / offset / page / page_size / total_pages / max_pageinteger | null

Standard pagination fields. There is no offset cap — max_page equals total_pages, as on /api/search. Default limit 50.