# Рейтинги на филми и сериали

> GET /3/movie/{movie_id}/ratings и GET /3/tv/{tv_id}/ratings връщат оценки от IMDb, Kinopoisk, Metacritic, Rotten Tomatoes и TMDB. Всеки източник е обект с value и votes или null, когато е неизвестен. IMDb, Kinopoisk и TMDB са от 10, другите два от 100. Добавете append_to_response=ratings, за да ги слеете с детайлите.

## Ендпойнт

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

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

Отговор:

```json
{
  "id": 550,
  "imdb": {
    "value": 8.8,
    "votes": 2669989
  },
  "kinopoisk": {
    "value": 8.7,
    "votes": null
  },
  "metacritic": {
    "value": 67,
    "votes": null
  },
  "rotten_tomatoes": {
    "value": 81,
    "votes": null
  },
  "tmdb": {
    "value": 8.437,
    "votes": 33042
  }
}
```

## Вземане на рейтинги за филм

`GET /3/movie/{movie_id}/ratings` връща оценките, които източниците на рейтинги публикуват за един филм. Отговорът има `id` на филма и пет ключа за източници: `imdb`, `kinopoisk`, `metacritic`, `rotten_tomatoes` и `tmdb`. Всеки ключ за източник съдържа обект с `value` и `votes` или `null`, когато този източник не е известен за заглавието.

Примерът зарежда Fight Club (id 550) и отпечатва всеки източник, като отбелязва неизвестните.

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

```js
const res = await fetch('https://api.amodb.dev/3/movie/550/ratings', {
  headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` },
});
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const ratings = await res.json();
for (const source of ['imdb', 'kinopoisk', 'metacritic', 'rotten_tomatoes', 'tmdb']) {
  const score = ratings[source];
  console.log(source, score ? `${score.value} (votes: ${score.votes ?? 'unknown'})` : 'not known');
}
```

```python
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/movie/550/ratings",
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
ratings = r.json()
for source in ("imdb", "kinopoisk", "metacritic", "rotten_tomatoes", "tmdb"):
    score = ratings[source]
    if score is None:
        print(source, "not known")
    else:
        print(source, score["value"], "votes:", score["votes"] or "unknown")
```

```php
<?php
$ch = curl_init('https://api.amodb.dev/3/movie/550/ratings');
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");
}
$ratings = json_decode($body, true);
foreach (['imdb', 'kinopoisk', 'metacritic', 'rotten_tomatoes', 'tmdb'] as $source) {
    $score = $ratings[$source];
    echo $source, ' ', $score === null ? 'not known' : $score['value'] . ' votes: ' . ($score['votes'] ?? 'unknown'), PHP_EOL;
}
```

```go
package main

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

type Score struct {
	Value float64 `json:"value"`
	Votes *int    `json:"votes"`
}

type Ratings struct {
	IMDb           *Score `json:"imdb"`
	Kinopoisk      *Score `json:"kinopoisk"`
	Metacritic     *Score `json:"metacritic"`
	RottenTomatoes *Score `json:"rotten_tomatoes"`
	TMDB           *Score `json:"tmdb"`
}

func show(name string, s *Score) {
	if s == nil {
		fmt.Println(name, "not known")
		return
	}
	if s.Votes == nil {
		fmt.Println(name, s.Value, "votes: unknown")
		return
	}
	fmt.Println(name, s.Value, "votes:", *s.Votes)
}

func main() {
	req, _ := http.NewRequest("GET", "https://api.amodb.dev/3/movie/550/ratings", 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 r Ratings
	if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
		panic(err)
	}
	show("imdb", r.IMDb)
	show("kinopoisk", r.Kinopoisk)
	show("metacritic", r.Metacritic)
	show("rotten_tomatoes", r.RottenTomatoes)
	show("tmdb", r.TMDB)
}
```

### Параметри

| Параметър  | Къде   | Задължителен  | Описание                                                            |
| ---------- | ------ | ------------- | ------------------------------------------------------------------- |
| `movie_id` | път    | да            | Числов id на филма, например `550`.                                 |
| `api_key`  | заявка | един от двата | Вашият ключ. Ползвайте него или заглавката `Authorization: Bearer`. |

### Полета на отговора

| Поле              | Тип                 | Бележки                                                                                        |
| ----------------- | ------------------- | ---------------------------------------------------------------------------------------------- |
| `id`              | цяло число          | Id на филма. Липсва, когато ползвате `append_to_response`.                                     |
| `imdb`            | обект или null      | Оценка на IMDb, от 10 с един десетичен знак.                                                   |
| `kinopoisk`       | обект или null      | Оценка на Kinopoisk, от 10 с един десетичен знак.                                              |
| `metacritic`      | обект или null      | Оценка на Metacritic, от 100 като цяло число.                                                  |
| `rotten_tomatoes` | обект или null      | Оценка на Rotten Tomatoes, от 100 като цяло число.                                             |
| `tmdb`            | обект или null      | Потребителска оценка на TMDB, от 10 с до три десетични знака.                                  |
| `value`           | число               | Вътре във всеки обект на източник. Оценката по собствената скала на този източник.             |
| `votes`           | цяло число или null | Вътре във всеки обект на източник. Брой гласове зад оценката или `null`, когато не е известен. |

Четете петте ключа на източници по име и пропускайте всеки друг ключ. Ключовете на източниците винаги идват в един и същи ред: `imdb`, `kinopoisk`, `metacritic`, `rotten_tomatoes`, `tmdb`.

### Примерен отговор

```json
{
  "id": 550,
  "imdb": { "value": 8.8, "votes": 2669989 },
  "kinopoisk": { "value": 8.7, "votes": null },
  "metacritic": { "value": 67, "votes": null },
  "rotten_tomatoes": { "value": 81, "votes": null },
  "tmdb": { "value": 8.437, "votes": 33039 }
}
```

Тук само IMDb и TMDB идват с брой гласове. Kinopoisk, Metacritic и Rotten Tomatoes имат оценка и брой гласове `null`.

## Вземане на рейтинги за сериал

`GET /3/tv/{tv_id}/ratings` има същите ключове и същите правила за null. Подайте id на сериала, например `1396` за Breaking Bad.

| Метод и път                       | Какво връща          | Параметри  |
| --------------------------------- | -------------------- | ---------- |
| `GET /3/movie/{movie_id}/ratings` | `id` и пет източника | `movie_id` |
| `GET /3/tv/{tv_id}/ratings`       | `id` и пет източника | `tv_id`    |

```bash
curl -sf "https://api.amodb.dev/3/tv/1396/ratings" -H "Authorization: Bearer $AMODB_KEY"
```

Breaking Bad няма оценка в Metacritic, затова този източник е `null`:

```json
{
  "id": 1396,
  "imdb": { "value": 9.5, "votes": 2671962 },
  "kinopoisk": { "value": 8.9, "votes": null },
  "metacritic": null,
  "rotten_tomatoes": { "value": 96, "votes": null },
  "tmdb": { "value": 9, "votes": 18863 }
}
```

## Добавяне на рейтинги към извикване за детайли

`append_to_response=ratings` работи при детайли на филм и сериал. Обектът пристига под ключа `ratings` до обичайните полета, без собствено `id`. Страница със списък иска една заявка на заглавие вместо две.

| Заявка                                          | Къде се появяват оценките                 |
| ----------------------------------------------- | ----------------------------------------- |
| `/3/movie/550?append_to_response=ratings`       | `ratings` в записа на филма               |
| `/3/tv/1396?append_to_response=credits,ratings` | `ratings` и `credits` в записа на сериала |

Вижте [детайли за филм](https://amodb.dev/bg/movies/) и [сериали](https://amodb.dev/bg/tv-series/) за другите стойности, които можете да добавите.

## Източници и стойности null

Източник със стойност null не е нулева оценка. Означава, че оценката за заглавието липсва.

| Ключ              | Източник        | Скала       | Етикет за показване |
| ----------------- | --------------- | ----------- | ------------------- |
| `imdb`            | IMDb            | от 0 до 10  | IMDb                |
| `kinopoisk`       | Kinopoisk       | от 0 до 10  | Kinopoisk           |
| `metacritic`      | Metacritic      | от 0 до 100 | Metacritic          |
| `rotten_tomatoes` | Rotten Tomatoes | от 0 до 100 | Rotten Tomatoes     |
| `tmdb`            | TMDB            | от 0 до 10  | TMDB                |

Покритието зависи от заглавието, затова пишете кода си спрямо null, а не спрямо фиксиран списък от източници. Всеки от петте ключа може да е null за всяко заглавие.

## С какво рейтингите се различават от vote_average

Полетата `vote_average` и `vote_count` в записа на филм или сериал са потребителската оценка на TMDB. Ключът `tmdb` носи същата оценка в същата форма като другите четири, така че едно извикване ви дава и петте източника в един формат.

Всеки източник има своя аудитория и скала. Не ги усреднявайте и не сравнявайте стойност от един източник с броя гласове на друг.

## Показване на рейтинги в приложение

Показвайте само наличните източници. Кратък списък от значки стига за карта. Добавете скалата, за да може читателят да различи 8.8 от 10 от 67 от 100.

```js
const labels = {
  imdb: ['IMDb', 10],
  kinopoisk: ['Kinopoisk', 10],
  metacritic: ['Metacritic', 100],
  rotten_tomatoes: ['Rotten Tomatoes', 100],
  tmdb: ['TMDB', 10],
};

function badges(ratings) {
  return Object.entries(labels)
    .filter(([key]) => ratings[key])
    .map(([key, [label, max]]) => `${label} ${ratings[key].value}/${max}`);
}
```

Показвайте етикета с всяка стойност. Когато и петте са null, скрийте блока вместо да показвате празни значки.

## Грешки

Неуспехите запазват тялото на грешката на TMDB, където `success` е false, а `status_code` назовава проблема. Заглавие без оценки не е такъв случай.

| HTTP | status_code | Кога                                                                      |
| ---- | ----------- | ------------------------------------------------------------------------- |
| 401  | 7           | Ключът липсва или е грешен.                                               |
| 402  | 36          | Периодът на плана е изтекъл.                                              |
| 404  | 34          | Няма филм или сериал с това id.                                           |
| 429  | 25          | Надхвърлен е лимитът на заявки в минута. Изчакайте `Retry-After` секунди. |

Неизвестна оценка е `null`, а не грешка. Подробности има на страниците [грешки](https://amodb.dev/bg/errors/) и [лимити на заявките](https://amodb.dev/bg/rate-limits/).

## Практически бележки

- Рейтингите се кешират на edge за 6 часа, както детайлите. По-честото обновяване връща същото тяло.
- Заявка с `append_to_response=ratings` се брои като една заявка от вашите 20, 40 или 120 заявки в минута.
- Пазете оценките с датата, на която сте ги взели. Гласовете растат с времето и числата се движат.
- За да съпоставите първо IMDb или Kinopoisk id със заглавие, ползвайте [търсене по външен идентификатор](https://amodb.dev/bg/find-by-external-id/). За усещания, а не оценки, вижте [настроения](https://amodb.dev/bg/moods/).

## Въпроси и отговори

### Защо източникът е null?

Null означава, че оценката липсва или е нула за това заглавие. Нова премиера или регионален филм често има по-малко източници от известния, затова винаги обработвайте null, преди да форматирате число. Полето votes също може да е null.

### С какво това се различава от vote_average?

Полето vote_average в записа за детайли е само потребителската оценка на TMDB. Ендпойнтът за рейтинги я връща отново под ключа tmdb, с три знака след десетичната запетая, и добавя другите четири източника, всеки като value и votes.

### Мога ли да усредня петте оценки?

Не го правете. IMDb, Kinopoisk и TMDB са от 10, докато Metacritic и Rotten Tomatoes са от 100. Всеки източник има и своя аудитория, а някои са null. Показвайте наличните източници един до друг с етикетите им.

### Струва ли извикването за рейтинги допълнителни заявки?

То е една заявка като всяка друга. С append_to_response=ratings оценките идват в извикване за детайли, така че ползвате един слот в минутата вместо два.

## Свързани страници

- [API за детайли на филм](https://amodb.dev/bg/movies/): API за детайли на филм със същите пътища и JSON като TMDB v3. Един филм по id, а актьори, рейтинги и настроения през append_to_response, на 14 езика.
- [API за сериали](https://amodb.dev/bg/tv-series/): API за сериали със същите пътища и JSON като TMDB v3. Сериал по id със сезони, мрежи и следващ епизод, плюс възрастови рейтинги и доставчици за гледане.
- [Търсене по външен идентификатор](https://amodb.dev/bg/find-by-external-id/): Търсете филм, сериал или личност по IMDb, TVDB, Wikidata или Kinopoisk id с ендпойнта find на TMDB и четете външни id и факти от Wikidata за заглавие.
- [Индикатори за настроение](https://amodb.dev/bg/moods/): API за настроение с индикатори от 0 до 10 за заглавие. Вземете настроението на филм или сериал, добавете го с append_to_response=moods и направете значки.
- [Лимити на заявките](https://amodb.dev/bg/rate-limits/): amodb ограничава всеки ключ по заявки в минута в плъзгащ се прозорец от 60 секунди: 20, 40 или 120. Заглавки за лимита и обработка на 429 с Retry-After.
- [Бърз старт](https://amodb.dev/bg/quickstart/): Първата ви заявка към amodb: вземете ключ, поискайте детайли за филм с curl, JavaScript, Python, PHP или Go и заредете постера от img.amodb.dev. До 2 минути.

Обновено: 2026-10-18. Source: https://amodb.dev/bg/ratings/
