API Discover

Discover lista películas en GET /3/discover/movie y series de TV en GET /3/discover/tv, filtradas y ordenadas con los parámetros que elijas: género, reparto, equipo técnico, productora, palabra clave, fechas, puntuación, votos, duración, idioma y plataforma de streaming. El JSON coincide con TMDB v3 y los resultados se guardan en caché 30 minutos.

Actualizado el Ver en Markdown

Descubrir películas

GET /3/discover/movie devuelve una lista paginada de películas que cumplen todos los filtros que envías, en el orden que elijas. Es el endpoint para páginas de exploración, listas de «lo mejor de» y recomendaciones por faceta, y no necesita texto en query. Cuando tengas un título escrito por un usuario, usa la búsqueda.

El ejemplo lista las películas de ciencia ficción (id de género 878) con al menos 1000 votos, las mejor valoradas primero.

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

Parámetros

  • api_keyconsultauno de los dos
    Tu clave. Usa esta o el encabezado Authorization: Bearer.
  • sort_byconsulta
    Campo y dirección como vote_average.desc. Campos: popularity, vote_average, vote_count, primary_release_date, revenue, title, original_title, cada uno con .asc o .desc. title y original_title ordenan ambos por el título original. Un valor desconocido recurre a popularity.desc, que también es el valor por defecto.
  • with_genresconsulta
    Ids de género. Una coma significa AND, una barra vertical significa OR.
  • without_genresconsulta
    Ids de género que se excluyen.
  • with_cast, with_crewconsulta
    Ids de persona. Búscalos con la búsqueda.
  • with_peopleconsulta
    Ids de persona que aparecen en el reparto o en el equipo técnico.
  • with_companies, without_companiesconsulta
    Ids de productoras que se exigen o se excluyen. La coma y la barra vertical funcionan como en with_genres.
  • with_keywords, without_keywordsconsulta
    Ids de palabras clave que se exigen o se excluyen. Consulta palabras clave.
  • with_origin_countryconsulta
    Código de país de producción de 2 letras en mayúsculas, como FR.
  • primary_release_yearconsulta
    Año de cuatro dígitos de la fecha de estreno principal.
  • yearconsulta
    Año de cuatro dígitos. Coincide con cualquier fecha de estreno de ese año, así que devuelve más títulos que primary_release_year.
  • primary_release_date.gte, primary_release_date.lteconsulta
    Límite inferior y superior de la fecha de estreno principal, YYYY-MM-DD.
  • release_date.gte, release_date.lteconsulta
    Límite inferior y superior de cualquier fecha de estreno en cualquier país, YYYY-MM-DD.
  • regionconsulta
    Código de país de 2 letras en mayúsculas. Sustituye release_date en cada resultado por la fecha de ese país. No elimina títulos.
  • certification_country, certificationconsulta
    Filtro de clasificación por edad, por ejemplo US y PG. certification se ignora sin país. certification.gte y certification.lte definen un rango.
  • vote_average.gte, vote_average.lteconsulta
    Puntuación media mínima y máxima, de 0 a 10.
  • vote_count.gte, vote_count.lteconsulta
    Número mínimo y máximo de votos.
  • with_runtime.gte, with_runtime.lteconsulta
    Duración mínima y máxima en minutos.
  • with_original_languageconsulta
    Idioma original como código de 2 letras, por ejemplo fr o ko.
  • with_watch_providersconsulta
    Ids de proveedores. Necesita watch_region y se ignora sin él. Los ids salen de géneros y listas de consulta.
  • watch_regionconsulta
    Código de país de 2 letras en mayúsculas para la disponibilidad del proveedor.
  • include_adultconsulta
    Se acepta y se ignora. Nunca se devuelven títulos para adultos.
  • languageconsulta
    Etiqueta de TMDB como en-US o pl-PL. Se sirven 14 idiomas base. Valor por defecto en-US.
  • pageconsulta
    Número de página de 1 a 500. Valor por defecto 1.

Campos de la respuesta

CampoTipoNotas
page, total_pages, total_resultsenteroPaginación de este conjunto de filtros. Los filtros amplios informan como máximo 1001 páginas y 20001 resultados, pero solo se pueden leer las páginas de 1 a 500.
resultsarrayHasta 20 películas. Vacío cuando ningún título cumple todos los filtros.
identeroId de película para los detalles de película.
title, original_title, overviewtextoTexto localizado y título original.
original_languagetextoCódigo de dos letras del idioma en que se hizo la película.
release_datetextoYYYY-MM-DD.
genre_idsarray de enterosSolo ids. Conviértelos en nombres con /genre/movie/list.
poster_path, backdrop_pathtexto o nullAñádelo a https://img.amodb.dev/t/p/{size}.
vote_average, vote_count, popularitynúmeroValores de puntuación y de ranking.
adult, videobooleanoadult es siempre false.

Ejemplo de respuesta

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
}

La respuesta se obtuvo de la API real con la solicitud del ejemplo. Se corta a 3 de las 20 entradas de la página 1, y las cadenas overview largas se acortan.

Combinar filtros

Los parámetros separados se combinan con AND. Dentro de un mismo parámetro, una coma significa AND y una barra vertical significa OR. En una URL sin codificar la barra se escribe %7C, y los clientes que codifican los valores de consulta lo hacen por ti.

ObjetivoSolicitud
Ciencia ficción mejor valorada con suficientes votos/discover/movie?with_genres=878&sort_by=vote_average.desc&vote_count.gte=1000
Acción o aventura/discover/movie?with_genres=28%7C12
Acción pero no animación/discover/movie?with_genres=28&without_genres=16
Un actor con un director/discover/movie?with_cast=6193&with_crew=525
Películas largas de un año/discover/movie?primary_release_year=2010&with_runtime.gte=150
Estrenos en una ventana de fechas/discover/movie?primary_release_date.gte=2026-10-01&primary_release_date.lte=2026-10-31
Películas en un idioma original/discover/movie?with_original_language=fr
En streaming en un país/discover/movie?with_watch_providers=8&watch_region=US
Clasificación R en Estados Unidos/discover/movie?certification_country=US&certification=R
Sin una palabra clave/discover/movie?with_keywords=818&without_keywords=4565

with_original_language filtra por el idioma en que se hizo un título, y acepta códigos fuera de los 14 idiomas servidos, por ejemplo ja o ko. El parámetro language sigue decidiendo el idioma del texto que recibes. En la fila de proveedores, 8 es Netflix. Lee los ids de proveedor de /watch/providers/movie.

Descubrir series de TV

GET /3/discover/tv usa la misma estructura de respuesta y la misma paginación. Las entradas traen name, original_name, first_air_date, origin_country y genre_ids, y los ids de género salen de /genre/tv/list, que contiene los ids de TV combinados, como 10765 para ciencia ficción y fantasía.

ParámetroDescripción
first_air_date.gte, first_air_date.lteLímite inferior y superior de la fecha de primera emisión, YYYY-MM-DD.
first_air_date_yearAño de cuatro dígitos de la fecha de primera emisión.
air_date.gte, air_date.lteLímite inferior y superior de las fechas en que una serie tiene episodios en emisión, YYYY-MM-DD.
with_networksIds de cadenas. Búscalos en productoras y cadenas de TV.
with_statusCódigo de estado numérico: 0 serie que continúa, 2 en producción, 3 finalizada, 4 cancelada.
with_typeTipo numérico de programa: 0 documental, 1 noticias, 2 miniserie, 3 reality, 4 con guion, 5 programa de entrevistas, 6 vídeo.
sort_bypopularity, vote_average, vote_count, first_air_date, name u original_name, cada uno con .asc o .desc. name y original_name ordenan ambos por el nombre original.
with_genres, without_genres, with_companies, with_keywords, without_keywordsMismas reglas que para las películas.
vote_average.gte, vote_count.gte, with_runtime.gte, with_runtime.lte, with_original_languageMismas reglas que para las películas.
with_watch_providers, watch_region, language, pageMismas reglas que para las películas.

Una solicitud como /discover/tv?first_air_date.gte=2025-01-01&with_genres=18&vote_count.gte=100&sort_by=popularity.desc lista series de drama que empezaron en 2025 o después. Lee un resultado en detalle en series de TV.

Errores

HTTPstatus_codeCuándo
4017La clave falta o es incorrecta.
40236El periodo del plan ha terminado.
40537Llamaste a un método de escritura.
42925Superaste tus solicitudes por minuto. Espera los segundos de Retry-After.
50011Un page fuera del rango de 1 a 500.
50424El backend no respondió a tiempo. Reintenta una vez.

Un conjunto de filtros sin coincidencias no es un error. Recibes HTTP 200 con un array results vacío y total_results en 0. Consulta errores y límites de solicitudes.

Notas prácticas

  • La caché perimetral guarda cada conjunto de filtros distinto 30 minutos y lo comparte entre claves. La clave de caché usa la consulta ordenada, así que el orden de tus parámetros no importa.
  • Una página tiene 20 entradas y la última es la 500, así que un conjunto de filtros llega a 10,000 entradas. Divide por ventanas de fechas para ir más a fondo. Un filtro amplio informa total_results de 20001, que es un tope y no un recuento real.
  • Combina siempre sort_by=vote_average.desc con vote_count.gte. Sin él, los títulos con pocos votos ocupan los primeros puestos.
  • Los ids de los filtros son numéricos. Obtén los ids de persona en la búsqueda, y los ids de género y de proveedor en géneros y listas de consulta.
  • Para listas ya preparadas como populares o en cartelera, consulta tendencias y listas.