# API за база данни за филми за вашия каталог

> Ползвайте amodb като източник за собствена база данни за филми. Филмите, личностите, компаниите, колекциите, ключовите думи и жанровете споделят числови id, така че редовете се свързват чисто. Заредете първоначално с discover по прозорци на датата на излизане, обновявайте редовете по възраст и съпоставяйте собствените си id през find. JSON на TMDB v3, от 20 до 120 заявки в минута.

## Изградете собствена база данни за филми от API

amodb е независимо API, което работи по протокола на TMDB v3. Филмите, личностите, компаниите, колекциите, ключовите думи и жанровете имат числови id и сочат едни към други, така че от него можете да попълвате SQL таблици и да ги държите актуални. Заредете таблиците със странициране на discover, обновявайте ги по възраст и съпоставяйте собствените си идентификатори с `find`. amodb няма поток changes, затова обновяването е обикновено повторно теглене на редовете, които пазите.

Какво получавате:

- Шест свързани типа обекти със стабилни числови id.
- Странициране на discover за първото зареждане: до 20 резултата на страница, 500 страници на заявка.
- Прозорци по дата на излизане в discover, за да разбиете първото зареждане и да изброите новите премиери.
- Търсене по външни id за `imdb_id`, `tvdb_id`, `wikidata_id` и `kinopoisk_id`.

## Какви данни получавате

Това е моделът на данните. Всеки ред е една таблица в релационно копие.

| Обект        | Четене с                            | Ключ            | Свързва се с                                                                                       |
| ------------ | ----------------------------------- | --------------- | -------------------------------------------------------------------------------------------------- |
| Филм         | `GET /3/movie/{movie_id}`           | `id`, `imdb_id` | `genres[].id`, `production_companies[].id`, `belongs_to_collection.id`                             |
| Личност      | `GET /3/person/{person_id}`         | `id`, `imdb_id` | Филми през `/3/movie/{movie_id}/credits`                                                           |
| Компания     | `GET /3/company/{company_id}`       | `id`            | Филми през `with_companies` в discover. `parent_company` е винаги `null`, а `description` е празно |
| Колекция     | `GET /3/collection/{collection_id}` | `id`            | `parts[]`, списък с филми                                                                          |
| Ключова дума | `GET /3/keyword/{keyword_id}`       | `id`            | Филми през `/3/keyword/{keyword_id}/movies` или `with_keywords`                                    |
| Жанр         | `GET /3/genre/movie/list`           | `id`            | `genres[].id` във филмите                                                                          |

Връзките „много към много“ изискват свързващи таблици: `movie_genre`, `movie_company`, `movie_keyword` и `movie_credit`. Ползвайте `credit_id` от [участници](https://amodb.dev/bg/credits/) като ключ на последната. Списъците с полета са на страниците [филми](https://amodb.dev/bg/movies/), [личности](https://amodb.dev/bg/people/) и [колекции](https://amodb.dev/bg/collections/).

## Започнете в 3 стъпки

1. Сравнете трите скорости на заявките на страницата с [цените](https://amodb.dev/bg/pricing/). По-високата скорост скъсява първото зареждане, нищо друго не се променя.
2. Създайте ключ в личния си профил и го пазете в променлива на средата.
3. Извикайте `/3/discover/movie` за едноднев прозорец от дати на излизане, после вземете всяко id от списъка.

## Пример със заявка

PHP скриптът изброява филмите, излезли вчера и днес, през discover и записва всеки запис в SQLite таблица с upsert. Спи 3 секунди между четенията на детайли, за да остане под 20 заявки в минута, повтаря 429 след `Retry-After` и изтрива редове, чието id вече връща 404.

```bash
curl -s "https://api.amodb.dev/3/discover/movie?primary_release_date.gte=2026-10-17&primary_release_date.lte=2026-10-18&sort_by=primary_release_date.asc&page=1" \
  -H "Authorization: Bearer $AMODB_KEY"
```

```php
<?php
const BASE = 'https://api.amodb.dev/3';

function amodb(string $path, array $query = []): ?array
{
    $url = BASE . $path . '?' . http_build_query($query);
    for ($attempt = 0; $attempt < 3; $attempt++) {
        $retryAfter = 1;
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 10,
            CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('AMODB_KEY')],
            CURLOPT_HEADERFUNCTION => function ($handle, $line) use (&$retryAfter) {
                if (stripos($line, 'Retry-After:') === 0) {
                    $retryAfter = max(1, (int) trim(substr($line, 12)));
                }
                return strlen($line);
            },
        ]);
        $body = curl_exec($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        if ($status === 429) {
            sleep($retryAfter);
            continue;
        }
        if ($status === 404) {
            return null;
        }
        if ($status !== 200) {
            throw new RuntimeException("amodb returned $status for $path");
        }
        return json_decode($body, true);
    }
    throw new RuntimeException("Still rate limited on $path");
}

$db = new PDO('sqlite:movies.sqlite');
$db->exec('CREATE TABLE IF NOT EXISTS movie (id INTEGER PRIMARY KEY, imdb_id TEXT, title TEXT, release_date TEXT, raw TEXT)');
$save = $db->prepare('INSERT OR REPLACE INTO movie (id, imdb_id, title, release_date, raw) VALUES (?, ?, ?, ?, ?)');
$drop = $db->prepare('DELETE FROM movie WHERE id = ?');

$from = date('Y-m-d', strtotime('-1 day'));
$to = date('Y-m-d');
$page = 1;
do {
    $list = amodb('/discover/movie', [
        'primary_release_date.gte' => $from,
        'primary_release_date.lte' => $to,
        'sort_by' => 'primary_release_date.asc',
        'page' => $page,
    ]);
    foreach ($list['results'] as $row) {
        $movie = amodb('/movie/' . $row['id'], ['language' => 'en-US']);
        if ($movie === null) {
            $drop->execute([$row['id']]);
            continue;
        }
        $save->execute([$movie['id'], $movie['imdb_id'] ?? null, $movie['title'], $movie['release_date'] ?? null, json_encode($movie)]);
        sleep(3);
    }
    $page++;
} while ($page <= min($list['total_pages'], 500));
```

Discover връща редове от списък, а не пълни записи. Това са 2 от 20-те резултата на страница 1. Останалите полета четете от `/3/movie/{id}`.

```json
{
  "page": 1,
  "results": [
    {
      "adult": false,
      "backdrop_path": "/siepLRGVjM8yLKppApkD3uSh8Y0.jpg",
      "genre_ids": [
        35
      ],
      "id": 1800227,
      "original_language": "en",
      "original_title": "Sly's Pack",
      "overview": "Nesmith, Gary, & Tony are smoking weed on the roof of a parking garage, but a...",
      "popularity": 0.0071,
      "poster_path": "/3HpIWZUI7jmpKZkfZNdchS2WsvN.jpg",
      "release_date": "2026-10-17",
      "title": "Sly's Pack",
      "video": false,
      "vote_average": 0,
      "vote_count": 0
    },
    {
      "adult": false,
      "backdrop_path": null,
      "genre_ids": [
        99
      ],
      "id": 1800168,
      "original_language": "en",
      "original_title": "The Good Life",
      "overview": "The Good LIfe is based on the best-selling book by Drs. Robert Waldinger and...",
      "popularity": 0.0143,
      "poster_path": null,
      "release_date": "2026-10-17",
      "title": "The Good Life",
      "video": false,
      "vote_average": 0,
      "vote_count": 0
    }
  ],
  "total_pages": 15,
  "total_results": 299
}
```

## Попълване и обновяване на таблиците

| Задача                    | Извикване                                                                                                             | Ограничения                                                                                                                                    |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| Първо зареждане           | `GET /3/discover/movie` със `sort_by` и прозорец от дати                                                              | `page` от 1 до 500, до 20 резултата на страница, или 10 000 на заявка. За да отидете отвъд, разбивайте по `primary_release_date.gte` и `.lte`. |
| Нови премиери             | `GET /3/discover/movie` с `primary_release_date.gte`, зададено на последното ви изпълнение, и `GET /3/movie/upcoming` | Кешира се 30 минути.                                                                                                                           |
| Обновяване на редове      | `GET /3/movie/{movie_id}` за редове, по-стари от 6 часа                                                               | Няма поток changes. Обновявайте заглавията, които потребителите отварят, а останалите по-рядко.                                                |
| Свързване на собствени id | `GET /3/find/{external_id}`                                                                                           | Едно id на извикване, източникът се избира с `external_source`.                                                                                |
| Отложено попълване        | `GET /3/movie/{movie_id}`, когато потребител отвори заглавие                                                          | Записвайте отговора с времеви печат.                                                                                                           |

Прозорецът на странициране е основното решение в проектирането. Когато `total_pages` в отговор е над 500, прозорецът съдържа над 10 000 реда, затова го режете на половини, докато се събере. За последна година ви трябват месеци, а един ден премиери са няколкостотин заглавия. Пазете приключената част, за да може срутило се изпълнение да продължи. Правилата за съпоставяне при свързването са на страницата [търсене по външен идентификатор](https://amodb.dev/bg/find-by-external-id/).

## Оразмеряване на синхронизацията

Всеки ред, който обновявате, струва едно четене на детайли. План от 20 заявки в минута дава 1200 извиквания на час, 40 дава 2400, а 120 дава 7200. Една страница на discover изброява 20 id с едно извикване. Пускайте обновяването в часове с по-малко натоварване, ако приложението ви споделя ключа, защото лимитът е на ключ, а не на скрипт. Вижте [лимити на заявките](https://amodb.dev/bg/rate-limits/) за заглавките, които показват какво остава в прозореца.

## Кеширане на два слоя

| Слой           | Какво държи                                | TTL                                                                            |
| -------------- | ------------------------------------------ | ------------------------------------------------------------------------------ |
| Edge кеш       | Детайли и участници                        | 6 часа                                                                         |
| Edge кеш       | Списъци на discover, тенденции и популярни | 30 минути                                                                      |
| Edge кеш       | Търсене                                    | 10 минути                                                                      |
| Edge кеш       | Конфигурация                               | 24 часа                                                                        |
| Edge кеш       | Изображения                                | 30 дни                                                                         |
| Вашите таблици | Редовете, които пазите                     | Докато правилото за възраст не каже да теглите отново, но не по-рано от 6 часа |

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

## Как се сравнява

| Възможност                | Сами да обработвате страници               | Статични файлове с набори от данни            | amodb                                                      |
| ------------------------- | ------------------------------------------ | --------------------------------------------- | ---------------------------------------------------------- |
| Актуалност                | Колкото е актуално последното ви обхождане | Колкото е актуален последният публикуван файл | Детайли, кеширани 6 часа, теглене по възраст               |
| Инкрементални обновявания | Ново обхождане и сравнение                 | Изтегляне на нов файл                         | Discover с прозорец по дата на излизане, без поток changes |
| Id между обектите         | URL адреси на страници                     | Определя се от издателя                       | Числови id, `imdb_id` и `/3/find`                          |
| Какво поддържате          | Краулъри и хранилище                       | Хранилище и задача за импорт                  | Хранилище и скрипт за синхронизация                        |
| Лимит на заявките         | Определя се от сайтовете, които обхождате  | Не се прилага                                 | 20, 40 или 120 заявки в минута, на ключ                    |
| Езици на запис            | Каквото предлага всяка страница            | Зависи от файловете                           | 14, избират се с `language`                                |

## Цени

Първото зареждане е скъпата част и е ограничено от заявките ви в минута. Изберете 20, 40 или 120 в минута на страницата с [цените](https://amodb.dev/bg/pricing/). Плащате за 1, 3, 6, 12 или 24 месеца с отстъпка 0, 10, 20, 30 или 40 процента. Нищо не се подновява автоматично, няма безплатен план и всеки план чете същите данни.

## Въпроси и отговори

### Как да поддържам локалното копие актуално?

amodb няма поток changes, затова обновявайте по възраст. Детайлите се кешират на edge за 6 часа, така че теглете ред отново не по-рано. Вземайте новите премиери с discover и primary_release_date.gte, зададено на последното ви изпълнение.

### Как да заредя първото копие?

Обходете /3/discover/movie със страници от 1 до 500 (до 20 резултата всяка, или 10 000 на заявка) и разбивайте по прозорци на primary_release_date, за да стигнете по-далеч. Само март 2025 съдържа около 4400 заглавия. После четете /3/movie/{id} за всяко id, което пазите.

### Колко време отнема първото зареждане при моя лимит на заявките?

При 20 заявки в минута можете да направите 1200 извиквания на час, при 40 са 2400, а при 120 са 7200. Разделете броя на нужните четения на детайли на тази цифра, за да планирате изпълнението.

### Мога ли да свържа id на amodb с id, които вече пазя?

Да. /3/find/{external_id} приема imdb_id, tvdb_id, wikidata_id и kinopoisk_id и връща съответния запис на amodb. Записите за филми носят и imdb_id, така че свързването работи в двете посоки.

### Има ли безплатен план за изграждане на база данни?

Не. Достъпът е предплатен за 1, 3, 6, 12 или 24 месеца и не се подновява сам. Всеки план чете същите данни, така че по-големият план само ускорява първото зареждане и обновяванията.

## Свързани страници

- [API за детайли на филм](https://amodb.dev/bg/movies/): API за детайли на филм със същите пътища и JSON като TMDB v3. Един филм по id, а актьори, рейтинги и настроения през append_to_response, на 14 езика.
- [API за детайли на личност](https://amodb.dev/bg/people/): API за детайли на личност със същите пътища и JSON като TMDB v3. Актьор или член на екип по id с биография, филмография, външни id и списък с популярни.
- [API за колекции](https://amodb.dev/bg/collections/): API за колекции от филми с пътища на TMDB v3: франчайз по id с всичките му части, belongs_to_collection във филм и търсене на колекции по име.
- [Компании и мрежи](https://amodb.dev/bg/companies-networks/): Търсете продуцентски компании и мрежи с пътища на TMDB v3. Четете име, държава и лого по id, после филтрирайте discover по компания или мрежа.
- [Търсене по външен идентификатор](https://amodb.dev/bg/find-by-external-id/): Търсете филм, сериал или личност по IMDb, TVDB, Wikidata или Kinopoisk id с ендпойнта find на TMDB и четете външни id и факти от Wikidata за заглавие.
- [Лимити на заявките](https://amodb.dev/bg/rate-limits/): amodb ограничава всеки ключ по заявки в минута в плъзгащ се прозорец от 60 секунди: 20, 40 или 120. Заглавки за лимита и обработка на 429 с Retry-After.

Обновено: 2026-10-18. Source: https://amodb.dev/bg/movie-database-api/
