contract 2026-08-19
Endpoints

European classifieds

A retail price surface of roughly 9.8M live listings gathered from 681 origin portals — national classifieds sites, dealer groups and manufacturer stock pages — across 39 European countries: mobile.de, kleinanzeigen.de, autoscout24, leboncoin.fr, lacentrale.fr, autosupermarket.it, njuskalo.hr and hundreds more. Every listing keeps its origin portal in source_site, so the same feed answers a national question and a portal-level one. These are retail listings, not auction inventory: no bidding, no auction end date, no detail payload and no gallery, just a single remote thumbnail per listing. They live in their own tables with their own vocabulary (seller type, origin portal), which is why they get their own query surface instead of a site slug on /api/search. Ended and paid-placement ("promoted") rows are excluded from every response, and all three endpoints return 503 while the dataset has not been built yet. Scope: theparking — that is the scope name in the path, not the name of a source.

Calling it end to end

  1. 1Call GET /api/theparking/facets once and cache it. It hands you every valid country code, brand, fuel, gearbox, seller type and origin portal, each with a live count, plus the price and year bounds for your sliders. It is precomputed by the nightly sweep and reads back in ~10 ms, so caching it costs you nothing in freshness. Never hard-code these values — brands are published verbatim by each portal.
  2. 2When the user picks a brand, call GET /api/theparking/models?brand=BMW,Audi to fill the model select. Models come back most common first, capped at 400.
  3. 3Query GET /api/theparking/listings with the chosen filters. Multi-value filters are comma-separated: they OR within a parameter and AND across parameters. Page with limit/offset or page/page_size — limit caps at 100. If you do not need a match count, pass include_total=false: it is the fastest way to page this feed.
  4. 4Render each row directly. There is no detail endpoint and no gallery: the listing object you receive is the entire record, with one remote thumbnail in image_url and a deep link out in offer_url.
  5. 5To use it as a market reference, query the same brand, model, and year window you are about to bid on, read the price_eur spread by seller_type, and diff it against the auction lot’s public_price_eur.

Coverage by country

9,808,689 active listings as of 2026-08-18, across 39 countries and 681 origin portals. The figures move with every refresh — read them as proportions, and take live counts from /api/theparking/facets.

Countrycountry=ListingsPortalsLargest origin portals
Germanyde2,218,902101mobile.de, kleinanzeigen.de, autoscout24.de, volkswagen.de, pkw.de, instamotion.com
Francefr1,328,466148leboncoin.fr, lacentrale.fr, zoomcar.fr, autocadre.com, spoticar.fr, paruvendu.fr
Italyit1,076,20661subito.it, autoscout24.it, quattroruote.it, autosupermarket.it, automobile.it, automoto.it
Spaines710,37068coches.net, milanuncios.com, autoscout24.es, autocasion.com, motorflash.com, coches.com
Netherlandsnl640,48263autowereld.nl, marktplaats.nl, autotrack.nl, autoscout24.nl, viabovag.nl, autokopen.nl
Polandpl548,62351otomoto.pl, olx.pl, sprzedajemy.pl, autoplac.pl, allegro.pl, motogratka.pl
Bulgariabg381,26524car24.bg, mobile.bg, cars.bg, auto.bg, bazar.bg, olx.bg
Austriaat280,20335willhaben.at, gebrauchtwagen.at, autoscout24.at, zweispurig.at, dasweltauto.at, kleinanzeigen.at
Belgiumbe264,93191autoscout24.be, 2ememain.be, gocar.be, vroom.be, carselect.touring.be, okasie.be
Albaniaal252,5115merrjep.al, albania.landrover.com, carandclassic.com, motorsportmarkt.de, oldcar24.com
Switzerlandch222,76633autoscout24.ch, autolina.ch, tutti.ch, ricardo.ch, emilfrey.ch, auto.amag.ch
Swedense187,86929blocket.se, bytbil.com, bilweb.se, volkswagen.se, riddermarkbil.se, hedinautomotive.se

A country figure is a mix of portals, not a single market — half of German inventory is one site. When that matters, narrow with source or widen with source_exclude. Only the largest portals are listed here; /api/theparking/facets?limit=0 returns all 681.

GET

/api/theparking/listings

Query retail classifieds aggregated from portals across Europe.

Requires the theparking scope.

Parameters

countrystring · query string

Comma-separated country codes, case-insensitive.

Example de,at·Where the value comes from /api/theparking/facets -> countries[].value

brandstring · query string

Comma-separated brands, exact as published.

Example BMW,Audi·Where the value comes from /api/theparking/facets -> brands[].value

modelstring · query string

Comma-separated models.

Example 3 Series·Where the value comes from /api/theparking/models?brand=BMW -> value

fuelstring · query string

Comma-separated normalized fuels.

Example diesel·Where the value comes from /api/theparking/facets -> fuels[].value

gearboxstring · query string

Comma-separated normalized gearboxes.

Example automatic·Where the value comes from /api/theparking/facets -> gearboxes[].value

sellerstring · query string

Comma-separated seller types, such as dealer or private.

Example dealer·Where the value comes from /api/theparking/facets -> sellers[].value

sourcestring · query string

Comma-separated origin portals, case-insensitive. Unlike site on the auction side, an unrecognised portal is not an error — this vocabulary is drawn from the data itself rather than fixed, so an unknown value simply matches nothing.

Example mobile.de·Where the value comes from /api/theparking/facets -> sources[].value

source_excludestring · query string

Comma-separated origin portals to leave out, case-insensitive. With ~681 portals in the vocabulary this is the only practical way to say “everything but”. A listing with no recorded portal survives an exclusion.

Example mobile.de·Where the value comes from /api/theparking/facets -> sources[].value

price_from / price_tointeger · query string

EUR bounds.

Example 5000 / 15000·Where the value comes from EUR budget chosen by your user.

year_from / year_tointeger · query string

Year bounds.

Example 2016 / 2022·Where the value comes from Year bounds chosen by your user.

kilometers_from / kilometers_tointeger · query string

Mileage bounds.

Example 0 / 200000·Where the value comes from Mileage bounds chosen by your user.

qstring · query string

Substring match on title and description.

Example touring·Where the value comes from Free text entered by your user.

with_photoboolean · query string

Only listings that carry a thumbnail.

Example true·Where the value comes from Your filter choice.

sortenum · query string

Default newest.

Example price_low·Where the value comes from Choose newest, price_low, price_high, year_new, year_old, or mileage_low.

limit / offsetinteger · query string

Or page_size / page. limit caps at 100.

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

include_totalboolean · query string

Default true. Pass false to skip the match count entirely — total comes back null and the request is markedly faster.

Example false·Where the value comes from Your pagination strategy.

Example requests

Request
GET https://api.thecarapi.com/api/theparking/listings?country=de,at&brand=BMW&price_to=15000
GET https://api.thecarapi.com/api/theparking/listings?seller=dealer&source=mobile.de&sort=price_low&with_photo=true
GET https://api.thecarapi.com/api/theparking/listings?country=de&source_exclude=mobile.de,kleinanzeigen.de&include_total=false

Example response

json
{
  "success": true,
  "listings": [
    {
      "reference_id": "tp-91744022",
      "title": "BMW 320d Touring",
      "brand": "BMW",
      "model": "3 Series",
      "engine": "320d",
      "year": 2016,
      "price_eur": 12500.5,
      "mileage_km": 180000,
      "fuel_norm": "diesel",
      "gearbox_norm": "automatic",
      "colour": "black",
      "doors": "5",
      "country": "Germany",
      "country_code": "de",
      "region": "Bayern",
      "seller_type": "dealer",
      "source_site": "mobile.de",
      "photo_count": 12,
      "offer_url": "https://www.theparking.eu/...",
      "image_url": "https://img.leparking.fr/...",
      "published": "2026-07-30",
      "first_seen_at": "2026-07-30T04:11:02",
      "last_seen_at": "2026-08-05T04:09:55"
    }
  ],
  "total": 4412,
  "total_capped": false,
  "total_unavailable": false,
  "limit": 50,
  "offset": 0,
  "total_pages": 89
}

What you get back

reference_idstring

Stable identity for the listing, prefixed tp-. Use it to de-duplicate across polls.

titlestring

Listing headline as published by the origin portal.

brand / model / enginestring

Brand and model as published, plus the engine or trim string when the portal supplies one.

yearinteger

Registration year.

price_eurnumber

Retail asking price in EUR. This is an asking price, not a transaction price.

mileage_kminteger

Odometer reading in kilometres.

fuel_normstring

Normalized fuel, e.g. diesel, petrol, electric, hybrid. Matches the fuel filter vocabulary.

gearbox_normstring

Normalized gearbox, e.g. automatic, manual. Matches the gearbox filter vocabulary.

colourstring

Exterior colour as published.

doorsstring

Door count as published by the portal.

country / country_codestring

Country the car is listed in — display name and lower-case code. country_code is what the country filter accepts.

regionstring

Sub-national region or state when the portal publishes one.

seller_typestring

dealer or private. The single most useful axis for separating trade from retail asking prices.

source_sitestring

Origin portal the listing came from, e.g. mobile.de. Matches the source / source_exclude filter vocabulary, ~681 values wide. This is the attribution that makes a country figure readable — half of all German inventory is one portal.

photo_countinteger

How many photos the origin listing carries. Only one thumbnail is exposed here.

offer_urlstring

Deep link out to the listing, routed through the aggregator that indexes it — the URL is a theparking.eu one, not a direct link on the origin portal. Read source_site, not this URL, to know which portal the listing belongs to.

image_urlstring

Single remote thumbnail on the aggregator’s own CDN. Not copied into our image vault — treat it as a hotlink that disappears with the listing.

publisheddate

Date the origin portal published the listing.

first_seen_at / last_seen_attimestamp

When our sweep first and most recently observed the listing. Use last_seen_at to judge staleness.

total / limit / offset / total_pagesinteger

Standard pagination envelope for the matching set. total is exact for ordinary filters, and null when total_unavailable is true.

total_cappedboolean

True when counting stopped at 100,000. Read total as “100,000+” and page by offset rather than trusting total_pages. An unfiltered total is precomputed and never capped.

total_unavailableboolean

True when total is null because the count did not finish inside its budget — typically a q= search or a rare source. The listings themselves are complete and correct; only the count is missing, and the verdict is cached for 5 minutes.

GET

/api/theparking/facets

Counted filter vocabulary for the classifieds dataset.

Requires the theparking scope.

Parameters

limitinteger · query string

Values returned per dimension, default 50. 0 returns all of them — the only way to get the full 681-portal sources list.

Example 0·Where the value comes from How many values your picker can hold.

Example requests

Request
GET https://api.thecarapi.com/api/theparking/facets
GET https://api.thecarapi.com/api/theparking/facets?limit=0
curl -H "X-API-Key: $API_KEY" "https://api.thecarapi.com/api/theparking/facets"

Example response

json
{
  "success": true,
  "countries": [
    {
      "value": "de",
      "count": 184220
    },
    {
      "value": "fr",
      "count": 151077
    }
  ],
  "brands": [
    {
      "value": "BMW",
      "count": 41288
    }
  ],
  "fuels": [
    {
      "value": "diesel",
      "count": 302914
    }
  ],
  "gearboxes": [
    {
      "value": "automatic",
      "count": 188402
    }
  ],
  "sellers": [
    {
      "value": "dealer",
      "count": 402881
    }
  ],
  "sources": [
    {
      "value": "mobile.de",
      "count": 1109971
    },
    {
      "value": "leboncoin.fr",
      "count": 658810
    }
  ],
  "value_counts": {
    "countries": 39,
    "brands": 118,
    "fuels": 7,
    "gearboxes": 3,
    "sellers": 2,
    "sources": 681
  },
  "totals": {
    "listings": 9808689,
    "total_capped": false,
    "price_min": 300,
    "price_max": 480000,
    "year_min": 1970,
    "year_max": 2026
  }
}

What you get back

countries{value, count}[]

Every country code present in the dataset with its live listing count. This is the list to render a country picker from — it shows how wide the European coverage actually is.

brands{value, count}[]

Brands exactly as published, with counts. Feed a value straight back into the brand filter or into /api/theparking/models.

fuels{value, count}[]

Normalized fuel vocabulary with counts. These are the only values the fuel filter accepts.

gearboxes{value, count}[]

Normalized gearbox vocabulary with counts.

sellers{value, count}[]

Seller types with counts, typically dealer and private.

sources{value, count}[]

Origin portals with counts, most common first — the list of classifieds sites, dealer groups and manufacturer stock pages currently aggregated, and the vocabulary the source / source_exclude filters accept. There are ~681 of them, so the default trim of 50 is a leaderboard rather than a picker; pass limit=0 for the whole set.

value_countsobject

How many distinct values each dimension really has, before the per-dimension trim. Check value_counts.sources against the length of sources to know whether you are looking at all of them.

totalsobject

Dataset-level summary: active listing count plus price and year bounds (price_min, price_max, year_min, year_max). Use it to seed slider ranges. totals.total follows the same capping rule as the listings feed and carries its own totals.total_capped.

GET

/api/theparking/models

List models available for one or more brands.

Requires the theparking scope.

Parameters

brandstring · query stringrequired

Comma-separated brand list. Required.

Example BMW,Audi·Where the value comes from /api/theparking/facets -> brands[].value

Example requests

Request
GET https://api.thecarapi.com/api/theparking/models?brand=BMW
GET https://api.thecarapi.com/api/theparking/models?brand=BMW,Audi

Example response

json
{
  "success": true,
  "models": [
    {
      "value": "3 Series",
      "count": 8841
    },
    {
      "value": "5 Series",
      "count": 6002
    }
  ]
}

What you get back

models{value, count}[]

Model names available for the requested brands, most common first, capped at 400. value goes straight back into the model filter on /api/theparking/listings.