# API databáze filmů pro váš vlastní katalog

> Používejte amodb jako zdroj pro vlastní databázi filmů. Filmy, osoby, společnosti, kolekce, klíčová slova a žánry sdílejí číselná ID, takže se řádky čistě spojují. První data načtěte stránkováním discover v oknech dat premiér, řádky obnovujte podle stáří a vlastní ID přiřaďte přes hledání podle externího ID. JSON TMDB v3, 20 až 120 požadavků za minutu.

## Postavte si vlastní databázi filmů z API

amodb je nezávislé API, které mluví protokolem TMDB v3. Filmy, osoby, společnosti, kolekce, klíčová slova i žánry mají číselná ID a odkazují na sebe, takže z něj můžete plnit SQL tabulky a udržovat je aktuální. Tabulky naplňte stránkováním discover, obnovujte je podle stáří a vlastní identifikátory přiřazujte přes `find`. amodb nemá feed změn, takže obnova je prosté opětovné stažení řádků, které ponecháváte.

Co dostanete:

- Šest propojených typů entit se stálými číselnými ID.
- Stránkování discover pro první načtení: až 20 výsledků na stránku, 500 stránek na dotaz.
- Okna dat premiér v discover, kterými rozdělíte první načtení a vypíšete nové premiéry.
- Vyhledání podle externích ID `imdb_id`, `tvdb_id`, `wikidata_id` a `kinopoisk_id`.

## Jaká data dostanete

Toto je datový model. Každý řádek je jedna tabulka v relační kopii.

| Entita        | Čtení                               | Klíč            | Odkazuje na                                                                                        |
| ------------- | ----------------------------------- | --------------- | -------------------------------------------------------------------------------------------------- |
| Film          | `GET /3/movie/{movie_id}`           | `id`, `imdb_id` | `genres[].id`, `production_companies[].id`, `belongs_to_collection.id`                             |
| Osoba         | `GET /3/person/{person_id}`         | `id`, `imdb_id` | Filmy přes `/3/movie/{movie_id}/credits`                                                           |
| Společnost    | `GET /3/company/{company_id}`       | `id`            | Filmy přes `with_companies` v discover. `parent_company` je vždy `null` a `description` je prázdné |
| Kolekce       | `GET /3/collection/{collection_id}` | `id`            | `parts[]`, seznam filmů                                                                            |
| Klíčové slovo | `GET /3/keyword/{keyword_id}`       | `id`            | Filmy přes `/3/keyword/{keyword_id}/movies` nebo `with_keywords`                                   |
| Žánr          | `GET /3/genre/movie/list`           | `id`            | `genres[].id` u filmů                                                                              |

Vazby mnoho k mnoha potřebují spojovací tabulky: `movie_genre`, `movie_company`, `movie_keyword` a `movie_credit`. Jako klíč poslední použijte `credit_id` ze stránky [obsazení a štáb](https://amodb.dev/cs/credits/). Seznamy polí jsou na stránkách [filmy](https://amodb.dev/cs/movies/), [osoby](https://amodb.dev/cs/people/) a [kolekce](https://amodb.dev/cs/collections/).

## Začněte ve 3 krocích

1. Porovnejte tři rychlosti požadavků na stránce [ceník](https://amodb.dev/cs/pricing/). Vyšší rychlost zkrátí první načtení, nic jiného se nemění.
2. Vytvořte klíč v panelu účtu a držte ho v proměnné prostředí.
3. Zavolejte `/3/discover/movie` pro jednodenní okno dat premiér a pak načtěte každé ID ze seznamu.

## Příklad požadavku

Skript v PHP vypíše filmy vydané včera a dnes přes discover a každý záznam uloží (upsert) do tabulky SQLite. Mezi čteními detailů čeká 3 sekundy, aby zůstal pod 20 požadavky za minutu, po `Retry-After` zopakuje 429 a maže řádky, jejichž ID nyní vrací 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 vrací řádky seznamu, ne plné záznamy. Toto jsou 2 z 20 výsledků na stránce 1. Ostatní pole načtěte z `/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
}
```

## Plnění a obnova tabulek

| Úloha                | Volání                                                                                                    | Limity                                                                                                                         |
| -------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| První načtení        | `GET /3/discover/movie` se `sort_by` a oknem dat                                                          | `page` 1 až 500, až 20 výsledků na stránku, tedy 10 000 na dotaz. K překonání dělte podle `primary_release_date.gte` a `.lte`. |
| Nové premiéry        | `GET /3/discover/movie` s `primary_release_date.gte` nastaveným na poslední běh a `GET /3/movie/upcoming` | Cache 30 minut.                                                                                                                |
| Obnova řádků         | `GET /3/movie/{movie_id}` pro řádky starší než 6 hodin                                                    | Neexistuje feed změn. Obnovujte tituly, které uživatelé otevírají, a ostatní méně často.                                       |
| Spojení vlastních ID | `GET /3/find/{external_id}`                                                                               | Jedno ID na volání, zdroj se volí přes `external_source`.                                                                      |
| Líné plnění          | `GET /3/movie/{movie_id}`, když uživatel otevře titul                                                     | Odpověď uložte s časovým razítkem.                                                                                             |

Okno stránkování je hlavní návrhové rozhodnutí. Když je `total_pages` v odpovědi nad 500, okno obsahuje víc než 10 000 řádků, rozpůlte ho tedy, dokud se nevejde. Poslední rok potřebuje měsíce a jeden den premiér jsou několik set titulů. Ukládejte dokončený úsek, aby se spadlý běh mohl obnovit. Pravidla párování pro spojení jsou na stránce [hledání podle externího ID](https://amodb.dev/cs/find-by-external-id/).

## Dimenzování synchronizace

Každý obnovovaný řádek stojí jedno čtení detailu. Tarif s 20 požadavky za minutu dává 1 200 volání za hodinu, 40 dává 2 400 a 120 dává 7 200. Stránka discover vypíše 20 ID za jedno volání. Obnovu pouštějte mimo špičku, pokud aplikace sdílí klíč, protože limit platí na klíč, ne na skript. Hlavičky, které hlásí, co v okně zbývá, jsou na stránce [limity požadavků](https://amodb.dev/cs/rate-limits/).

## Cache ve dvou vrstvách

| Vrstva        | Obsahuje                               | TTL                                                                  |
| ------------- | -------------------------------------- | -------------------------------------------------------------------- |
| Cache na edge | Detaily a obsazení                     | 6 hodin                                                              |
| Cache na edge | Seznamy discover, trending a populární | 30 minut                                                             |
| Cache na edge | Vyhledávání                            | 10 minut                                                             |
| Cache na edge | Konfigurace                            | 24 hodin                                                             |
| Cache na edge | Obrázky                                | 30 dní                                                               |
| Vaše tabulky  | Řádky, které ponecháváte               | Dokud pravidlo stáří neřekne znovu načíst, nikdy dřív než za 6 hodin |

Cache na edge je sdílená mezi klíči, ale limit požadavků se vyhodnocuje před ní, takže zásah cache stále spotřebuje jeden požadavek z vaší minuty. Čtení řádku častěji než každých 6 hodin vrátí stejnou kopii a plýtvá kvótou. O novém načtení nechte rozhodnout pravidlo stáří.

## Jak si stojí v porovnání

| Schopnost               | Scrapování stránek vlastními silami | Statické soubory datasetu                   | amodb                                                 |
| ----------------------- | ----------------------------------- | ------------------------------------------- | ----------------------------------------------------- |
| Aktuálnost              | Tak čerstvé jako poslední crawl     | Tak čerstvé jako poslední zveřejněný soubor | Detaily v cache 6 hodin, obnova podle stáří           |
| Přírůstkové aktualizace | Znovu procházet a porovnávat        | Stáhnout nový soubor                        | Discover s oknem dat premiér, bez feedu změn          |
| ID napříč entitami      | URL stránek                         | Určuje vydavatel                            | Číselná ID, `imdb_id` a `/3/find`                     |
| Co provozujete          | Crawlery a úložiště                 | Úložiště a importní úloha                   | Úložiště a synchronizační skript                      |
| Limit požadavků         | Určují weby, které procházíte       | Netýká se                                   | 20, 40 nebo 120 požadavků za minutu, počítáno na klíč |
| Jazyky na záznam        | Co nabízí která stránka             | Záleží na souborech                         | 14, vybírané přes `language`                          |

## Ceník

Nákladné je první načtení a omezuje ho váš počet požadavků za minutu. Vyberte 20, 40 nebo 120 za minutu na stránce [ceník](https://amodb.dev/cs/pricing/). Platíte za 1, 3, 6, 12 nebo 24 měsíců se slevou 0, 10, 20, 30 nebo 40 procent. Nic se neobnovuje automaticky, bezplatný tarif neexistuje a každý tarif čte stejná data.

## Otázky a odpovědi

### Jak udržím lokální kopii aktuální?

amodb nemá feed změn, takže obnovujte podle stáří. Detaily se na edge cachují 6 hodin, takže řádek znovu nenačítejte dřív. Nové premiéry zachytíte přes discover s primary_release_date.gte nastaveným na poslední běh.

### Jak načtu první kopii?

Projděte /3/discover/movie se stránkami 1 až 500 (až 20 výsledků na stránku, tedy 10 000 na dotaz) a dál dělte podle oken primary_release_date. Samotný březen 2025 obsahuje asi 4 400 titulů. Pak pro každé ponechané ID přečtěte /3/movie/{id}.

### Jak dlouho trvá první načtení při mém limitu požadavků?

Při 20 požadavcích za minutu zvládnete 1 200 volání za hodinu, při 40 je to 2 400 a při 120 je to 7 200. Počet potřebných čtení detailů vydělte tímto číslem a naplánujete běh.

### Mohu spojit ID z amodb s ID, která už ukládám?

Ano. /3/find/{external_id} přijímá imdb_id, tvdb_id, wikidata_id a kinopoisk_id a vrací odpovídající záznam amodb. Záznamy filmů nesou také imdb_id, takže spojení funguje oběma směry.

### Existuje bezplatný tarif pro budování databáze?

Ne. Přístup je předplacený na 1, 3, 6, 12 nebo 24 měsíců a sám se neobnovuje. Všechny tarify čtou stejná data, takže větší tarif jen urychlí první načtení i obnovy.

## Související stránky

- [API detailu filmu](https://amodb.dev/cs/movies/): API detailu filmu se stejnými cestami a JSON jako TMDB v3. Načtěte film podle ID, přidejte obsazení, hodnocení a nálady přes append_to_response, 14 jazyků.
- [API detailu osoby](https://amodb.dev/cs/people/): API detailu osoby se stejnými cestami a JSON jako TMDB v3. Herec či člen štábu podle ID s biografií, filmografií, externími ID a seznamem populárních osob.
- [API kolekcí](https://amodb.dev/cs/collections/): API kolekcí filmů s cestami TMDB v3: načtěte franšízu podle ID se všemi filmy, čtěte belongs_to_collection u filmu a hledejte kolekce podle názvu.
- [Společnosti a televizní sítě](https://amodb.dev/cs/companies-networks/): Produkční společnosti a televizní sítě přes cesty TMDB v3. Přečtěte název, zemi a logo podle ID a filtrujte discover podle ID společnosti nebo sítě.
- [Hledání podle externího ID](https://amodb.dev/cs/find-by-external-id/): Najděte film, seriál nebo osobu podle ID z IMDb, TVDB, Wikidata nebo Kinopoisk přes endpoint find TMDB a čtěte externí ID a fakta z Wikidata o titulu.
- [Limity požadavků](https://amodb.dev/cs/rate-limits/): amodb omezuje klíč počtem požadavků za minutu v klouzavém okně 60 sekund: 20, 40 nebo 120 podle tarifu. Čtěte hlavičky limitu a řešte 429 pomocí Retry-After.

Aktualizováno: 2026-10-18. Source: https://amodb.dev/cs/movie-database-api/
