# API cuvinte-cheie

> Endpoint-urile pentru cuvinte-cheie întorc etichetele de subiect ale unui film sau serial TV, fiecare ca ID și nume. Poți căuta un cuvânt-cheie, lista filmele care îl poartă sau transmite ID-urile la discover cu with_keywords ca să construiești pagini tematice. Filmele răspund sub keywords, serialele TV sub results.

## Endpoint

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

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

Răspuns:

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

## Obține cuvintele-cheie ale unui film

`GET /3/movie/{movie_id}/keywords` întoarce etichetele de subiect ale unui film. Un cuvânt-cheie este o expresie scurtă, precum o temă, un decor sau un tip de sursă, și are un ID numeric pe care îl poți reutiliza în [descoperire](https://amodb.dev/ro/discover/).

Exemplul încarcă cuvintele-cheie ale unui film și apoi cere de la discover cele mai populare filme care împart primul lui cuvânt-cheie.

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

### Parametri

| Parametru  | Loc        | Obligatoriu          | Descriere                                                             |
| ---------- | ---------- | -------------------- | --------------------------------------------------------------------- |
| `movie_id` | cale       | da                   | ID numeric de film, de exemplu `550`.                                 |
| `api_key`  | interogare | una dintre cele două | Cheia ta. Folosește-o pe aceasta sau antetul `Authorization: Bearer`. |

### Câmpurile răspunsului

| Câmp              | Tip          | Observații                                                                                      |
| ----------------- | ------------ | ----------------------------------------------------------------------------------------------- |
| `id`              | număr întreg | ID-ul filmului.                                                                                 |
| `keywords`        | array        | Obiecte cu `id` și `name`. Gol când filmul nu are niciunul.                                     |
| `keywords[].id`   | număr întreg | ID-ul cuvântului-cheie. Folosește-l în `with_keywords` și în căile de cuvinte-cheie de mai jos. |
| `keywords[].name` | șir          | Textul cuvântului-cheie.                                                                        |

### Exemplu de răspuns

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

Răspunsul real conține 14 cuvinte-cheie. Acesta este tăiat la primele 3. Numele cuvintelor-cheie nu sunt traduse, deci `language` nu are efect aici.

## Cuvinte-cheie pentru un serial TV

`GET /3/tv/{series_id}/keywords` primește aceeași cheie și întoarce aceleași obiecte, dar array-ul se numește `results`. ID-ul din cale este ID-ul serialului, de exemplu `1396`.

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

Răspunsul real conține 29 de intrări, iar acesta este tăiat la primele 2. Un client care servește ambele tipuri de media poate citi `data.keywords ?? data.results` și le poate trata la fel.

## Fișele de cuvinte-cheie și filmele lor

| Metodă și cale                     | Întoarce                                                                           | Parametri          |
| ---------------------------------- | ---------------------------------------------------------------------------------- | ------------------ |
| `GET /keyword/{keyword_id}`        | `{ id, name }`                                                                     | niciunul           |
| `GET /keyword/{keyword_id}/movies` | Listă paginată de filme cu `id`, `page`, `results`, `total_pages`, `total_results` | `language`, `page` |

Ambele căi folosesc ID-ul numeric dintr-un array de cuvinte-cheie. Lista de filme dă aceeași structură de element ca alte [liste de filme](https://amodb.dev/ro/trending-lists/), inclusiv `genre_ids` și `poster_path`, plus `id`-ul cuvântului-cheie la nivelul de sus. `include_adult` este acceptat și ignorat. O pagină dincolo de `total_pages` întoarce un array `results` gol. Nu există o listă de seriale pentru un cuvânt-cheie, deci folosește `/discover/tv?with_keywords=` pentru TV.

## Combină cuvintele-cheie cu discover

Pentru orice dincolo de o listă simplă, filtrează în [descoperire](https://amodb.dev/ro/discover/). Sortează, paginează și combină cuvintele-cheie cu alte filtre și acoperă TV la fel ca filmele.

| Scop                                      | Șir de interogare                                  |
| ----------------------------------------- | -------------------------------------------------- |
| Filme cu un cuvânt-cheie                  | `/discover/movie?with_keywords=818`                |
| Filme cu ambele din două cuvinte-cheie    | `/discover/movie?with_keywords=818,4565`           |
| Filme fără un cuvânt-cheie                | `/discover/movie?without_keywords=818`             |
| Seriale cu un cuvânt-cheie                | `/discover/tv?with_keywords=9712`                  |
| Seriale cu oricare din două cuvinte-cheie | `/discover/tv?with_keywords=818%7C9712`            |
| Un cuvânt-cheie într-un gen               | `/discover/movie?with_keywords=818&with_genres=18` |

O virgulă între ID-uri înseamnă toate. Scrie o bară verticală între ID-uri, ca în `with_keywords=818|4565`, ca să se potrivească oricare. Rezultatele discover sunt ținute în cache la margine 30 de minute.

## Găsește un ID de cuvânt-cheie

Ca să transformi text într-un ID, apelează `GET /3/search/keyword?query=heist`. Întoarce o listă paginată de perechi `id` și `name`, câte 20 pe pagină. Vezi [căutare](https://amodb.dev/ro/search/) pentru setul complet de căi de căutare. O căutare de cuvinte-cheie care nu se potrivește cu nimic răspunde în prezent 500 cu `status_code` 11 în loc de o listă goală. Răspunsurile de căutare sunt ținute în cache 10 minute, dar fiecare apel se numără tot la cererile tale pe minut, deci aplică debounce pe o casetă cu sugestii.

## Erori

| HTTP | status_code | Când                                                                                |
| ---- | ----------- | ----------------------------------------------------------------------------------- |
| 401  | 7           | Cheia lipsește sau este greșită.                                                    |
| 402  | 36          | Perioada planului s-a încheiat.                                                     |
| 404  | 34          | Niciun cuvânt-cheie cu acel ID la `/keyword/{keyword_id}` și la lista lui de filme. |
| 405  | 37          | Ai folosit o metodă de scriere pe o cale de cuvinte-cheie.                          |
| 429  | 25          | Ai depășit cererile pe minut. Așteaptă numărul de secunde din `Retry-After`.        |
| 500  | 11          | O interogare `/search/keyword` care nu se potrivește cu nimic.                      |

Un ID de film sau de serial necunoscut pe căile de cuvinte-cheie nu dă 404. Primești HTTP 200 cu ID-ul și un array gol.

Vezi [erori](https://amodb.dev/ro/errors/) pentru fiecare cod și [limite de cereri](https://amodb.dev/ro/rate-limits/) pentru limitele planurilor.

## Note practice

- Stochează `id`-ul cuvântului-cheie, nu numele. Un nume poate fi reformulat, un ID nu se schimbă.
- Listele de cuvinte-cheie sunt ținute în cache împreună cu detaliile titlului, 6 ore. O reîmprospătare săptămânală pentru paginile de etichete este suficientă.
- Un singur titlu are o listă scurtă de etichete. Pentru pagini tematice, pornește de la un ID de cuvânt-cheie și listează titlurile lui în discover, nu invers.
- Folosește `without_keywords` ca să elimini zgomotul, de exemplu o etichetă pe care nu o vrei niciodată pe o pagină pentru familie.
- Un array gol este un răspuns valid pentru titluri obscure. Ascunde rândul de etichete în loc să arăți o eroare.

## Întrebări și răspunsuri

### De ce folosește răspunsul TV results, iar filmele keywords?

Așa le structurează TMDB v3, iar amodb păstrează asta ca clienții existenți să funcționeze. Filmele întorc un array keywords. Serialele TV întorc aceleași obiecte sub results. Citește data.keywords ?? data.results.

### Cum găsesc ID-ul unui cuvânt-cheie după nume?

Apelează calea de căutare a cuvintelor-cheie cu un query, de exemplu /3/search/keyword?query=heist. Întoarce o listă paginată de perechi id și name. Alege potrivirea exactă și stochează ID-ul.

### Pot folosi același ID de cuvânt-cheie pentru filme și TV?

Da. Un ID de cuvânt-cheie are aceeași valoare în discover pentru filme și în discover pentru TV, deci with_keywords funcționează pe ambele căi. Stochează un ID pe temă și reutilizează-l pentru ambele tipuri de media.

### Cum combin mai multe cuvinte-cheie într-o singură interogare?

Îmbină ID-urile în with_keywords cu virgulă ca să le ceri pe toate sau cu bară verticală ca să accepți oricare. Folosește without_keywords ca să excluzi ID-uri. Ține URL-ul în limita de lungime a clientului tău HTTP.

## Pagini conexe

- [API discover](https://amodb.dev/ro/discover/): API discover cu filtrele TMDB v3. Listează filme și seriale după gen, distribuție, companie, cuvânt-cheie, an, evaluare, durată și furnizor, cu sortare.
- [API căutare](https://amodb.dev/ro/search/): API căutare cu căile și JSON-ul TMDB v3. Găsește filme, seriale, persoane, colecții, companii și cuvinte-cheie după text, cu filtre de an și paginare.
- [API detalii film](https://amodb.dev/ro/movies/): API detalii film cu aceleași căi și același JSON ca TMDB v3. Preia un film după ID, adaugă credite, evaluări și atmosferă cu append_to_response, în 14 limbi.
- [API seriale TV](https://amodb.dev/ro/tv-series/): API seriale TV cu căile și JSON-ul TMDB v3. Preia un serial după ID cu sezoane, rețele și următorul episod, plus clasificări de conținut și furnizori.
- [Genuri și liste de referință](https://amodb.dev/ro/genres/): API listă de genuri cu căi TMDB v3: ID-uri de gen pentru filme și TV cu nume traduse, plus liste de țări, limbi, meserii, clasificări și furnizori de vizionare.
- [Ghid rapid](https://amodb.dev/ro/quickstart/): Fă primul apel amodb: ia o cheie, cere detaliile unui film în curl, JavaScript, Python, PHP sau Go, apoi încarcă posterul de pe img.amodb.dev. Sub 2 minute.

Actualizat: 2026-10-18. Source: https://amodb.dev/ro/keywords/
