Discover API

Discover wypisuje filmy pod GET /3/discover/movie i seriale pod GET /3/discover/tv, filtrowane i sortowane według wybranych parametrów: gatunek, obsada, ekipa, firma, słowo kluczowe, daty, ocena, głosy, czas trwania, język i dostawca streamingu. JSON odpowiada TMDB v3, a wyniki są w cache przez 30 minut.

Zaktualizowano Zobacz jako Markdown

Discover dla filmów

GET /3/discover/movie zwraca listę z paginacją filmów pasujących do wszystkich wysłanych filtrów, w wybranej kolejności. To endpoint do stron przeglądania, list „najlepszych” i rekomendacji według faset i nie potrzebuje tekstu query. Gdy masz tytuł wpisany przez użytkownika, użyj zamiast niego wyszukiwania.

Przykład wypisuje filmy science fiction (ID gatunku 878) z co najmniej 1000 głosów, najlepiej oceniane na początku.

bashjspyphpgo
curl -sSf --get "https://api.amodb.dev/3/discover/movie" \
  --data-urlencode "with_genres=878" \
  --data-urlencode "sort_by=vote_average.desc" \
  --data-urlencode "vote_count.gte=1000" \
  --data-urlencode "language=en-US" \
  -H "Authorization: Bearer $AMODB_KEY"
const params = new URLSearchParams({
  with_genres: '878',
  sort_by: 'vote_average.desc',
  'vote_count.gte': '1000',
  language: 'en-US',
});
const res = await fetch(`https://api.amodb.dev/3/discover/movie?${params}`, {
  headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` },
});
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { results, total_pages } = await res.json();
console.log(`page 1 of ${total_pages}`);
for (const m of results.slice(0, 5)) console.log(m.vote_average, m.title, m.release_date);
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/discover/movie",
    params={
        "with_genres": 878,
        "sort_by": "vote_average.desc",
        "vote_count.gte": 1000,
        "language": "en-US",
    },
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
data = r.json()
print("page 1 of", data["total_pages"])
for m in data["results"][:5]:
    print(m["vote_average"], m["title"], m["release_date"])
<?php
$url = 'https://api.amodb.dev/3/discover/movie?' . http_build_query([
    'with_genres' => 878,
    'sort_by' => 'vote_average.desc',
    'vote_count.gte' => 1000,
    'language' => 'en-US',
]);
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 10,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('AMODB_KEY')],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
    throw new RuntimeException("amodb returned $status");
}
$data = json_decode($body, true);
foreach (array_slice($data['results'], 0, 5) as $m) {
    echo $m['vote_average'], ' ', $m['title'], PHP_EOL;
}
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"time"
)

type Page struct {
	TotalPages int `json:"total_pages"`
	Results    []struct {
		Title       string  `json:"title"`
		ReleaseDate string  `json:"release_date"`
		VoteAverage float64 `json:"vote_average"`
	} `json:"results"`
}

func main() {
	q := url.Values{
		"with_genres":    {"878"},
		"sort_by":        {"vote_average.desc"},
		"vote_count.gte": {"1000"},
		"language":       {"en-US"},
	}
	req, _ := http.NewRequest("GET", "https://api.amodb.dev/3/discover/movie?"+q.Encode(), nil)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("AMODB_KEY"))
	client := &http.Client{Timeout: 10 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		panic(res.Status)
	}
	var p Page
	if err := json.NewDecoder(res.Body).Decode(&p); err != nil {
		panic(err)
	}
	fmt.Println("pages:", p.TotalPages)
	for _, m := range p.Results {
		fmt.Println(m.VoteAverage, m.Title, m.ReleaseDate)
	}
}

Parametry

  • api_keyqueryjeden z dwóch
    Twój klucz. Użyj go albo nagłówka Authorization: Bearer.
  • sort_byquery
    Pole i kierunek, na przykład vote_average.desc. Pola: popularity, vote_average, vote_count, primary_release_date, revenue, title, original_title, każde z .asc lub .desc. title i original_title sortują według tytułu oryginalnego. Nieznana wartość wraca do popularity.desc, które jest też domyślne.
  • with_genresquery
    ID gatunków. Przecinek oznacza AND, znak kreski pionowej OR.
  • without_genresquery
    ID gatunków do wykluczenia.
  • with_cast, with_crewquery
    ID osób. Znajdziesz je przez wyszukiwanie.
  • with_peoplequery
    ID osób, które występują jako obsada lub ekipa.
  • with_companies, without_companiesquery
    ID firm produkcyjnych do wymagania lub wykluczenia. Przecinek i kreska pionowa działają jak w with_genres.
  • with_keywords, without_keywordsquery
    ID słów kluczowych do wymagania lub wykluczenia. Zobacz słowa kluczowe.
  • with_origin_countryquery
    Dwuliterowy kod kraju produkcji wielkimi literami, na przykład FR.
  • primary_release_yearquery
    Czterocyfrowy rok głównej daty premiery.
  • yearquery
    Czterocyfrowy rok. Pasuje do dowolnej daty premiery w tym roku, więc zwraca więcej tytułów niż primary_release_year.
  • primary_release_date.gte, primary_release_date.ltequery
    Dolna i górna granica głównej daty premiery, YYYY-MM-DD.
  • release_date.gte, release_date.ltequery
    Dolna i górna granica dowolnej daty premiery w dowolnym kraju, YYYY-MM-DD.
  • regionquery
    Dwuliterowy kod kraju wielkimi literami. Zastępuje release_date w każdym wyniku datą w tym kraju. Nie usuwa tytułów.
  • certification_country, certificationquery
    Filtr klasyfikacji wiekowej, na przykład US i PG. certification jest ignorowane bez kraju. certification.gte i certification.lte dają zakres.
  • vote_average.gte, vote_average.ltequery
    Minimalna i maksymalna średnia ocena, od 0 do 10.
  • vote_count.gte, vote_count.ltequery
    Minimalna i maksymalna liczba głosów.
  • with_runtime.gte, with_runtime.ltequery
    Minimalny i maksymalny czas trwania w minutach.
  • with_original_languagequery
    Język oryginału jako dwuliterowy kod, na przykład fr lub ko.
  • with_watch_providersquery
    ID dostawców. Wymaga watch_region i bez niego jest ignorowane. ID pochodzą ze strony gatunki i słowniki.
  • watch_regionquery
    Dwuliterowy kod kraju wielkimi literami dla dostępności u dostawcy.
  • include_adultquery
    Przyjmowany i ignorowany. Tytuły dla dorosłych nigdy nie są zwracane.
  • languagequery
    Tag TMDB, na przykład en-US lub pl-PL. Obsługiwanych jest 14 języków bazowych. Domyślnie en-US.
  • pagequery
    Numer strony od 1 do 500. Domyślnie 1.

Pola odpowiedzi

PoleTypUwagi
page, total_pages, total_resultsintegerPaginacja dla tego zestawu filtrów. Szerokie filtry zgłaszają najwyżej 1001 stron i 20001 wyników, ale czytać można tylko strony od 1 do 500.
resultsarrayDo 20 filmów. Puste, gdy żaden tytuł nie spełnia wszystkich filtrów.
idintegerID filmu dla szczegółów filmu.
title, original_title, overviewstringTekst zlokalizowany i tytuł oryginalny.
original_languagestringDwuliterowy kod języka, w którym nakręcono film.
release_datestringYYYY-MM-DD.
genre_idsarray of integersTylko ID. Zamień je na nazwy przez /genre/movie/list.
poster_path, backdrop_pathstring lub nullDołącz do https://img.amodb.dev/t/p/{size}.
vote_average, vote_count, popularitynumberOcena i wartości rankingowe.
adult, videobooleanadult jest zawsze false.

Przykładowa odpowiedź

JSON
{
  "page": 1,
  "results": [
    {
      "adult": false,
      "backdrop_path": "/wLWvHcQz7N13DvSOTV7bHgwGXpT.jpg",
      "genre_ids": [878, 12],
      "id": 687163,
      "original_language": "en",
      "original_title": "Project Hail Mary",
      "overview": "Science teacher Ryland Grace wakes up on a spaceship light years from home with no recollection of who he i...",
      "popularity": 101.0341,
      "poster_path": "/yihdXomYb5kTeSivtFndMy5iDmf.jpg",
      "release_date": "2026-03-15",
      "title": "Project Hail Mary",
      "video": false,
      "vote_average": 8.635,
      "vote_count": 8354
    },
    {
      "adult": false,
      "backdrop_path": "/Ys8UIGWJpd2TMuQk8fU77W3mBz.jpg",
      "genre_ids": [12, 18, 878],
      "id": 157336,
      "original_language": "en",
      "original_title": "Interstellar",
      "overview": "The adventures of a group of explorers who make use of a newly discovered wormhole to surpass the limitatio...",
      "popularity": 74.3949,
      "poster_path": "/yQvGrMoipbRoddT0ZR8tPoR7NfX.jpg",
      "release_date": "2014-11-04",
      "title": "Interstellar",
      "video": false,
      "vote_average": 8.491,
      "vote_count": 41526
    },
    {
      "adult": false,
      "backdrop_path": "/tanwf7KOwQ6dxZzehKsXkffIJOd.jpg",
      "genre_ids": [878, 28, 12],
      "id": 969681,
      "original_language": "en",
      "original_title": "Spider-Man: Brand New Day",
      "overview": "Fighting crime full-time as Spider-Man in a world that doesn't remember him...",
      "popularity": 663.5004,
      "poster_path": "/bjiS5ipwxb9JFy3XRRN4OAilSeX.jpg",
      "release_date": "2026-07-29",
      "title": "Spider-Man: Brand New Day",
      "video": false,
      "vote_average": 8.468,
      "vote_count": 5684
    }
  ],
  "total_pages": 39,
  "total_results": 772
}

Odpowiedź pobrano z działającego API dla przykładowego żądania. Jest przycięta do 3 z 20 pozycji na stronie 1, a długie ciągi overview skrócono.

Łączenie filtrów

Osobne parametry łączą się przez AND. W jednym parametrze przecinek oznacza AND, a znak kreski pionowej OR. W surowym URL kreska pionowa to %7C, a klienty kodujące wartości zapytania robią to za ciebie.

CelŻądanie
Najlepiej oceniane sci-fi z wystarczającą liczbą głosów/discover/movie?with_genres=878&sort_by=vote_average.desc&vote_count.gte=1000
Akcja lub przygoda/discover/movie?with_genres=28%7C12
Akcja, ale nie animacja/discover/movie?with_genres=28&without_genres=16
Jeden aktor z jednym reżyserem/discover/movie?with_cast=6193&with_crew=525
Długie filmy z jednego roku/discover/movie?primary_release_year=2010&with_runtime.gte=150
Premiery w oknie dat/discover/movie?primary_release_date.gte=2026-10-01&primary_release_date.lte=2026-10-31
Filmy w jednym języku oryginału/discover/movie?with_original_language=fr
Streaming w jednym kraju/discover/movie?with_watch_providers=8&watch_region=US
Z klasyfikacją R w USA/discover/movie?certification_country=US&certification=R
Bez słowa kluczowego/discover/movie?with_keywords=818&without_keywords=4565

with_original_language filtruje według języka, w którym nakręcono tytuł, i przyjmuje też kody spoza 14 obsługiwanych języków, na przykład ja lub ko. Język zwracanego tekstu nadal ustala parametr language. W wierszu z dostawcą 8 to Netflix. ID dostawców odczytaj z /watch/providers/movie.

Discover dla seriali

GET /3/discover/tv używa tej samej koperty i paginacji. Pozycje zawierają name, original_name, first_air_date, origin_country i genre_ids, a ID gatunków pochodzą z /genre/tv/list, który zawiera połączone ID seriali, na przykład 10765 dla Sci-Fi i fantasy.

ParametrOpis
first_air_date.gte, first_air_date.lteDolna i górna granica daty pierwszej emisji, YYYY-MM-DD.
first_air_date_yearCzterocyfrowy rok daty pierwszej emisji.
air_date.gte, air_date.lteDolna i górna granica dat, w których serial ma emitowane odcinki, YYYY-MM-DD.
with_networksID sieci. Znajdziesz je na stronie firmy i sieci telewizyjne.
with_statusNumeryczny kod statusu: 0 serial powracający, 2 w produkcji, 3 zakończony, 4 anulowany.
with_typeNumeryczny typ programu: 0 dokument, 1 wiadomości, 2 miniserial, 3 reality, 4 fabularny, 5 talk show, 6 wideo.
sort_bypopularity, vote_average, vote_count, first_air_date, name lub original_name, każde z .asc lub .desc. name i original_name sortują według nazwy oryginalnej.
with_genres, without_genres, with_companies, with_keywords, without_keywordsTe same zasady co dla filmów.
vote_average.gte, vote_count.gte, with_runtime.gte, with_runtime.lte, with_original_languageTe same zasady co dla filmów.
with_watch_providers, watch_region, language, pageTe same zasady co dla filmów.

Żądanie takie jak /discover/tv?first_air_date.gte=2025-01-01&with_genres=18&vote_count.gte=100&sort_by=popularity.desc wypisuje seriale dramatyczne, które wystartowały w 2025 roku lub później. Wynik szczegółowo omawia strona seriale.

Błędy

HTTPstatus_codeKiedy
4017Brakuje klucza lub jest błędny.
40236Okres planu dobiegł końca.
40537Wywołano metodę zapisu.
42925Przekroczono limit żądań na minutę. Poczekaj tyle sekund, ile podaje Retry-After.
50011Wartość page spoza zakresu od 1 do 500.
50424Backend nie odpowiedział na czas. Spróbuj jeszcze raz.

Zestaw filtrów, który nic nie znajduje, nie jest błędem. Dostajesz HTTP 200 z pustą tablicą results i total_results równym 0. Zobacz błędy i limity żądań.

Praktyczne uwagi

  • Edge trzyma w cache każdy odrębny zestaw filtrów przez 30 minut i współdzieli go między kluczami. Klucz cache używa posortowanego zapytania, więc kolejność parametrów nie ma znaczenia.
  • Strona ma 20 pozycji, a ostatnia to 500, więc jeden zestaw filtrów sięga 10 000 pozycji. Aby pójść głębiej, dziel według okien dat. Szeroki filtr zgłasza total_results równe 20001, co jest limitem, a nie prawdziwą liczbą.
  • Zawsze łącz sort_by=vote_average.desc z vote_count.gte. Bez tego na górze tłoczą się tytuły z kilkoma głosami.
  • ID w filtrach są numeryczne. ID osób pobierz przez wyszukiwanie, a ID gatunków i dostawców ze strony gatunki i słowniki.
  • Gotowe listy, takie jak popularne lub aktualnie w kinach, znajdziesz na stronie trendy i listy.