contract 2026-10-05
Endpoints

Vehicle watches

Saved vehicle searches matched against every auction source your key can use and, if it has classifieds, the European classifieds — scanned every 10 minutes, with new matches delivered by polling or a signed webhook. Scope: watches. Granted per contract — not on a new key by default. Up to 10 criteria per watch and 25 active watches per key.

From a watch to a match

  1. 1Create the watch with POST /api/watches and keep the webhook_secret from the response — it is shown only here and when rotated.
  2. 2The first scan records what already matches, flagged initial: true. Later scans add only cars listed since.
  3. 3Either poll GET /api/watches/{watch_id}/matches with after_id set to the last next_after_id you saw, or receive each batch of new matches on your webhook_url.
  4. 4Verify every webhook delivery: X-Watch-Signature is sha256=<hex HMAC-SHA256 of "<X-Watch-Timestamp>.<raw body>"> under your webhook_secret.
GET

/api/watches

The calling key’s watches, with their match counts.

Requires the watches scope.

Example request

Request
GET https://api.thecarapi.com/api/watches

Example response

json
{
  "success": true,
  "watches": [
    {
      "id": 7,
      "name": "Diesel 3 Series under 20k",
      "criteria": [
        {
          "make": "BMW",
          "model": "3 Series",
          "fuel": "Diesel",
          "year_from": 2018,
          "max_price": 20000
        }
      ],
      "include_classifieds": true,
      "webhook_url": "https://example.com/hooks/watch",
      "webhook_enabled": true,
      "active": true,
      "match_count": 132
    }
  ],
  "contract_version": "2026-10-05"
}
POST

/api/watches

Save a vehicle configuration to keep searching for.

Requires the watches scope.

Parameters

criteriaobject | object[] · JSON bodyrequired

One criterion or a list of up to 10; a car matching any of them matches the watch. Each needs make, and may give model, fuel, gearbox, country (ISO or europe), year_from / year_to, kilometers_from / kilometers_to, horsepower_from / horsepower_to (auctions only) and price_from / max_price.

Example {"make": "BMW", "model": "3 Series", "fuel": "Diesel", "year_from": 2018, "max_price": 20000}·Where the value comes from /api/brands, /api/models, /api/fuels, /api/gearboxes

namestring · JSON body

Free text.

Example Diesel 3 Series under 20k·Where the value comes from Your label.

include_classifiedsboolean · JSON body

Default true. Also scan the European classifieds — only when the key has the classifieds scope.

Example true·Where the value comes from Your choice.

webhook_urlstring · JSON body

https on a public address. Each batch of new matches is POSTed here, signed.

Example https://example.com/hooks/watch·Where the value comes from Your receiver.

Example request

Request
POST https://api.thecarapi.com/api/watches
{"name": "Diesel 3 Series under 20k", "criteria": [{"make": "BMW", "model": "3 Series", "fuel": "Diesel", "year_from": 2018, "max_price": 20000}], "webhook_url": "https://example.com/hooks/watch"}

Example response

json
{
  "success": true,
  "watch": {
    "id": 7,
    "name": "Diesel 3 Series under 20k",
    "criteria": [
      {
        "make": "BMW",
        "model": "3 Series",
        "fuel": "Diesel",
        "year_from": 2018,
        "max_price": 20000
      }
    ],
    "include_classifieds": true,
    "webhook_url": "https://example.com/hooks/watch",
    "webhook_enabled": true,
    "webhook_secret": "3f9c…",
    "active": true
  },
  "contract_version": "2026-10-05"
}
GET

/api/watches/{watch_id}

One watch.

Requires the watches scope.

Parameters

watch_idinteger · in the URL pathrequired

The watch id.

Example 7·Where the value comes from /api/watches -> watches[].id

Example request

Request
GET https://api.thecarapi.com/api/watches/7

Example response

json
{
  "success": true,
  "watch": {
    "id": 7,
    "name": "Diesel 3 Series under 20k",
    "active": true,
    "match_count": 132
  },
  "contract_version": "2026-10-05"
}
PATCH

/api/watches/{watch_id}

Change a watch.

Requires the watches scope.

Parameters

watch_idinteger · in the URL pathrequired

The watch id.

Example 7·Where the value comes from /api/watches -> watches[].id

name / criteria / include_classifiedsstring | object[] | boolean · JSON body

New criteria restart the baseline: the next scan records what matches then as initial.

Example criteria·Where the value comes from As on create.

webhook_url / webhook_enabledstring | boolean · JSON body

An empty webhook_url removes it.

Example ""·Where the value comes from Your receiver.

activeboolean · JSON body

Pause or resume scanning.

Example false·Where the value comes from Your choice.

rotate_secretboolean · JSON body

true issues a new webhook_secret, returned in this response only.

Example true·Where the value comes from Your choice.

Example requests

Request
PATCH https://api.thecarapi.com/api/watches/7
{"active": false}
PATCH https://api.thecarapi.com/api/watches/7
{"rotate_secret": true}

Example response

json
{
  "success": true,
  "watch": {
    "id": 7,
    "active": false
  },
  "contract_version": "2026-10-05"
}
DELETE

/api/watches/{watch_id}

Delete a watch and its matches.

Requires the watches scope.

Parameters

watch_idinteger · in the URL pathrequired

The watch id.

Example 7·Where the value comes from /api/watches -> watches[].id

Example request

Request
DELETE https://api.thecarapi.com/api/watches/7

Example response

json
{
  "success": true,
  "contract_version": "2026-10-05"
}
GET

/api/watches/{watch_id}/matches

Matches found for a watch, in the order they were found.

Requires the watches scope.

Parameters

watch_idinteger · in the URL pathrequired

The watch id.

Example 7·Where the value comes from /api/watches -> watches[].id

after_idinteger · query string

Stable cursor, so nothing is missed or repeated. Default 0.

Example 0·Where the value comes from The last next_after_id you received.

include_initialboolean · query string

Default true. false skips what already matched when the watch was created.

Example false·Where the value comes from Your choice.

sourceenum · query string

Only matches from one side.

Example auction·Where the value comes from auction or classified.

limitinteger · query string

Default 100, maximum 500.

Example 100·Where the value comes from Page size.

Example requests

Request
GET https://api.thecarapi.com/api/watches/7/matches?after_id=0
GET https://api.thecarapi.com/api/watches/7/matches?after_id=1880&include_initial=false

Example response

json
{
  "success": true,
  "matches": [
    {
      "id": 1881,
      "source": "auction",
      "initial": false,
      "matched_at": "2026-10-18T09:20:00Z",
      "vehicle": {
        "site": "openlane",
        "auction_id": 11409652,
        "title": "BMW 320d Touring",
        "price_eur": 16900,
        "landed_price_eur": 18450,
        "api_url": "/api/auction/openlane/11409652"
      }
    }
  ],
  "next_after_id": 1881,
  "has_more": false,
  "contract_version": "2026-10-05"
}

What you get back

matches[].vehicleobject

The car as it looked when found, with api_url (auctions) or url (classifieds, the original ad) to read it now.

next_after_id / has_moreinteger / boolean

Send next_after_id as after_id next time; has_more says whether to ask again straight away.