# Рэйтынгі фільмаў і серыялаў

> 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/be/movies/) і [серыялы](https://amodb.dev/be/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/be/errors/) і [ліміты запытаў](https://amodb.dev/be/rate-limits/).

## Практычныя заўвагі

- Рэйтынгі кэшуюцца на edge на 6 гадзін, як і дэталі. Больш частае абнаўленне вяртае тое ж цела.
- Запыт з `append_to_response=ratings` лічыцца адным запытам з вашых 20, 40 або 120 запытаў у хвіліну.
- Захоўвайце ацэнкі з датай атрымання. Галасы з часам растуць, і лічбы змяняюцца.
- Каб спачатку супаставіць IMDb або Kinopoisk id з назвай, выкарыстоўвайце [пошук па вонкавым ідэнтыфікатары](https://amodb.dev/be/find-by-external-id/). Пра пачуцці, а не ацэнкі, гл. [настрой](https://amodb.dev/be/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/be/movies/): API дэталяў фільма з тымі ж шляхамі і JSON, што ў TMDB v3. Адзін фільм па id, а акцёры, рэйтынгі і настрой праз append_to_response, на 14 мовах.
- [API серыялаў](https://amodb.dev/be/tv-series/): API серыялаў з тымі ж шляхамі і JSON, што ў TMDB v3. Серыял па id з сезонамі, тэлеканаламі і наступным эпізодам, плюс узроставыя рэйтынгі і сэрвісы прагляду.
- [Пошук па вонкавым ідэнтыфікатары](https://amodb.dev/be/find-by-external-id/): Шукайце фільм, серыял або персону па IMDb, TVDB, Wikidata ці Kinopoisk id праз эндпоінт find TMDB і чытайце вонкавыя id і факты Wikidata для назвы.
- [Індыкатары настрою](https://amodb.dev/be/moods/): API настрою з індыкатарамі ад 0 да 10 для кожнай назвы. Дадавайце настрой фільма ці серыяла праз append_to_response=moods і будуйце значкі або фільтры.
- [Ліміты запытаў](https://amodb.dev/be/rate-limits/): amodb абмяжоўвае ключ па запытах у хвіліну ў слізгальным акне 60 секунд: 20, 40 або 120 па плане. Чытайце загалоўкі лімітаў і апрацоўвайце 429 праз Retry-After.
- [Хуткі старт](https://amodb.dev/be/quickstart/): Першы выклік да amodb: атрымайце ключ, запытайце дэталі фільма ў curl, JavaScript, Python, PHP або Go і загрузіце постэр з img.amodb.dev. Менш за 2 хвіліны.

Абноўлена: 2026-10-18. Source: https://amodb.dev/be/ratings/
