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

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

## Практичні поради

- Рейтинги кешуються на периферії мережі на 6 годин, як і деталі. Частіше оновлення повертає те саме тіло.
- Запит із `append_to_response=ratings` враховується як один запит у вашому ліміті 20, 40 або 120 запитів на хвилину.
- Зберігайте оцінки з датою отримання. Кількість голосів зростає з часом, і числа змінюються.
- Щоб спершу зіставити IMDb id чи Kinopoisk id з фільмом, використовуйте [пошук за зовнішнім ID](https://amodb.dev/uk/find-by-external-id/). Для відчуттів, а не оцінок, дивіться [настрої](https://amodb.dev/uk/moods/).

## Запитання й відповіді

### Чому джерело дорівнює null?

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

### Чим це відрізняється від vote_average?

Поле vote_average у записі деталей є лише оцінкою користувачів TMDB. Ендпоінт ratings повертає її знову під ключем tmdb, із трьома десятковими знаками, і додає ще чотири джерела, кожне як value і votes.

### Чи можна усереднити п'ять оцінок?

Не робіть цього. IMDb, Kinopoisk і TMDB мають шкалу з 10, а Metacritic і Rotten Tomatoes зі 100. Кожне джерело має й власну аудиторію, а деякі дорівнюють null. Показуйте наявні джерела поруч, із їхніми підписами.

### Чи виклик ratings коштує додаткових запитів?

Це один запит, як і будь-який інший. З append_to_response=ratings оцінки приходять усередині виклику деталей, тож ви використовуєте один запит із ліміту на хвилину замість двох.

## Пов'язані сторінки

- [API деталей фільму](https://amodb.dev/uk/movies/): API деталей фільму з тими самими шляхами та JSON, що в TMDB v3. Отримайте фільм за id, додайте акторів, рейтинги й настрої через append_to_response, 14 мовами.
- [API серіалів](https://amodb.dev/uk/tv-series/): API серіалів з тими самими шляхами та JSON, що в TMDB v3. Отримайте серіал за id із сезонами, телемережами й наступною серією, плюс вікові рейтинги.
- [Пошук за зовнішнім ID](https://amodb.dev/uk/find-by-external-id/): Знайдіть фільм, серіал чи персону за id IMDb, TVDB, Wikidata або Kinopoisk через find TMDB, а також прочитайте зовнішні id і факти Wikidata про проєкт.
- [Індикатори настрою](https://amodb.dev/uk/moods/): API настроїв фільмів з індикаторами від 0 до 10. Читайте настрої фільму чи серіалу, додавайте їх через append_to_response=moods і будуйте бейджі та фільтри.
- [Ліміти запитів](https://amodb.dev/uk/rate-limits/): amodb обмежує кожен ключ запитами на хвилину в ковзному вікні 60 секунд: 20, 40 або 120 за тарифом. Читайте заголовки ліміту й обробляйте 429 із Retry-After.
- [Швидкий старт](https://amodb.dev/uk/quickstart/): Перший виклик amodb: отримайте ключ, запросіть деталі фільму в curl, JavaScript, Python, PHP чи Go і завантажте постер з img.amodb.dev. Менш ніж за 2 хвилини.

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