API Discover
Discover liste les films sur GET /3/discover/movie et les séries sur GET /3/discover/tv, filtrés et triés selon les paramètres choisis : genre, distribution, équipe, société, mot-clé, dates, note, votes, durée, langue et plateforme de streaming. Le JSON suit TMDB v3, et les résultats sont mis en cache 30 minutes.
Découvrir des films
GET /3/discover/movie renvoie une liste paginée de films qui correspondent à tous les filtres envoyés, dans l'ordre choisi. C'est le point de terminaison des pages de navigation, des listes de meilleurs films et des recommandations par facette, et il n'a besoin d'aucun texte query. Quand un utilisateur a saisi un titre, utilisez plutôt recherche.
L'exemple liste les films de science-fiction (genre 878) avec au moins 1000 votes, les mieux notés en premier.
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)
}
}Paramètres
api_keyrequêtel'un des deuxVotre clé. Utilisez-la ou l'en-têteAuthorization: Bearer.sort_byrequêteChamp et sens commevote_average.desc. Champs :popularity,vote_average,vote_count,primary_release_date,revenue,title,original_title, chacun avec.ascou.desc.titleetoriginal_titletrient tous deux par titre original. Une valeur inconnue se replie surpopularity.desc, qui est aussi la valeur par défaut.with_genresrequêteIdentifiants de genres. Une virgule signifie ET, une barre verticale signifie OU.without_genresrequêteIdentifiants de genres à exclure.with_cast,with_crewrequêteIdentifiants de personnes. Trouvez-les avec recherche.with_peoplerequêteIdentifiants de personnes qui apparaissent dans la distribution ou l'équipe.with_companies,without_companiesrequêteIdentifiants de sociétés de production à exiger ou à exclure. La virgule et la barre verticale fonctionnent comme danswith_genres.with_keywords,without_keywordsrequêteIdentifiants de mots-clés à exiger ou à exclure. Voir mots-clés.with_origin_countryrequêteCode pays de production à 2 lettres en majuscules commeFR.primary_release_yearrequêteAnnée à quatre chiffres de la date de sortie principale.yearrequêteAnnée à quatre chiffres. Correspond à n'importe quelle date de sortie de cette année, donc renvoie plus de titres queprimary_release_year.primary_,release_ date.gte primary_requêterelease_ date.lte Bornes inférieure et supérieure de la date de sortie principale,YYYY-MM-DD.release_date.gte,release_date.lterequêteBornes inférieure et supérieure de n'importe quelle date de sortie dans n'importe quel pays,YYYY-MM-DD.regionrequêteCode pays à 2 lettres en majuscules. Remplacerelease_datedans chaque résultat par la date dans ce pays. Ne retire aucun titre.certification_country,certificationrequêteFiltre de classification par âge, par exempleUSetPG.certificationest ignoré sans pays.certification.gteetcertification.ltedonnent une plage.vote_average.gte,vote_average.lterequêteNote moyenne minimale et maximale, de 0 à 10.vote_count.gte,vote_count.lterequêteNombre minimal et maximal de votes.with_runtime.gte,with_runtime.lterequêteDurée minimale et maximale en minutes.with_original_languagerequêteLangue originale sous forme de code à 2 lettres commefrouko.with_watch_providersrequêteIdentifiants de plateformes. Demandewatch_regionet est ignoré sans lui. Les identifiants viennent de genres et listes de référence.watch_regionrequêteCode pays à 2 lettres en majuscules pour la disponibilité des plateformes.include_adultrequêteAccepté et ignoré. Les titres pour adultes ne sont jamais renvoyés.languagerequêteBalise TMDB commeen-USoupl-PL. 14 langues de base sont servies. Par défauten-US.pagerequêteNuméro de page de 1 à 500. Par défaut 1.
Champs de la réponse
| Champ | Type | Remarques |
|---|---|---|
page, total_pages, total_results | entier | Pagination pour ce jeu de filtres. Les filtres larges annoncent au plus 1001 pages et 20001 résultats, mais seules les pages 1 à 500 peuvent être lues. |
results | tableau | Jusqu'à 20 films. Vide quand aucun titre ne correspond à tous les filtres. |
id | entier | Identifiant du film pour les détails du film. |
title, original_title, overview | chaîne | Texte localisé et titre original. |
original_language | chaîne | Code à deux lettres de la langue dans laquelle le film a été tourné. |
release_date | chaîne | YYYY-MM-DD. |
genre_ids | tableau d'entiers | Identifiants seulement. Associez-les à des noms avec /genre/movie/list. |
poster_path, backdrop_path | chaîne ou null | À ajouter à https:/. |
vote_average, vote_count, popularity | nombre | Valeurs de note et de classement. |
adult, video | booléen | adult vaut toujours false. |
Exemple de réponse
{
"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
}La réponse a été récupérée depuis l'API réelle pour la requête d'exemple. Elle est réduite à 3 des 20 entrées de la page 1, et les longues chaînes overview sont raccourcies.
Combiner des filtres
Des paramètres distincts se combinent avec ET. À l'intérieur d'un paramètre, une virgule signifie ET et une barre verticale signifie OU. Dans une URL brute, la barre verticale s'écrit %7C, et les clients qui encodent les valeurs de requête le font pour vous.
| Objectif | Requête |
|---|---|
| Meilleure science-fiction avec assez de votes | / |
| Action ou aventure | / |
| Action mais pas animation | / |
| Un acteur avec un réalisateur | / |
| Films longs d'une année | / |
| Sorties dans une fenêtre de dates | / |
| Films dans une langue originale | / |
| En streaming dans un pays | / |
| Classés R aux États-Unis | / |
| Sans un mot-clé | / |
with_original_language filtre par la langue dans laquelle un titre a été tourné, et il accepte des codes en dehors des 14 langues servies, par exemple ja ou ko. Le paramètre language décide toujours de la langue du texte renvoyé. Dans la ligne des plateformes, 8 est Netflix. Lisez les identifiants de plateformes dans /watch/providers/movie.
Découvrir des séries
GET /3/discover/tv utilise la même enveloppe et la même pagination. Les entrées contiennent name, original_name, first_air_date, origin_country et genre_ids, et les identifiants de genres viennent de /genre/tv/list, qui contient les identifiants TV fusionnés comme 10765 pour Sci-Fi et Fantasy.
| Paramètre | Description |
|---|---|
first_air_date.gte, first_air_date.lte | Bornes inférieure et supérieure de la date de première diffusion, YYYY-MM-DD. |
first_air_date_year | Année à quatre chiffres de la date de première diffusion. |
air_date.gte, air_date.lte | Bornes inférieure et supérieure des dates où une série a des épisodes diffusés, YYYY-MM-DD. |
with_networks | Identifiants de chaînes. Trouvez-les sur sociétés et chaînes. |
with_status | Code de statut numérique : 0 série en cours, 2 en production, 3 terminée, 4 annulée. |
with_type | Type de série numérique : 0 documentaire, 1 actualités, 2 mini-série, 3 téléréalité, 4 fiction, 5 talk-show, 6 vidéo. |
sort_by | popularity, vote_average, vote_count, first_air_date, name ou original_name, chacun avec .asc ou .desc. name et original_name trient tous deux par nom original. |
with_genres, without_genres, with_companies, with_keywords, without_keywords | Mêmes règles que pour les films. |
vote_average.gte, vote_count.gte, with_runtime.gte, with_runtime.lte, with_original_language | Mêmes règles que pour les films. |
with_watch_providers, watch_region, language, page | Mêmes règles que pour les films. |
Une requête comme / liste les séries dramatiques commencées en 2025 ou plus tard. Lisez un résultat en détail sur séries TV.
Erreurs
| HTTP | status_code | Quand |
|---|---|---|
| 401 | 7 | La clé est absente ou fausse. |
| 402 | 36 | La période de l'offre est terminée. |
| 405 | 37 | Vous avez appelé une méthode d'écriture. |
| 429 | 25 | Au-dessus de vos requêtes par minute. Attendez les secondes de Retry-After. |
| 500 | 11 | Une page en dehors de 1 à 500. |
| 504 | 24 | Le backend n'a pas répondu à temps. Réessayez une fois. |
Un jeu de filtres qui ne correspond à rien n'est pas une erreur. Vous obtenez un HTTP 200 avec un tableau results vide et total_results à 0. Voir erreurs et limites de débit.
Remarques pratiques
- La périphérie met en cache chaque jeu de filtres distinct 30 minutes et le partage entre les clés. La clé de cache utilise la requête triée : l'ordre de vos paramètres n'a donc pas d'importance.
- Une page contient 20 entrées et la dernière page est la 500 : un jeu de filtres atteint donc 10 000 entrées. Découpez par fenêtres de dates pour aller plus loin. Un filtre large annonce un
total_resultsde 20001, qui est un plafond et non un vrai compte. - Associez toujours
sort_àby= vote_ average.desc vote_count.gte. Sans cela, les titres ayant quelques votes encombrent le haut de la liste. - Les identifiants dans les filtres sont numériques. Prenez les identifiants de personnes dans recherche, et les identifiants de genres et de plateformes dans genres et listes de référence.
- Pour des listes prêtes à l'emploi comme populaires ou à l'affiche, voir tendances et listes.