API de palavras-chave

Os endpoints de palavras-chave retornam as tags de enredo de um filme ou série, cada uma com id e name. Você pode consultar uma palavra-chave, listar os filmes que a usam ou passar os ids ao discover com with_keywords para montar páginas de tema. Filmes respondem em keywords, séries em results.

Atualizado em Ver em Markdown

Obter as palavras-chave de um filme

GET /3/movie/{movie_id}/keywords retorna as tags de enredo de um filme. Uma palavra-chave é uma expressão curta, como um tema, um cenário ou um tipo de fonte, e tem um id numérico que você pode reutilizar no discover.

O exemplo carrega as palavras-chave de um filme e depois pede ao discover os filmes mais populares que compartilham a primeira palavra-chave dele.

bashjspyphpgo
curl -s "https://api.amodb.dev/3/movie/550/keywords" \
  -H "Authorization: Bearer $AMODB_KEY"

curl -s "https://api.amodb.dev/3/discover/movie?with_keywords=818&sort_by=popularity.desc" \
  -H "Authorization: Bearer $AMODB_KEY"
const base = 'https://api.amodb.dev/3';
const headers = { Authorization: `Bearer ${process.env.AMODB_KEY}` };

const kw = await fetch(`${base}/movie/550/keywords`, { headers });
if (!kw.ok) throw new Error(`keywords failed with ${kw.status}`);
const { keywords } = await kw.json();
console.log(keywords.map((k) => `${k.id}:${k.name}`).join(', '));

if (keywords.length > 0) {
  const first = keywords[0];
  const found = await fetch(`${base}/discover/movie?with_keywords=${first.id}&sort_by=popularity.desc`, { headers });
  if (!found.ok) throw new Error(`discover failed with ${found.status}`);
  const page = await found.json();
  console.log(first.name, page.results.slice(0, 5).map((m) => m.title));
}
import os
import requests

base = "https://api.amodb.dev/3"
headers = {"Authorization": f"Bearer {os.environ['AMODB_KEY']}"}

r = requests.get(f"{base}/movie/550/keywords", headers=headers, timeout=10)
r.raise_for_status()
keywords = r.json()["keywords"]
print(", ".join(f"{k['id']}:{k['name']}" for k in keywords))

if keywords:
    first = keywords[0]
    d = requests.get(
        f"{base}/discover/movie",
        params={"with_keywords": first["id"], "sort_by": "popularity.desc"},
        headers=headers,
        timeout=10,
    )
    d.raise_for_status()
    print(first["name"], [m["title"] for m in d.json()["results"][:5]])
<?php
function amodb_get(string $url): array {
    $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");
    }
    return json_decode($body, true);
}

$base = 'https://api.amodb.dev/3';
$keywords = amodb_get("$base/movie/550/keywords")['keywords'];
if ($keywords) {
    $first = $keywords[0];
    $found = amodb_get("$base/discover/movie?with_keywords={$first['id']}&sort_by=popularity.desc");
    $titles = array_column(array_slice($found['results'], 0, 5), 'title');
    echo $first['name'], ': ', implode(', ', $titles), PHP_EOL;
}
package main

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

var client = &http.Client{Timeout: 10 * time.Second}

func get(path string, out any) error {
	req, _ := http.NewRequest("GET", "https://api.amodb.dev/3"+path, nil)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("AMODB_KEY"))
	res, err := client.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		return fmt.Errorf("amodb returned %s", res.Status)
	}
	return json.NewDecoder(res.Body).Decode(out)
}

type Keywords struct {
	Keywords []struct {
		ID   int    `json:"id"`
		Name string `json:"name"`
	} `json:"keywords"`
}

type Page struct {
	Results []struct {
		Title string `json:"title"`
	} `json:"results"`
}

func main() {
	var kw Keywords
	if err := get("/movie/550/keywords", &kw); err != nil {
		panic(err)
	}
	if len(kw.Keywords) == 0 {
		return
	}
	first := kw.Keywords[0]
	var page Page
	if err := get(fmt.Sprintf("/discover/movie?with_keywords=%d&sort_by=popularity.desc", first.ID), &page); err != nil {
		panic(err)
	}
	fmt.Println(first.Name)
	for i, m := range page.Results {
		if i == 5 {
			break
		}
		fmt.Println(" ", m.Title)
	}
}

Parâmetros

  • movie_idcaminhoobrigatório
    Id numérico do filme, por exemplo 550.
  • api_keyconsultaum dos dois
    Sua chave. Use este parâmetro ou o header Authorization: Bearer.

Campos da resposta

CampoTipoObservações
idinteiroO id do filme.
keywordsarrayObjetos com id e name. Vazio quando o filme não tem nenhuma.
keywords[].idinteiroId da palavra-chave. Use em with_keywords e nos caminhos de palavra-chave abaixo.
keywords[].namestringO texto da palavra-chave.

Exemplo de resposta

JSON
{
  "id": 550,
  "keywords": [
    { "id": 818, "name": "based on novel or book" },
    { "id": 825, "name": "support group" },
    { "id": 851, "name": "dual identity" }
  ]
}

A resposta real tem 14 palavras-chave. Esta foi cortada nas 3 primeiras. Os nomes das palavras-chave não são traduzidos, então language não tem efeito aqui.

Palavras-chave de uma série

GET /3/tv/{series_id}/keywords usa a mesma chave e retorna os mesmos objetos, mas o array se chama results. O id no caminho é o id da série, por exemplo 1396.

JSON
{
  "id": 1396,
  "results": [
    { "id": 1508, "name": "new mexico" },
    { "id": 2231, "name": "drug dealer" }
  ]
}

A resposta real tem 29 entradas e esta foi cortada nas 2 primeiras. Um cliente que atende os dois tipos de mídia pode ler data.keywords ?? data.results e tratar os dois da mesma forma.

Registros de palavras-chave e seus filmes

Método e caminhoRetornaParâmetros
GET /keyword/{keyword_id}{ id, name }nenhum
GET /keyword/{keyword_id}/moviesLista paginada de filmes com id, page, results, total_pages, total_resultslanguage, page

Os dois caminhos usam o id numérico de um array de palavras-chave. A lista de filmes tem o mesmo formato de item das outras listas de filmes, incluindo genre_ids e poster_path, além do id da palavra-chave no topo. include_adult é aceito e ignorado. Uma página além de total_pages retorna um array results vazio. Não existe lista de séries por palavra-chave, então use /discover/tv?with_keywords= para TV.

Combinar palavras-chave com o discover

Para qualquer coisa além de uma lista simples, filtre no discover. Ele ordena, pagina e combina palavras-chave com outros filtros, e cobre TV além de filmes.

ObjetivoString de consulta
Filmes com uma palavra-chave/discover/movie?with_keywords=818
Filmes com as duas palavras-chave/discover/movie?with_keywords=818,4565
Filmes sem uma palavra-chave/discover/movie?without_keywords=818
Séries com uma palavra-chave/discover/tv?with_keywords=9712
Séries com qualquer uma de duas palavras-chave/discover/tv?with_keywords=818%7C9712
Uma palavra-chave dentro de um gênero/discover/movie?with_keywords=818&with_genres=18

Uma vírgula entre ids significa todos eles. Escreva uma barra vertical entre os ids, como em with_keywords=818|4565, para aceitar qualquer um. Os resultados do discover ficam em cache de borda por 30 minutos.

Encontrar o id de uma palavra-chave

Para transformar texto em id, chame GET /3/search/keyword?query=heist. Ele retorna uma lista paginada de pares id e name, 20 por página. Veja a busca para o conjunto completo de caminhos de busca. Uma busca de palavra-chave sem resultado responde hoje 500 com status_code 11, e não com uma lista vazia. As respostas de busca ficam em cache por 10 minutos, mas toda chamada ainda conta no seu limite de requisições por minuto, então aplique debounce em caixas de autocompletar.

Erros

HTTPstatus_codeQuando
4017A chave está ausente ou incorreta.
40236O período do plano terminou.
40434Nenhuma palavra-chave com esse id em /keyword/{keyword_id} e na lista de filmes dela.
40537Você usou um método de escrita em um caminho de palavra-chave.
42925Você passou do seu limite de requisições por minuto. Espere os segundos indicados em Retry-After.
50011Uma consulta em /search/keyword sem nenhuma correspondência.

Um id de filme ou série desconhecido nos caminhos de palavras-chave não gera 404. Você recebe HTTP 200 com o id e um array vazio.

Veja erros para todos os códigos e limites de requisições para os limites de cada plano.

Notas práticas

  • Guarde o id da palavra-chave, não o nome. Um nome pode ser reescrito, um id não muda.
  • As listas de palavras-chave ficam em cache junto com os detalhes do título, por 6 horas. Para páginas de tags, uma atualização semanal basta.
  • Um título isolado tem uma lista curta de tags. Para páginas de tema, parta de um id de palavra-chave e liste os títulos dele no discover, não o contrário.
  • Use without_keywords para remover ruído, por exemplo uma tag que você nunca quer em uma página familiar.
  • Um array vazio é uma resposta válida para títulos obscuros. Oculte a linha de tags em vez de mostrar um erro.