---
title: "Интеграция на API за автомобилни търгове: страниране, кеширане, повторни опити и лимити"
description: "API за търгове в продукция: страниране, кеширане по тип данни, повторни опити, лимити и грешките, за които да се подготвите предварително."
slug: auction-api-integration-guide
canonical: https://thecarapi.com/bg/blog/auction-api-integration-guide
category: Ръководства
author: Инженерен екип на Авто Данни
published: 2026-07-30
updated: 2026-08-07
tags: [API интеграция, кеширане, лимити на заявките, страниране]
---

# Интеграция на API за автомобилни търгове: страниране, кеширане, повторни опити и лимити

Първата интеграция винаги работи. Тази, която оцелява пик в трафика, срив на източник и промяна в схемата, е различен софтуер.

Това е статията, която да прочетете след първото успешно извикване и преди да покажете каквото и да е на потребители. Всичко по-долу идва от интеграции, които са се счупили по конкретен, избегнат начин.

## Удостоверяване и работа с ключа

Ключовете се подават в заглавка, никога в параметрите на адреса — параметрите попадат в журналите за достъп, историята на браузъра, заглавките referrer и системите за следене на грешки.

```bash
# И двата начина работят
curl -H "X-API-Key: $API_KEY"          "https://api.thecarapi.com/api/search?limit=1"
curl -H "Authorization: Bearer $API_KEY" "https://api.thecarapi.com/api/search?limit=1"
```

> **Никога не извиквайте API от браузъра** — Ключ, изпратен на клиента, е публичен ключ, каквито и да са намеренията ви. Препращайте през собствения си бекенд — това ви дава и място за кеширане, за ограничаване на собствените ви потребители и за смяна на доставчика без нова версия на фронтенда.

Една оперативна подробност, която е добре да знаете, преди да ви ухапе: повтарящите се неуспешни удостоверявания обикновено водят до блокиране. Неправилно настроена тестова среда, която бомбардира API със стар ключ, може да блокира IP адреса, който споделя продукцията. Дръжте средите на отделни ключове и прекратявайте веднага при 401, вместо да опитвате отново.

## Кеширайте по тип данни, не по ендпойнт

Най-ефективното решение в цялата интеграция. Четирите слоя данни се променят с напълно различна скорост и едно TTL за всички е или прекалено агресивно, или прекалено консервативно.

| Данни | Препоръчително TTL | Обосновка |
| --- | --- | --- |
| Каталог — марки, модели, горива, държави | **24 часа** | Променя се при поява на нов модел. Кеширайте агресивно. |
| Бройки във фасетите | 5 – 15 минути | Приблизителни по природа; никой не забелязва леко остаряла бройка. |
| Резултати от търсене | 1 – 5 минути | Баланс между актуалност и повтарящи се еднакви заявки. |
| Детайли за автомобила (спецификация) | 1 час | Спецификацията не се променя. Цената — да; вижте по-долу. |
| Текуща цена / наддаване | **Не кеширайте** | Кеширана актуална цена е грешна цена. |
| Галерии | Дни | На практика непроменливи, след като лотът е обявен. |
| История на цените | 15 минути | Само се добавя; остаряването ви коства само най-новата точка. |

Редът за детайлите заслужава внимание. Спецификацията и цената пристигат в един и същ отговор, но имат противоположни изисквания. Чистото решение е да кеширате отговора с детайлите за полетата на спецификацията и да четете цената отделно на всеки екран, на който потребителят може да предприеме действие.

Много GET ендпойнти вече се кешират на ръба на мрежата и връщат заглавка `X-Cache`. Записвайте я — неочаквано ниският процент попадения обикновено означава, че променяте параметър, който не сте възнамерявали, например подавате време или нестабилно сортиране в иначе еднаква заявка.

## Страниране, без да паднете от края

Три правила, които покриват почти всеки проблем със страниране в тази област.

### Пропускайте броя, когато не ви трябва

Преброяването на съвпадащите редове в голям филтриран набор често е най-скъпата част на търсенето. При безкрайно превъртане или „зареди още“ никога не показвате общия брой, така че подавайте `include_total=false` и спестете разхода изцяло.

### Спазвайте ограничението за дълбочина

Дълбоките отмествания са скъпи навсякъде и повечето API ги ограничават. Ако трябва да обходите целия набор от резултати — например за нощно сверяване — не стигайте до отместване 50 000. Вместо това разделете заявката: обхождайте по марка, по година или по ценови диапазон, като всяка част остава плитка.

```python
# Грешно: пада от ограничението за дълбочина и забавя с всяка страница
offset = 0
while True:
    page = search(brand="bmw", offset=offset, limit=100)
    if not page["results"]:
        break
    offset += 100

# Правилно: разделете, така че всяка заявка да остане плитка
for year in range(2015, 2027):
    offset = 0
    while True:
        page = search(brand="bmw", year_from=year, year_to=year,
                      offset=offset, limit=100, include_total=False)
        if not page["results"]:
            break
        yield from page["results"]
        offset += 100
```

### Изберете сортиране и го запазете

Всяко сортиране в API е детерминирано, така че границата на страницата никога не повтаря и не губи ред — но само ако запазите сортирането еднакво през цялото обхождане. Смяната на `sort` по средата на страниране пренарежда набора под отместването ви. Няма случайно сортиране, което да трябва да се стабилизира: оттеглената стойност `random` все още се приема и се обслужва като `default` — първо със снимки, после най-новите.

## Повторни опити и какво да не повтаряте

Политика, която повтаря грешните неща, превръща малък проблем в срив. Правилото е: повтаряйте само това, което може реално да успее следващия път.

| Статус | Повторен опит? | Как |
| --- | --- | --- |
| `429` надвишен лимит | Да | Спазвайте `Retry-After`, ако го има, иначе експоненциално изчакване със случайно отклонение |
| `500` / `502` / `503` / `504` | Да | Експоненциално изчакване, до 3–4 опита |
| `408` изтекло време | Да | Веднъж, после стеснете заявката — често някой филтър е твърде широк |
| `401` / `403` | **Не** | Ключът е грешен. Повторните опити задействат защитата с блокиране |
| `400` грешна заявка | **Не** | Неправилната заявка ще остане неправилна |
| `404` | **Не** | Лотът не съществува или е премахнат |

Използвайте случайно отклонение. Без него всеки клиент, който е получил грешка по време на кратък срив, опитва отново в един и същ момент и създава лавина при възстановяването — превръщайки тридесетсекундно смущение в продължителен инцидент.

```javascript
const RETRYABLE = new Set([408, 429, 500, 502, 503, 504]);

async function call(url, { attempts = 4 } = {}) {
  for (let i = 0; i < attempts; i++) {
    const res = await fetch(url, { headers: { 'X-API-Key': process.env.API_KEY } });
    if (res.ok) return res.json();
    if (!RETRYABLE.has(res.status)) {
      throw new Error(`${res.status} ${await res.text()}`);   // прекрати веднага, без повтори
    }
    const after = Number(res.headers.get('retry-after')) * 1000;
    const backoff = after || 2 ** i * 250 + Math.random() * 250;  // случайно отклонение
    await new Promise(r => setTimeout(r, backoff));
  }
  throw new Error('exhausted retries');
}
```

## Записвайте идентификатора на заявката

Отговорите съдържат идентификатор на заявката, връщан и като `X-Request-ID`. Записвайте го при всяко извикване и го показвайте в собствените си съобщения за грешка. Той превръща разговора с поддръжката от „търсенето беше бавно тази сутрин“ в конкретно извикване, което някой може да провери. Струва един ред и е най-ценният запис, който ще добавите.

Записвайте и `contract_version`. Когато формата на отговора се промени, версията в журналите ви казва точно кога, което иначе е наистина трудно за възстановяване.

## Обработвайте правилно оскъдните полета

Полетата присъстват, когато източникът ги предоставя, което означава, че липсващите полета са нормалният случай, а не грешка. Два навика:

- **Никога не приемайте, че поле съществува.** VIN, мощност, брой снимки и списъци с оборудване често липсват. Деструктурирането без стойност по подразбиране е най-честата причина за срив в автомобилен фронтенд.
- **Различавайте null от нула.** Пробег `0` означава, че километражът показва нула. `null` означава, че източникът не е казал. Показването на двете като „0 км“ кара всяка кола с неизвестен пробег да изглежда нова.

> **Следете попълнеността, не само грешките** — Поле, което е било попълнено на 95% и падне до 40%, е счупен извличач при източника и няма да предизвика нито една грешка в журналите ви. Следете попълнеността по поле и по източник във времето — така хващате цял клас тихо влошаване на данните, за който наблюдението на грешки е сляпо.

## Проверки на състоянието и плавно влошаване

Една автомобилна платформа не трябва да спира, защото един ендпойнт е бавен. Решете предварително какво се влошава и как:

1. Ако **снимките** не се заредят, показвайте картите с контейнер. Не проваляйте страницата.
2. Ако **фасетите** не се заредят, показвайте търсенето без бройки във филтрите. Потребителите пак могат да търсят.
3. Ако **историята на цените** не се зареди, скрийте графиката. Тя е подобрение, не продуктът.
4. Ако **търсенето** не работи, това е истински срив — покажете го честно, вместо празен резултат, който потребителите четат като „няма съвпадащи коли“ и действат според него.

Последната разлика е по-важна, отколкото изглежда. Празният резултат и неуспешната заявка са напълно различни послания към потребителя и смесването им кара продукта ви да изглежда така, сякаш няма инвентар.

```bash
curl -s "https://api.thecarapi.com/api/health"
```

_Евтино за проверка и си струва да го свържете със собствената си страница за статус, вместо да научавате за проблем от потребителите._

## Списък за проверка преди старт

- API ключът е само на сървъра, а тестовата среда ползва различен ключ от продукцията.
- TTL на кеша е зададено по тип данни; актуалните цени не се кешират.
- Повторните опити обхващат само статуси, които може да успеят, със случайно отклонение и лимит на опитите.
- `include_total=false` на всеки изглед, който не показва брой.
- Дълбокото страниране е разделено на части, а не обхождано с отместване.
- Идентификаторите на заявките се записват и се показват в грешките.
- Всеки достъп до поле понася липсата му; null и нула се различават.
- Поведението при влошаване е определено за всеки ендпойнт, а празните резултати видимо се различават от отказите.
- Наблюдението на попълнеността работи преди старта, а не след първия инцидент с данните.

Подробностите за всеки споменат тук ендпойнт са в [API справочника](/docs), а [изграждането на платформа](/blog/build-used-car-marketplace) описва архитектурата, в която се вписва тази механика.

## Frequently asked questions

### Колко дълго да кеширам отговорите от API за автомобилни търгове?

По тип данни, а не по ендпойнт. Стойностите от каталога, като марки и горива, могат да се кешират 24 часа; бройките във фасетите 5–15 минути; резултатите от търсене 1–5 минути; спецификацията на автомобила около час; галериите — дни. Текущите цени и наддавания изобщо не трябва да се кешират — кешираната актуална цена просто е грешна цена.

### Кои HTTP грешки да опитвам отново?

Опитвайте отново 408, 429 и 5xx с експоненциално изчакване и случайно отклонение, до три-четири опита, като спазвате Retry-After, когато го има. Никога не опитвайте отново 400, 401, 403 или 404 — те няма да успеят при втори опит, а повтарянето на неуспешни удостоверявания може да задейства защита с блокиране, която засяга цялата ви среда.

### Как да експортирам голям набор от резултати, без да опра в лимитите на страниране?

Разделете заявката, вместо да обхождате дълбоки отмествания. Обхождайте по марки, години или ценови диапазони, така че всяка отделна заявка да остане плитка, и подавайте include_total=false, тъй като не показвате брой. Дълбоките отмествания стават все по-скъпи и обикновено са ограничени, така че обхождане с отместване на десетки хиляди редове ще се провали или ще изтече.

### Мога ли да извиквам API за търгове директно от фронтенда си?

Не. Всеки ключ, изпратен до браузър, е публичен, независимо от намеренията. Препращайте през собствения си бекенд, което ви дава и естествено място за кеширане на отговорите, за ограничаване на заявките на потребителите ви и за смяна на доставчика без нова версия на фронтенда.

### Защо понякога полета изчезват от отговорите?

Полетата присъстват, когато източникът ги публикува, така че липсата е нормална, а не изключение — VIN, мощност и списъци с оборудване често липсват. Внезапен спад в това колко често се появява дадено поле обаче обикновено означава счупен извличач при източника. Това не предизвиква грешки, така че се хваща само чрез следене на попълнеността по поле и по източник във времето.
