Справочник
Примери с код
Минимални клиенти на cURL, TypeScript, Python и PHP, плюс рецепти за страниране, условни заявки и страници с детайли.
Няма задължителен SDK. Всеки HTTP клиент, който може да изпраща заглавки и да чете JSON, ще работи. Примерите за търсене използват cURL с jq, TypeScript на сървъра, Python с requests или PHP с Guzzle. Задайте THECARAPI_KEY в съответната среда. Рецептите илюстрират модели на интеграция и използват съществуващото състояние и помощни функции на приложението ви.
cURL
bash
export THECARAPI_KEY="your_key"
curl -sS --compressed \
-H "X-API-Key: $THECARAPI_KEY" \
"https://api.thecarapi.com/api/search?brand=bmw&fuel=Diesel&year_from=2018&sort=price_low&limit=24" \
| jq '.results[] | {auction_id_str, site_name, clean_make, clean_model, public_price_eur}'TypeScript
typescript
const BASE = "https://api.thecarapi.com";
interface SearchResponse {
success: boolean;
results: SearchCard[];
total: number | null;
limit: number;
offset: number;
max_page: number | null;
total_pages: number | null;
contract_version: string;
request_id: string;
}
interface SearchCard {
auction_id: number;
auction_id_str: string;
site_name: string;
clean_make: string;
clean_model: string;
registration_year: number | null;
mileage: number | null;
/** Цените са JSON числа, никога низове. */
public_price_eur?: number | null; // Може да бъде пропуснато според правата за полета.
thumbnail_url: string | null;
}
async function search(params: Record<string, string | number>): Promise<SearchResponse> {
const url = `${BASE}/api/search?${new URLSearchParams(
Object.entries(params).map(([k, v]) => [k, String(v)]),
)}`;
const res = await fetch(url, {
headers: {
"X-API-Key": process.env.THECARAPI_KEY!,
"Accept-Encoding": "gzip",
},
});
if (!res.ok) {
throw new Error(`${res.status} — request ${res.headers.get("X-Request-ID")}`);
}
return res.json();
}
const page = await search({ brand: "bmw", fuel: "Diesel", limit: 24 });
console.log(page.results.length, "of", page.total);Python
python
import os
import requests
BASE = "https://api.thecarapi.com"
session = requests.Session()
session.headers.update({"X-API-Key": os.environ["THECARAPI_KEY"]})
# requests договаря gzip и разкомпресира прозрачно.
response = session.get(
f"{BASE}/api/search",
params={"brand": "bmw", "fuel": "Diesel", "year_from": 2018, "limit": 24},
timeout=30,
)
response.raise_for_status()
payload = response.json()
for car in payload["results"]:
print(car["site_name"], car["auction_id_str"], car.get("public_price_eur"))PHP
php
<?php
$client = new GuzzleHttp\Client([
'base_uri' => 'https://api.thecarapi.com',
'headers' => ['X-API-Key' => getenv('THECARAPI_KEY')],
'decode_content' => 'gzip', // На Guzzle това трябва да се каже изрично
'timeout' => 30,
]);
$response = $client->get('/api/search', [
'query' => ['brand' => 'bmw', 'fuel' => 'Diesel', 'limit' => 24],
]);
$payload = json_decode((string) $response->getBody(), true);
foreach ($payload['results'] as $car) {
printf("%s/%s — €%s\n", $car['site_name'], $car['auction_id_str'], $car['public_price_eur'] ?? 'unavailable');
}Рецепта: обхождане на набор от резултати
python
def iter_results(session, **filters):
"""Връща всяка карта, като спазва политиката за дълбочина, вместо да я гадае."""
offset, limit = 0, 100
while True:
r = session.get(f"{BASE}/api/search",
params={**filters, "limit": limit, "offset": offset,
"include_total": "false"},
timeout=30)
r.raise_for_status()
rows = r.json()["results"]
if not rows:
return
yield from rows
offset += limit
# /api/search и /api/listVehicles нямат ограничение на отместването. Каталогът,
# топ офертите и обявите спират на 5000, а твърде дълбока страница
# отговаря с 400. Четете странирането от /api/contract.include_total=false пропуска преброяването, което е скъпата половина на дълбокото търсене.Рецепта: проверка на страница от търсенето без повторно изтегляне
javascript
let etag = null;
let cached = null;
async function poll(url) {
const res = await fetch(url, {
headers: {
"X-API-Key": process.env.THECARAPI_KEY,
...(etag ? { "If-None-Match": etag } : {}),
},
});
if (res.status === 304) return cached; // нищо не се е променило, не е прехвърлено тяло
if (!res.ok) throw new Error(`HTTP ${res.status}`);
etag = res.headers.get("ETag"); // непрозрачен — върнете го точно
cached = await res.json();
return cached;
}Рецепта: страница с детайли за автомобил с една заявка
javascript
const { auction } = await getJson(`/api/auction/${site}/${id}`);
const photos = auction.vault_gallery?.images ?? [];
const stillComing = auction.vault_gallery?.pending ?? 0; // покажете контейнери
const price = auction.public_price_eur; // вече актуална, ако е възможно
const asOf = auction.live_price
? new Date(auction.live_price.fetched_at * 1000) // секунди → ms
: null;
// Само ако обновяването е изпуснало бюджета на заявката, прочетете точно още веднъж.
if (!auction.live_price && auction.live_price_pending) {
setTimeout(() => refetch(site, id), 2000);
}vault_gallery е същото тяло, което връща /api/auction-images/{site}/{id}, така че втората заявка не е нужна.