Authentication & scopes
Three interchangeable ways to present a key, the restrictions a key can carry, and the scope groups that gate each endpoint.
Every endpoint except the two liveness probes (/api/health/live and /api/health/ready) requires an API key. Present the key in one of these ways:
| Method | Header or parameter | Notes |
|---|---|---|
| Header | X-API-Key: <key> | Recommended for server-to-server calls. |
| Bearer | Authorization: Bearer <key> | Equivalent to X-API-Key. |
| Query string | ?api_key=<key> | Disabled by default; use only when explicitly enabled for your key. Keys in URLs end up in logs and referrers. |
# Header — the normal case
curl -H "X-API-Key: $API_KEY" "https://api.thecarapi.com/api/sites"
# Bearer — identical behaviour, useful when your HTTP layer already speaks OAuth
curl -H "Authorization: Bearer $API_KEY" "https://api.thecarapi.com/api/sites"Key restrictions
| Restriction | Effect when violated |
|---|---|
| IP or CIDR allowlist | Requests from outside the list return 403. |
| Origin allowlist | Browser requests from other origins return 403. |
| Expiry date | Requests after the date return 401. |
| Status (revoked, suspended) | All requests return 403. |
| Scope set | A request to a route your key does not cover returns 403 with {"success": false, "error": "API key is not authorized for this route"}. There is no machine-readable error code in the body — branch on the status, not on the message text. |
Five failed authentication attempts from one IP trigger a temporary brute-force lockout: every subsequent request from that address answers 429 for 15 minutes, including requests carrying a valid key. A successful authentication clears the counter, so a client that fixes its key on the first or second failure never reaches the threshold. Do not retry a 401 in a loop.
Published scope groups
| Scope | Published access |
|---|---|
search | Inventory search, filter facets (individually or combined via /api/facets), sources, and the full model catalog |
catalog | Manufacturer and model-group catalog |
seo | Popular searches and brand/model slug resolution |
auctions | Auction detail, images, price history, and VIN history |
details | Full vehicle details, including upstream fetches |
top-offers | Auctions priced below their market reference |
classifieds | European classifieds feed, facets, and models (theparking remains a legacy alias) |
archive | Historical inventory search, stored detail and coverage statistics; granted separately |
market | Cars.bg and auction market price snapshots |
calculator | Import cost calculator and supported countries |
ops | Service health, the contract, and the API index |
* grants every route. A scope may also be a literal URL rule rather than a group. public is a legacy compatibility bundle — search facets, catalog, SEO, auctions, calculator and health — preserved for older integrations; new keys are issued against the groups above.
Field grants
| Group | Fields | Default |
|---|---|---|
listing | Identity, specifications, images, timing and VAT scheme | Always retained |
source_prices | current_price, buy_now_price, start_price, final_price | Included |
landed_prices | current_final, buynow_final, public_price_eur, current_bgn, buynow_bgn | Included |
house_valuation | estimated_value_eur | Included where available |
vehicle_identity | chassis_number, car_id, vin_ocr | Included where available; VIN-history route access is separate |
crawl_meta | created_at, updated_at, first_seen_at, last_seen_at, last_available_at, last_changed_at | Included where available |
landed_breakdown | current_tax, buynow_tax, current_tax_delivery, buynow_tax_delivery | Separate grant |
market_reference | is_top_offer, top_offer_savings, top_offer_savings_pct, market_reference | Separate grant |
korea_merge | source_comparison, canonical_offer | Separate grant |
These are provisioning defaults, not a promise about an existing key. Endpoint access does not automatically grant every response field: for example, top-offers can be callable while its market_reference block is omitted. Examples show illustrative fields; use the OpenAPI schema and handle omitted optional fields. Private bidder data and account credentials remain excluded regardless of field grants.
What a new key gets by default
Scopes are granted per endpoint, and a new customer key is issued with the common surface enabled and the rest switched off. If a route answers 403 on your key, it is not broken — it was not granted, and the operator can enable it.
| Endpoints | |
|---|---|
| Enabled by default | /api/search, /api/brands, /api/models, /api/types, /api/years, /api/production-years, /api/fuels, /api/countries, /api/gearboxes, /api/sites, /load-models, /api/facets, /api/catalog/*, /api/seo/*, /api/auction/*, /api/auction-images/*, /api/calculator/*, /api/top-offers, /api/classifieds/*, /api/car-details, /api/contract, /api/health, / |
| Granted on request | /api/archive/*, /api/vin/{vin}/history, /api/cars-bg-market, /api/auction-market, /api/listVehicles (and /listVehicles), /api/search/auction-ids |
/api/health/live and /api/health/ready need no key and are unaffected by scopes.