---
title: "Search & discovery"
description: "Search live and archived auction inventory, then resolve lightweight full-text matches."
canonical: "https://thecarapi.com/docs/search"
contract_version: "2026-08-19"
api_base: "https://api.thecarapi.com"
source: "https://thecarapi.com/docs/search.md"
---

# Search & discovery

Search live and archived auction inventory, then resolve lightweight full-text matches.

## GET /api/search

Primary filtered search over live auction inventory.

**Scope:** `search`

### Parameters

| Parameter | Send in | Type | Required | Example | Where the value comes from | Description |
| --- | --- | --- | --- | --- | --- | --- |
| `search` | Query string | string | no | `BMW 320d` | Free text entered by your user. | Free-text brand, model, or keyword query. |
| `site` | Query string | string | no | `encar` | /api/sites -> sites[].name | Comma-separated source slugs, OR within the parameter. Case-insensitive. An unknown slug is a 400 naming the offender — one bad member rejects the whole list. |
| `site_exclude` | Query string | string | no | `copart` | /api/sites -> sites[].name | Comma-separated source slugs to leave out. Sent alongside site, it narrows the include list; excluding everything you included is a 400, not an empty page. |
| `brand` | Query string | string \| integer | no | `bmw` | /api/brands -> brands[].slug (or id/name) | Brand display name, slug, or brand_id. |
| `model` | Query string | string | no | `320d` | /api/models?brand=bmw -> models[].slug | Model name or slug. |
| `year_from / year_to` | Query string | integer | no | `2018 / 2024` | /api/years -> years[] | Registration-year range. |
| `fuel` | Query string | string | no | `Diesel` | /api/fuels -> fuels[] | Canonical fuel group, matched whole. Hybrid, Mild Hybrid and Plug-in Hybrid are three separate groups — fuel=Hybrid returns full hybrids only. A lot with no recorded fuel matches every fuel filter rather than none, so it stays reachable. |
| `gearbox` | Query string | string | no | `Automatic` | /api/gearboxes -> gearboxes[] | Canonical gearbox group. |
| `country` | Query string | string | no | `DE` | /api/countries -> country_details[].code | ISO country code or europe. |
| `vehicle_type` | Query string | string | no | `cars` | Choose from the documented vehicle_type enum. | cars or suvs & trucks. |
| `body_style` | Query string | string | no | `sedan` | Your application's normalized body-style value. | Body-style filter. |
| `steering` | Query string | enum | no | `left` | left \| lhd \| right \| rhd — any other value is a 400. | Left- or right-hand drive. left/lhd and right/rhd are equivalent spellings. Every listing resolves to one side or the other, so the two values partition the inventory and their counts sum to the unfiltered total. |
| `kilometers_from / kilometers_to` | Query string | integer | no | `0 / 80000` | Mileage range chosen by your user. | Mileage range. |
| `horsepower_from / horsepower_to` | Query string | integer | no | `150 / 300` | Horsepower range chosen by your user. | Horsepower range. |
| `price_from / price_to` | Query string | integer | no | `10000 / 30000` | EUR budget chosen by your user. | Public EUR price range. |
| `damaged` | Query string | boolean | no | `true` | Your filter choice. | Return damaged or broken vehicles only. |
| `buy_now` | Query string | boolean | no | `true` | Your filter choice. | Return Buy-Now listings only. |
| `ending_soon` | Query string | boolean | no | `true` | Your filter choice. | Return auctions ending within about two hours. |
| `smart_filter` | Query string | enum | no | `best_value` | Choose from the documented smart_filter enum. | top_offers, low_mileage, or best_value. |
| `is_active` | Query string | boolean | no | `false` | Your filter choice. | Default true: lots whose auction has closed are hidden. false shows closed lots in addition to live ones — it does not return only ended lots, and it is not a filter on the is_active response field. |
| `include_ended` | Query string | boolean | no | `false` | Your filter choice. | The same switch inverted: include_ended=true equals is_active=false. Default false. If both are sent, include_ended wins. |
| `sort` | Query string | enum | no | `price_low` | Choose from the documented Sort enum. | Sort value from the conventions section. |
| `seed` | Query string | string | no | `k9f2ab` | Previous search response -> random_seed | Stable random seed, up to 64 URL-safe characters. |
| `limit / page_size` | Query string | integer | no | `24` | Page size chosen by your application. | Page size, maximum 100. Default 100. |
| `offset / page` | Query string | integer | no | `24 / 2` | Current page state in your application. | Offset-based or page-based pagination. |
| `include_total` | Query string | boolean | no | `false` | Your performance/display choice. | Set false to skip the count. Default true. |
| `count_only` | Query string | boolean | no | `true` | Your response-mode choice. | Return counts without result rows. |

### Example requests

```http
GET https://api.thecarapi.com/api/search?brand=bmw&fuel=Diesel&year_from=2018&sort=price_low&limit=24
```

```http
GET https://api.thecarapi.com/api/search?site=encar&country=KR&buy_now=true&page=2&page_size=20
```

### Example response

```json
{
  "success": true,
  "results": [
    {
      "auction_id": 38112900,
      "site_name": "encar",
      "clean_make": "BMW",
      "clean_model": "320d",
      "registration_year": 2020,
      "mileage": 45000,
      "public_price_eur": 21500,
      "thumbnail_url": "https://cdn.example/photo.webp"
    }
  ],
  "total": 18342,
  "limit": 24,
  "offset": 0,
  "total_pages": 764,
  "max_page": 764,
  "random_seed": "k9f2ab",
  "contract_version": "2026-08-19"
}
```

### Response fields

| Field | Type | Meaning |
| --- | --- | --- |
| `results[]` | object[] | Search result cards. The full allowlisted field set is in the data dictionary; fields are present when the source provides them. |
| `total` | integer \| null | Total matching rows. Null when include_total=false or totals are suppressed. |
| `limit / offset` | integer | The window that was actually applied, echoed back. |
| `total_pages / max_page` | integer \| null | Total pages, and the deepest page reachable under the depth policy. |
| `random_seed` | string \| null | Non-null only when the effective sort is random. Pass it back as seed= to page through the same ordering. |
| `contract_version` | string | Schema contract the response was built against. |
| `request_id / server_time / data_updated_at` | string | Correlation id (also X-Request-ID), response time, and when the underlying data was last refreshed. |

**Notes.** Reuse random_seed through seed to keep randomized pagination stable. site accepts auto1, japanauction (the Japanese auction houses), copart, ecarstrade, encar, openlane or schadeautos — the European classifieds network is not a site value. Both site and site_exclude take a comma-separated, case-insensitive list; an unknown slug on either is a 400 naming the offender, and passing both narrows the include list by the exclusion. An unfiltered search can page to any depth; a filtered search is bounded by a per-query timeout rather than a hard offset.

## GET /api/search/auction-ids

Resolve a free-text query to matching auction ids only.

**Scope:** `search`

### Parameters

| Parameter | Send in | Type | Required | Example | Where the value comes from | Description |
| --- | --- | --- | --- | --- | --- | --- |
| `q` | Query string | string | no | `bmw 320d touring` | Free text entered by your user. | Free-text query. An empty query returns an empty list. |

### Example requests

```http
GET https://api.thecarapi.com/api/search/auction-ids?q=bmw%20320d
```

```http
GET https://api.thecarapi.com/api/search/auction-ids?q=kia%20ev6
```

### Example response

```json
{
  "success": true,
  "auction_ids": [
    "encar:38112900",
    "auto1:AB12CD"
  ],
  "found": 2
}
```

**Notes.** Use this to pre-filter, then hydrate each id through the auction detail routes. Returns an empty list when full-text search is disabled server-side.
