API Discover

O Discover lista filmes em GET /3/discover/movie e séries de TV em GET /3/discover/tv, filtrados e ordenados pelos parâmetros que você escolher: gênero, elenco, equipe técnica, produtora, palavra-chave, datas, nota, votos, duração, idioma e provedor de streaming. O JSON segue o TMDB v3, e os resultados ficam em cache por 30 minutos.

Atualizado em Ver em Markdown

Descobrir filmes

GET /3/discover/movie retorna uma lista paginada de filmes que atendem a todos os filtros enviados, na ordem que você escolher. É o endpoint para páginas de navegação, listas dos “melhores” e recomendações por faceta, e não precisa de texto em query. Quando você tem um título digitado por um usuário, use a busca.

O exemplo lista filmes de ficção científica (id de gênero 878) com pelo menos 1000 votos, os mais bem avaliados primeiro.

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_keyconsultaum dos dois
    Sua chave. Use este parâmetro ou o header Authorization: Bearer.
  • sort_byconsulta
    Campo e direção, como vote_average.desc. Campos: popularity, vote_average, vote_count, primary_release_date, revenue, title, original_title, cada um com .asc ou .desc. title e original_title ordenam ambos pelo título original. Um valor desconhecido volta para popularity.desc, que também é o padrão.
  • with_genresconsulta
    Ids de gênero. Vírgula significa E, barra vertical significa OU.
  • without_genresconsulta
    Ids de gênero a excluir.
  • with_cast, with_crewconsulta
    Ids de pessoa. Encontre-os na busca.
  • with_peopleconsulta
    Ids de pessoa que aparecem no elenco ou na equipe técnica.
  • with_companies, without_companiesconsulta
    Ids de produtora a exigir ou excluir. Vírgula e barra vertical funcionam como em with_genres.
  • with_keywords, without_keywordsconsulta
    Ids de palavra-chave a exigir ou excluir. Veja palavras-chave.
  • with_origin_countryconsulta
    Código de país de produção com 2 letras maiúsculas, como FR.
  • primary_release_yearconsulta
    Ano com quatro dígitos da data de lançamento principal.
  • yearconsulta
    Ano com quatro dígitos. Corresponde a qualquer data de lançamento naquele ano, então retorna mais títulos que primary_release_year.
  • primary_release_date.gte, primary_release_date.lteconsulta
    Limites inferior e superior da data de lançamento principal, YYYY-MM-DD.
  • release_date.gte, release_date.lteconsulta
    Limites inferior e superior de qualquer data de lançamento em qualquer país, YYYY-MM-DD.
  • regionconsulta
    Código de país com 2 letras maiúsculas. Troca release_date em cada resultado pela data nesse país. Não remove títulos.
  • certification_country, certificationconsulta
    Filtro de classificação indicativa, por exemplo US e PG. certification é ignorado sem um país. certification.gte e certification.lte definem um intervalo.
  • vote_average.gte, vote_average.lteconsulta
    Nota média mínima e máxima, de 0 a 10.
  • vote_count.gte, vote_count.lteconsulta
    Número mínimo e máximo de votos.
  • with_runtime.gte, with_runtime.lteconsulta
    Duração mínima e máxima em minutos.
  • with_original_languageconsulta
    Idioma original como código de 2 letras, como fr ou ko.
  • with_watch_providersconsulta
    Ids de provedor. Exige watch_region e é ignorado sem ele. Os ids vêm de gêneros e listas de consulta.
  • watch_regionconsulta
    Código de país com 2 letras maiúsculas para a disponibilidade do provedor.
  • include_adultconsulta
    Aceito e ignorado. Títulos adultos nunca são retornados.
  • languageconsulta
    Tag do TMDB como en-US ou pl-PL. 14 idiomas base são atendidos. Padrão en-US.
  • pageconsulta
    Número da página, de 1 a 500. Padrão 1.

Campos da resposta

CampoTipoObservações
page, total_pages, total_resultsinteiroPaginação deste conjunto de filtros. Filtros amplos informam no máximo 1001 páginas e 20001 resultados, mas só as páginas de 1 a 500 podem ser lidas.
resultsarrayAté 20 filmes. Vazio quando nenhum título atende a todos os filtros.
idinteiroId do filme para os detalhes do filme.
title, original_title, overviewstringTexto localizado e título original.
original_languagestringCódigo de duas letras do idioma em que o filme foi feito.
release_datestringYYYY-MM-DD.
genre_idsarray de inteirosSó os ids. Converta-os em nomes com /genre/movie/list.
poster_path, backdrop_pathstring ou nullAcrescente a https://img.amodb.dev/t/p/{size}.
vote_average, vote_count, popularitynúmeroValores de nota e de ranking.
adult, videobooleanoadult é sempre false.

Exemplo de resposta

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
}

A resposta foi obtida da API real com a requisição do exemplo. Ela foi cortada para 3 das 20 entradas da página 1, e as strings longas de overview foram encurtadas.

Combinar filtros

Parâmetros separados se combinam com E. Dentro de um mesmo parâmetro, a vírgula significa E e a barra vertical significa OU. Em uma URL pura a barra vertical é escrita %7C, e os clientes que codificam os valores da consulta fazem isso por você.

ObjetivoRequisição
Ficção científica mais bem avaliada, com votos suficientes/discover/movie?with_genres=878&sort_by=vote_average.desc&vote_count.gte=1000
Ação ou aventura/discover/movie?with_genres=28%7C12
Ação, mas não animação/discover/movie?with_genres=28&without_genres=16
Um ator com um diretor/discover/movie?with_cast=6193&with_crew=525
Filmes longos de um ano/discover/movie?primary_release_year=2010&with_runtime.gte=150
Lançamentos em uma janela de datas/discover/movie?primary_release_date.gte=2026-10-01&primary_release_date.lte=2026-10-31
Filmes em um idioma original/discover/movie?with_original_language=fr
Em streaming em um país/discover/movie?with_watch_providers=8&watch_region=US
Classificação R nos EUA/discover/movie?certification_country=US&certification=R
Sem uma palavra-chave/discover/movie?with_keywords=818&without_keywords=4565

with_original_language filtra pelo idioma em que o título foi feito e aceita códigos fora dos 14 idiomas atendidos, por exemplo ja ou ko. O parâmetro language continua definindo o idioma do texto que você recebe. Na linha do provedor, 8 é a Netflix. Leia os ids de provedor em /watch/providers/movie.

Descobrir séries de TV

GET /3/discover/tv usa o mesmo envelope e a mesma paginação. As entradas trazem name, original_name, first_air_date, origin_country e genre_ids, e os ids de gênero vêm de /genre/tv/list, que contém os ids de TV unificados, como 10765 para Sci-Fi e Fantasia.

ParâmetroDescrição
first_air_date.gte, first_air_date.lteLimites inferior e superior da data da primeira exibição, YYYY-MM-DD.
first_air_date_yearAno com quatro dígitos da primeira exibição.
air_date.gte, air_date.lteLimites inferior e superior das datas em que uma série tem episódios no ar, YYYY-MM-DD.
with_networksIds de emissora. Encontre-os em produtoras e emissoras.
with_statusCódigo numérico de status: 0 série em exibição, 2 em produção, 3 encerrada, 4 cancelada.
with_typeTipo numérico de programa: 0 documentário, 1 notícias, 2 minissérie, 3 reality, 4 roteirizado, 5 talk show, 6 vídeo.
sort_bypopularity, vote_average, vote_count, first_air_date, name ou original_name, cada um com .asc ou .desc. name e original_name ordenam ambos pelo nome original.
with_genres, without_genres, with_companies, with_keywords, without_keywordsAs mesmas regras dos filmes.
vote_average.gte, vote_count.gte, with_runtime.gte, with_runtime.lte, with_original_languageAs mesmas regras dos filmes.
with_watch_providers, watch_region, language, pageAs mesmas regras dos filmes.

Uma requisição como /discover/tv?first_air_date.gte=2025-01-01&with_genres=18&vote_count.gte=100&sort_by=popularity.desc lista séries de drama que começaram em 2025 ou depois. Veja um resultado em detalhe em séries de TV.

Erros

HTTPstatus_codeQuando
4017A chave está ausente ou incorreta.
40236O período do plano terminou.
40537Você chamou um método de escrita.
42925Acima do seu limite de requisições por minuto. Espere os segundos indicados em Retry-After.
50011Um page fora do intervalo de 1 a 500.
50424O backend não respondeu a tempo. Tente de novo uma vez.

Um conjunto de filtros sem nenhuma correspondência não é um erro. Você recebe HTTP 200 com um array results vazio e total_results igual a 0. Veja erros e limites de requisições.

Notas práticas

  • A borda guarda em cache cada conjunto distinto de filtros por 30 minutos e o compartilha entre as chaves. A chave do cache usa a consulta ordenada, então a ordem dos seus parâmetros não importa.
  • Uma página tem 20 entradas e a última é a 500, então um conjunto de filtros chega a 10,000 entradas. Divida por janelas de datas para ir mais fundo. Um filtro amplo informa total_results igual a 20001, que é um teto e não uma contagem real.
  • Combine sempre sort_by=vote_average.desc com vote_count.gte. Sem isso, títulos com poucos votos lotam o topo.
  • Os ids nos filtros são numéricos. Pegue ids de pessoa na busca, e ids de gênero e de provedor em gêneros e listas de consulta.
  • Para listas prontas, como populares ou em cartaz, veja em alta e listas.