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

> Используйте amodb как источник для собственной базы фильмов. Фильмы, люди, компании, коллекции, ключевые слова и жанры имеют общие числовые id, поэтому строки легко связываются. Заполняйте базу постраничным discover по окнам дат выхода, обновляйте строки по возрасту и сопоставляйте свои id через поиск по внешнему ID. JSON TMDB v3, от 20 до 120 запросов в минуту.

## Собираем собственную базу фильмов через API

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

Что вы получаете:

- Шесть связанных типов сущностей со стабильными числовыми 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/ru/credits/) как ключ последней. Списки полей приведены на страницах [фильмы](https://amodb.dev/ru/movies/), [люди](https://amodb.dev/ru/people/) и [коллекции](https://amodb.dev/ru/collections/).

## Начало работы в 3 шага

1. Сравните три значения запросов в минуту на странице [цены](https://amodb.dev/ru/pricing/). Больший лимит ускоряет первую загрузку, больше ничего не меняется.
2. Создайте ключ в личном кабинете и храните его в переменной окружения.
3. Вызовите `/3/discover/movie` для окна дат выхода в один день, затем запросите каждый id из списка.

## Пример запроса

Скрипт на PHP получает через discover фильмы, вышедшие вчера и сегодня, и записывает каждую запись в таблицу SQLite. Между чтениями данных он ждет 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 часов                                                                     | Ленты изменений нет. Обновляйте фильмы, которые открывают пользователи, а остальные реже.                                                       |
| Сопоставление своих id | `GET /3/find/{external_id}`                                                                                            | Один id на вызов, источник выбирается через `external_source`.                                                                                  |
| Ленивое заполнение     | `GET /3/movie/{movie_id}`, когда пользователь открывает фильм                                                          | Сохраняйте ответ с меткой времени.                                                                                                              |

Окно постраничной выборки: главное проектное решение. Если `total_pages` в ответе больше 500, в окне больше 10 000 строк, поэтому делите его пополам, пока оно не уместится. Недавнему году нужны месяцы, а один день релизов это несколько сотен фильмов. Сохраняйте завершенный срез, чтобы упавший запуск мог продолжиться. Правила сопоставления описаны на странице [поиск по внешнему ID](https://amodb.dev/ru/find-by-external-id/).

## Оценка объема синхронизации

Каждая обновляемая строка стоит одно чтение данных. Тариф на 20 запросов в минуту дает 1 200 вызовов в час, 40 дает 2 400, а 120 дает 7 200. Страница discover перечисляет 20 id за один вызов. Запускайте обновление в непиковые часы, если приложение использует тот же ключ, потому что лимит действует на ключ, а не на скрипт. Заголовки, показывающие остаток в окне, описаны на странице [лимиты запросов](https://amodb.dev/ru/rate-limits/).

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

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

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

## Сравнение

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

## Цены

Первая загрузка самая затратная часть, и она ограничена вашим числом запросов в минуту. Выберите 20, 40 или 120 в минуту на странице [цены](https://amodb.dev/ru/pricing/). Оплатите 1, 3, 6, 12 или 24 месяца со скидкой 0, 10, 20, 30 или 40 процентов. Автоматического продления нет, бесплатного тарифа нет, а все тарифы читают одни и те же данные.

## Вопросы и ответы

### Как поддерживать локальную копию свежей?

В amodb нет ленты изменений, поэтому обновляйте записи по возрасту. Данные хранятся в edge-кэше 6 часов, поэтому запрашивайте запись заново не чаще. Новые релизы находите через discover, задав primary_release_date.gte равным дате вашего последнего запуска.

### Как загрузить первую копию?

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

### Сколько займет первая загрузка при моем лимите запросов?

При 20 запросах в минуту можно сделать 1 200 вызовов в час, при 40 это 2 400, при 120 это 7 200. Разделите число нужных чтений данных на эту цифру, чтобы спланировать запуск.

### Можно ли связать 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/ru/movies/): API деталей фильма с теми же путями и JSON, что в TMDB v3. Получите фильм по ID, добавьте актеров, рейтинги и настроения через append_to_response, на 14 языках.
- [API деталей человека](https://amodb.dev/ru/people/): API деталей человека с теми же путями и JSON, что в TMDB v3. Получайте актера или члена съемочной группы по ID: биография, фильмография, внешние ID, популярные.
- [API коллекций](https://amodb.dev/ru/collections/): API коллекций фильмов с путями TMDB v3: получите франшизу по ID со всеми частями, прочитайте belongs_to_collection у фильма и найдите коллекцию по названию.
- [Компании и телесети](https://amodb.dev/ru/companies-networks/): Ищите киностудии и телесети по путям TMDB v3: читайте название, страну и логотип по ID, затем фильтруйте discover по ID компании или телесети.
- [Поиск по внешнему ID](https://amodb.dev/ru/find-by-external-id/): Найдите фильм, сериал или персону по ID IMDb, TVDB, Wikidata или Kinopoisk через эндпоинт find TMDB, а также прочитайте внешние ID и факты Wikidata о проекте.
- [Лимиты запросов](https://amodb.dev/ru/rate-limits/): amodb ограничивает ключ запросами в минуту в скользящем окне 60 секунд: 20, 40 или 120 по тарифу. Читайте заголовки лимита и обрабатывайте 429 с Retry-After.

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