# 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.

## Endpoint

`GET /3/movie/{movie_id}/keywords`

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

Resposta:

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

## 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](https://amodb.dev/pt/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.

```bash
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"
```

```js
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));
}
```

```python
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
<?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;
}
```

```go
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

| Parâmetro  | Em       | Obrigatório | Descrição                                                          |
| ---------- | -------- | ----------- | ------------------------------------------------------------------ |
| `movie_id` | caminho  | sim         | Id numérico do filme, por exemplo `550`.                           |
| `api_key`  | consulta | um dos dois | Sua chave. Use este parâmetro ou o header `Authorization: Bearer`. |

### Campos da resposta

| Campo             | Tipo    | Observações                                                                         |
| ----------------- | ------- | ----------------------------------------------------------------------------------- |
| `id`              | inteiro | O id do filme.                                                                      |
| `keywords`        | array   | Objetos com `id` e `name`. Vazio quando o filme não tem nenhuma.                    |
| `keywords[].id`   | inteiro | Id da palavra-chave. Use em `with_keywords` e nos caminhos de palavra-chave abaixo. |
| `keywords[].name` | string  | O 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 caminho                   | Retorna                                                                              | Parâmetros         |
| ---------------------------------- | ------------------------------------------------------------------------------------ | ------------------ |
| `GET /keyword/{keyword_id}`        | `{ id, name }`                                                                       | nenhum             |
| `GET /keyword/{keyword_id}/movies` | Lista paginada de filmes com `id`, `page`, `results`, `total_pages`, `total_results` | `language`, `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](https://amodb.dev/pt/trending-lists/), 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](https://amodb.dev/pt/discover/). Ele ordena, pagina e combina palavras-chave com outros filtros, e cobre TV além de filmes.

| Objetivo                                       | String 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](https://amodb.dev/pt/search/) 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

| HTTP | status_code | Quando                                                                                              |
| ---- | ----------- | --------------------------------------------------------------------------------------------------- |
| 401  | 7           | A chave está ausente ou incorreta.                                                                  |
| 402  | 36          | O período do plano terminou.                                                                        |
| 404  | 34          | Nenhuma palavra-chave com esse id em `/keyword/{keyword_id}` e na lista de filmes dela.             |
| 405  | 37          | Você usou um método de escrita em um caminho de palavra-chave.                                      |
| 429  | 25          | Você passou do seu limite de requisições por minuto. Espere os segundos indicados em `Retry-After`. |
| 500  | 11          | Uma 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](https://amodb.dev/pt/errors/) para todos os códigos e [limites de requisições](https://amodb.dev/pt/rate-limits/) 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.

## Perguntas e respostas

### Por que a resposta de séries usa results e a de filmes usa keywords?

Esse é o formato do TMDB v3, e o amodb o mantém para que os clientes existentes continuem funcionando. Filmes retornam um array keywords. Séries retornam os mesmos objetos em results. Leia data.keywords ?? data.results.

### Como encontro o id de uma palavra-chave pelo nome?

Chame o caminho de busca de palavras-chave com uma consulta, por exemplo /3/search/keyword?query=heist. Ele retorna uma lista paginada de pares id e name. Escolha a correspondência exata e guarde o id.

### Posso usar o mesmo id de palavra-chave para filmes e séries?

Sim. O id de uma palavra-chave é o mesmo valor no discover de filmes e no discover de séries, então with_keywords funciona nos dois caminhos. Guarde um id por tema e reutilize nos dois tipos de mídia.

### Como combino várias palavras-chave em uma consulta?

Una os ids em with_keywords com vírgula para exigir todos, ou com barra vertical para aceitar qualquer um. Use without_keywords para excluir ids. Mantenha a URL dentro do limite de tamanho do seu cliente HTTP.

## Páginas relacionadas

- [API Discover](https://amodb.dev/pt/discover/): API Discover com os mesmos filtros do TMDB v3. Liste filmes e séries por gênero, elenco, produtora, palavra-chave, ano, nota, duração e provedor, com ordenação.
- [API de busca](https://amodb.dev/pt/search/): API de busca com caminhos e JSON do TMDB v3. Encontre filmes, séries, pessoas, coleções, produtoras e palavras-chave por texto, com filtro de ano e paginação.
- [API de detalhes de filmes](https://amodb.dev/pt/movies/): API de detalhes de filmes com caminhos e JSON do TMDB v3. Busque um filme por id e junte créditos, avaliações e moods com append_to_response, em 14 idiomas.
- [API de séries de TV](https://amodb.dev/pt/tv-series/): API de séries de TV com os mesmos caminhos e JSON do TMDB v3. Busque uma série por id com temporadas, emissoras, próximo episódio e classificações.
- [Gêneros e listas de consulta](https://amodb.dev/pt/genres/): API de gêneros com caminhos do TMDB v3: ids de gênero de filmes e TV com nomes traduzidos, mais listas de países, idiomas, funções, classificações e provedores.
- [Início rápido](https://amodb.dev/pt/quickstart/): Faça sua primeira chamada ao amodb: obtenha uma chave, peça um filme em curl, JavaScript, Python, PHP ou Go e carregue o pôster. Menos de 2 minutos.

Atualizado: 2026-10-18. Source: https://amodb.dev/pt/keywords/
