# API bază de date filme pentru propriul catalog

> Folosește amodb ca sursă pentru propria bază de date de filme. Filmele, persoanele, companiile, colecțiile, cuvintele-cheie și genurile au ID-uri numerice comune, deci rândurile se leagă curat. Încarcă prin paginarea discover pe ferestre de date, reîmprospătează după vechime, potrivește ID-uri prin căutarea după ID extern. JSON TMDB v3, 20 până la 120 de cereri pe minut.

## Construiește-ți propria bază de date de filme dintr-un API

amodb este un API independent care vorbește protocolul TMDB v3. Filmele, persoanele, companiile, colecțiile, cuvintele-cheie și genurile au toate ID-uri numerice și trimit unele la altele, așa că poți umple tabele SQL din el și le poți ține la zi. Încarcă tabelele cu paginarea discover, reîmprospătează-le după vechime și potrivește-ți propriii identificatori cu `find`. amodb nu are flux de modificări, așa că o reîmprospătare este pur și simplu o nouă preluare a rândurilor pe care le păstrezi.

Ce primești:

- Șase tipuri de entități legate, cu ID-uri numerice stabile.
- Paginare discover pentru prima încărcare: până la 20 de rezultate pe pagină, 500 de pagini pe interogare.
- Ferestre de date de lansare în discover, ca să tai prima încărcare în felii și să listezi lansările noi.
- Căutări după ID extern pentru `imdb_id`, `tvdb_id`, `wikidata_id` și `kinopoisk_id`.

## Ce date primești

Acesta este modelul de date. Fiecare rând este un tabel într-o copie relațională.

| Entitate     | Se citește cu                       | Cheie           | Se leagă de                                                                                             |
| ------------ | ----------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------- |
| Film         | `GET /3/movie/{movie_id}`           | `id`, `imdb_id` | `genres[].id`, `production_companies[].id`, `belongs_to_collection.id`                                  |
| Persoană     | `GET /3/person/{person_id}`         | `id`, `imdb_id` | Filme prin `/3/movie/{movie_id}/credits`                                                                |
| Companie     | `GET /3/company/{company_id}`       | `id`            | Filme prin `with_companies` în discover. `parent_company` este mereu `null`, iar `description` este gol |
| Colecție     | `GET /3/collection/{collection_id}` | `id`            | `parts[]`, o listă de filme                                                                             |
| Cuvânt-cheie | `GET /3/keyword/{keyword_id}`       | `id`            | Filme prin `/3/keyword/{keyword_id}/movies` sau `with_keywords`                                         |
| Gen          | `GET /3/genre/movie/list`           | `id`            | `genres[].id` la filme                                                                                  |

Legăturile mulți la mulți cer tabele de joncțiune: `movie_genre`, `movie_company`, `movie_keyword` și `movie_credit`. Folosește `credit_id` din [credite](https://amodb.dev/ro/credits/) drept cheie pentru ultimul. Listele de câmpuri sunt la [filme](https://amodb.dev/ro/movies/), [persoane](https://amodb.dev/ro/people/) și [colecții](https://amodb.dev/ro/collections/).

## Începe în 3 pași

1. Compară cele trei ritmuri de cereri la [prețuri](https://amodb.dev/ro/pricing/). Un ritm mai mare scurtează prima încărcare, nimic altceva nu se schimbă.
2. Creează o cheie în panoul contului tău și păstrează-o într-o variabilă de mediu.
3. Apelează `/3/discover/movie` pentru o fereastră de o zi de date de lansare, apoi preia fiecare ID din listă.

## Exemplu de cerere

Scriptul PHP listează filmele lansate ieri și azi prin discover și face upsert pentru fiecare înregistrare într-un tabel SQLite. Doarme 3 secunde între citirile de detalii ca să rămână sub 20 de cereri pe minut, reîncearcă un 429 după `Retry-After` și șterge rândurile al căror ID întoarce acum 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 întoarce rânduri de listă, nu înregistrări complete. Acestea sunt 2 dintre cele 20 de rezultate de pe pagina 1. Citește `/3/movie/{id}` pentru restul câmpurilor.

```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
}
```

## Umple și reîmprospătează tabelele

| Sarcină                   | Apel                                                                                                        | Limite                                                                                                                                                        |
| ------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Prima încărcare           | `GET /3/discover/movie` cu `sort_by` și o fereastră de date                                                 | `page` de la 1 la 500, până la 20 de rezultate pe pagină, deci 10,000 pe interogare. Împarte pe `primary_release_date.gte` și `.lte` ca să mergi mai departe. |
| Lansări noi               | `GET /3/discover/movie` cu `primary_release_date.gte` setat la ultima ta rulare, și `GET /3/movie/upcoming` | Ținute în cache 30 de minute.                                                                                                                                 |
| Reîmprospătare rânduri    | `GET /3/movie/{movie_id}` pentru rândurile mai vechi de 6 ore                                               | Nu există flux de modificări. Reîmprospătează titlurile pe care le deschid utilizatorii, iar restul mai rar.                                                  |
| Legarea propriilor ID-uri | `GET /3/find/{external_id}`                                                                                 | Un ID pe apel, sursa se alege cu `external_source`.                                                                                                           |
| Umplere la cerere         | `GET /3/movie/{movie_id}` când un utilizator deschide un titlu                                              | Stochează răspunsul cu un marcaj de timp.                                                                                                                     |

Fereastra de paginare este principala alegere de proiectare. Când `total_pages` dintr-un răspuns este peste 500, fereastra conține mai mult de 10,000 de rânduri, așa că împarte-o la jumătate până încape. Pentru un an recent îți trebuie luni, iar o singură zi de lansări înseamnă câteva sute de titluri. Stochează felia pe care ai terminat-o, ca o rulare întreruptă să poată continua. Regulile de potrivire pentru legare sunt la [căutare după ID extern](https://amodb.dev/ro/find-by-external-id/).

## Dimensionarea sincronizării

Fiecare rând pe care îl reîmprospătezi costă o citire de detalii. Un plan de 20 de cereri pe minut dă 1,200 de apeluri pe oră, cel de 40 dă 2,400, iar cel de 120 dă 7,200. O pagină discover listează 20 de ID-uri pentru un singur apel. Rulează reîmprospătarea în afara orelor de vârf dacă aplicația ta folosește aceeași cheie, pentru că limita este pe cheie, nu pe script. Vezi [limite de cereri](https://amodb.dev/ro/rate-limits/) pentru antetele care arată ce a mai rămas din fereastră.

## Cache pe două straturi

| Strat            | Conține                                 | TTL                                                                                       |
| ---------------- | --------------------------------------- | ----------------------------------------------------------------------------------------- |
| Cache la margine | Detalii și credite                      | 6 ore                                                                                     |
| Cache la margine | Liste discover, în tendințe și populare | 30 de minute                                                                              |
| Cache la margine | Căutare                                 | 10 minute                                                                                 |
| Cache la margine | Configurație                            | 24 de ore                                                                                 |
| Cache la margine | Imagini                                 | 30 de zile                                                                                |
| Tabelele tale    | Rândurile pe care le păstrezi           | Până când regula ta de vechime spune să le preiei din nou, niciodată mai devreme de 6 ore |

Cache-ul la margine este partajat între chei, dar limita de cereri rulează înaintea lui, așa că o lovitură de cache consumă tot o cerere din minutul tău. Recitirea unui rând mai des de 6 ore întoarce aceeași copie și irosește cota. Lasă o regulă de vechime să decidă când preiei din nou.

## Cum se compară

| Capacitate               | Extragi singur paginile                     | Fișiere de set de date statice            | amodb                                                               |
| ------------------------ | ------------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------- |
| Prospețime               | Cât de proaspăt e ultimul tău crawl         | Cât de proaspăt e ultimul fișier publicat | Detalii în cache 6 ore, preluare după vechime                       |
| Actualizări incrementale | Reiei crawl-ul și compari                   | Descarci un fișier nou                    | Discover cu o fereastră de date de lansare, fără flux de modificări |
| ID-uri între entități    | URL-uri de pagini                           | Definite de editor                        | ID-uri numerice, `imdb_id` și `/3/find`                             |
| Ce rulezi                | Crawlere și stocare                         | Stocare și un job de import               | Stocare și un script de sincronizare                                |
| Limită de cereri         | Stabilită de site-urile pe care le parcurgi | Nu se aplică                              | 20, 40 sau 120 de cereri pe minut, numărate pe cheie                |
| Limbi pe înregistrare    | Ce oferă fiecare pagină                     | Depinde de fișiere                        | 14, alese cu `language`                                             |

## Prețuri

Prima încărcare este partea scumpă și este limitată de numărul tău de cereri pe minut. Alege 20, 40 sau 120 pe minut la [prețuri](https://amodb.dev/ro/pricing/). Plătești pentru 1, 3, 6, 12 sau 24 de luni, cu reduceri de 0, 10, 20, 30 sau 40 la sută. Nimic nu se reînnoiește automat, nu există nivel gratuit, iar fiecare plan citește aceleași date.

## Întrebări și răspunsuri

### Cum îmi păstrez proaspătă o copie locală?

amodb nu are flux de modificări, așa că reîmprospătează după vechime. Detaliile sunt ținute în cache la margine 6 ore, deci reia un rând nu mai devreme de atât. Preia lansările noi cu discover și primary_release_date.gte setat la ultima ta rulare.

### Cum încarc prima copie?

Parcurge /3/discover/movie cu page de la 1 la 500 (până la 20 de rezultate fiecare, deci 10,000 pe interogare) și împarte pe ferestre primary_release_date ca să mergi mai departe. Doar martie 2025 are aproximativ 4,400 de titluri. Apoi citește /3/movie/{id} pentru fiecare ID pe care îl păstrezi.

### Cât durează o primă încărcare la limita mea de cereri?

La 20 de cereri pe minut poți face 1,200 de apeluri pe oră, la 40 sunt 2,400, iar la 120 sunt 7,200. Împarte numărul de citiri de detalii de care ai nevoie la acea cifră ca să planifici rularea.

### Pot lega ID-urile amodb de ID-urile pe care le stochez deja?

Da. /3/find/{external_id} acceptă imdb_id, tvdb_id, wikidata_id și kinopoisk_id și întoarce înregistrarea amodb corespunzătoare. Fișele de film au și imdb_id, deci legătura funcționează în ambele sensuri.

### Există un nivel gratuit pentru construirea unei baze de date?

Nu. Accesul este plătit în avans pentru 1, 3, 6, 12 sau 24 de luni și nu se reînnoiește singur. Fiecare plan citește aceleași date, deci un plan mai mare doar face prima încărcare și reîmprospătările mai rapide.

## Pagini conexe

- [API detalii film](https://amodb.dev/ro/movies/): API detalii film cu aceleași căi și același JSON ca TMDB v3. Preia un film după ID, adaugă credite, evaluări și atmosferă cu append_to_response, în 14 limbi.
- [API detalii persoană](https://amodb.dev/ro/people/): API detalii persoană cu căile și JSON-ul TMDB v3. Preia un actor sau membru al echipei după ID, cu biografie, filmografie, ID-uri externe și lista populară.
- [API colecții](https://amodb.dev/ro/collections/): API colecții de filme cu căi TMDB v3: preia o franciză după ID cu toate părțile, citește belongs_to_collection la un film și caută colecții după nume.
- [Companii și rețele](https://amodb.dev/ro/companies-networks/): Caută companii de producție și rețele TV cu căi TMDB v3. Citește numele, țara și logoul după ID, apoi filtrează discover după ID-ul unei companii sau rețele.
- [Căutare după ID extern](https://amodb.dev/ro/find-by-external-id/): Caută un film, serial sau o persoană după ID IMDb, TVDB, Wikidata sau Kinopoisk cu endpoint-ul find și citește ID-urile externe și faptele Wikidata.
- [Limite de cereri](https://amodb.dev/ro/rate-limits/): amodb limitează fiecare cheie în cereri pe minut, în fereastră glisantă de 60 de secunde: 20, 40 sau 120. Citește antetele și tratează 429 cu Retry-After.

Actualizat: 2026-10-18. Source: https://amodb.dev/ro/movie-database-api/
