# API выяў і хост выяў

> Эндпоінты выяў пералічваюць постэры, фонавыя выявы, лагатыпы, профілі і кадры назвы ў выглядзе шляхоў да файлаў. Потым вы загружаеце кожны файл з img.amodb.dev у фіксаваным памеры, без ключа і з 30-дзённым edge-кэшам. Шляхі і JSON адпавядаюць TMDB v3, таму існуючы код для выяў працуе пасля змены базавага URL.

## Эндпоінт

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

```bash
curl "https://api.amodb.dev/3/movie/550/images?include_image_language=en,null" \
  -H "Authorization: Bearer $AMODB_KEY"
```

Адказ:

```json
{
  "id": 550,
  "backdrops": [
    {
      "aspect_ratio": 1.778,
      "height": 1440,
      "iso_639_1": null,
      "file_path": "/c6OLXfKAk5BKeR6broC8pYiCquX.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "width": 2560
    },
    {
      "aspect_ratio": 1.778,
      "height": 1080,
      "iso_639_1": "en",
      "file_path": "/b9HyPoxwxjxkWEUL5ErZdhApQe2.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "width": 1920
    },
    {
      "aspect_ratio": 1.778,
      "height": 2160,
      "iso_639_1": "en",
      "file_path": "/ewMhHVyXQKMAviVWM7InPjZqpSr.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "width": 3840
    }
  ],
  "logos": [
    {
      "aspect_ratio": 4.638,
      "height": 389,
      "iso_639_1": "en",
      "file_path": "/7Uqhv24pGJs4Ns31NoOPWFJGWNG.png",
      "vote_average": 0,
      "vote_count": 0,
      "width": 1804
    },
    {
      "aspect_ratio": 0.848,
      "height": 1295,
      "iso_639_1": "en",
      "file_path": "/4XkF0Rf7gvSfea8fYLFbU5tmuJw.png",
      "vote_average": 0,
      "vote_count": 0,
      "width": 1098
    },
    {
      "aspect_ratio": 1.457,
      "height": 1299,
      "iso_639_1": "en",
      "file_path": "/lm0VCzO1ZFhyx81k5Fzkex4u6C8.png",
      "vote_average": 0,
      "vote_count": 0,
      "width": 1893
    }
  ],
  "posters": [
    {
      "aspect_ratio": 0.667,
      "height": 3000,
      "iso_639_1": "en",
      "file_path": "/jSziioSwPVrOy9Yow3XhWIBDjq1.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "width": 2000
    },
    {
      "aspect_ratio": 0,
      "height": 0,
      "iso_639_1": null,
      "file_path": "/qkrH7rjYKU4KOwwIl6wF6H3ISvm.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "width": 0
    },
    {
      "aspect_ratio": 0,
      "height": 0,
      "iso_639_1": null,
      "file_path": "/efBb4gjjKneUoBVgfFOUu2OwihS.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "width": 0
    }
  ]
}
```

## Атрыманне выяў фільма

`GET /3/movie/{movie_id}/images` пералічвае кожную вядомую выяву аднаго фільма ў трох масівах: `backdrops`, `logos` і `posters`. Кожны запіс мае `file_path`, памер у пікселях і тэг мовы. Сам файл у JSON не ўтрымліваецца. Яго трэба загрузіць з хоста выяў другім крокам.

У прыкладзе запытваюцца англійскія выявы і выявы без тэксту, выбіраецца першы англійскі постэр, а потым гэты файл загружаецца шырынёй 500 пікселяў.

```bash
curl -s "https://api.amodb.dev/3/movie/550/images?include_image_language=en,null" \
  -H "Authorization: Bearer $AMODB_KEY"

curl -s -o poster.jpg -w "%{http_code}\n" \
  "https://img.amodb.dev/t/p/w500/jSziioSwPVrOy9Yow3XhWIBDjq1.jpg"
```

```js
const url = 'https://api.amodb.dev/3/movie/550/images?include_image_language=en,null';
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` } });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { posters } = await res.json();
if (posters.length === 0) throw new Error('no posters');
const poster = posters.find((p) => p.iso_639_1 === 'en') ?? posters[0];
const posterUrl = `https://img.amodb.dev/t/p/w500${poster.file_path}`;
const img = await fetch(posterUrl);
console.log(img.status, img.headers.get('content-type'), posterUrl);
```

```python
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/movie/550/images",
    params={"include_image_language": "en,null"},
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
posters = r.json()["posters"]
if not posters:
    raise SystemExit("no posters")
poster = next((p for p in posters if p["iso_639_1"] == "en"), posters[0])
poster_url = "https://img.amodb.dev/t/p/w500" + poster["file_path"]
img = requests.get(poster_url, timeout=10)
print(img.status_code, img.headers.get("content-type"), poster_url)
```

```php
<?php
$url = 'https://api.amodb.dev/3/movie/550/images?include_image_language=en,null';
$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");
}
$posters = json_decode($body, true)['posters'];
if (!$posters) {
    throw new RuntimeException('no posters');
}
$poster = $posters[0];
foreach ($posters as $p) {
    if ($p['iso_639_1'] === 'en') {
        $poster = $p;
        break;
    }
}
$posterUrl = 'https://img.amodb.dev/t/p/w500' . $poster['file_path'];
$img = curl_init($posterUrl);
curl_setopt_array($img, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10]);
curl_exec($img);
echo curl_getinfo($img, CURLINFO_HTTP_CODE), ' ', curl_getinfo($img, CURLINFO_CONTENT_TYPE), ' ', $posterUrl, PHP_EOL;
curl_close($img);
```

```go
package main

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

type Images struct {
	Posters []struct {
		FilePath string `json:"file_path"`
		Language string `json:"iso_639_1"`
	} `json:"posters"`
}

func main() {
	url := "https://api.amodb.dev/3/movie/550/images?include_image_language=en,null"
	req, _ := http.NewRequest("GET", url, 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 images Images
	if err := json.NewDecoder(res.Body).Decode(&images); err != nil || len(images.Posters) == 0 {
		panic("no posters")
	}
	poster := images.Posters[0]
	for _, p := range images.Posters {
		if p.Language == "en" {
			poster = p
			break
		}
	}
	posterURL := "https://img.amodb.dev/t/p/w500" + poster.FilePath
	img, err := client.Get(posterURL)
	if err != nil {
		panic(err)
	}
	defer img.Body.Close()
	fmt.Println(img.StatusCode, img.Header.Get("Content-Type"), posterURL)
}
```

### Параметры

| Параметр                 | Дзе   | Абавязковы   | Апісанне                                                                                                                                                                  |
| ------------------------ | ----- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `movie_id`               | шлях  | так          | Лікавы id фільма, напрыклад `550`.                                                                                                                                        |
| `api_key`                | запыт | адзін з двух | Ваш ключ. Выкарыстоўвайце яго або загаловак `Authorization: Bearer`.                                                                                                      |
| `include_image_language` | запыт | не           | Коды ISO 639-1 праз коску. Дадайце `null`, каб уключыць выявы без тэксту, напрыклад `en,null`. Вяртаюцца толькі пералічаныя мовы. Без параметра вы атрымаеце кожную мову. |
| `language`               | запыт | не           | Прымаецца, але на гэтым эндпоінце ігнаруецца. Для выбару моў выкарыстоўвайце `include_image_language`.                                                                    |

### Палі адказу

| Поле                            | Тып            | Заўвагі                                                                                                                          |
| ------------------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `id`                            | цэлы лік       | Id фільма.                                                                                                                       |
| `backdrops`, `logos`, `posters` | масіў          | Адзін масіў на кожны від выявы, у такім парадку ключоў. Кожны можа быць пустым.                                                  |
| `file_path`                     | радок          | Пачынаецца з косай рыскі. Дадайце яго да памеру на хосце выяў. Постэры і фонавыя выявы маюць `.jpg`, лагатыпы `.png` або `.svg`. |
| `width`, `height`               | цэлы лік       | Памер зыходнага файла ў пікселях. `0`, калі памер невядомы.                                                                      |
| `aspect_ratio`                  | лік            | Шырыня, падзеленая на вышыню. Постэры каля 0.667, фонавыя выявы каля 1.778. `0`, калі памер невядомы.                            |
| `iso_639_1`                     | радок або null | Мова тэксту на выяве. `null` азначае, што тэксту няма.                                                                           |
| `vote_average`, `vote_count`    | лік, цэлы лік  | Для выяў фільмаў і серыялаў заўсёды `0`, таму па іх нельга ранжыраваць выявы. Захоўвайце парадак, які вяртае API.                |

### Прыклад адказу

Паказаны па два запісы ў кожным масіве.

```json
{
  "id": 550,
  "backdrops": [
    {
      "aspect_ratio": 1.778,
      "height": 1440,
      "iso_639_1": null,
      "file_path": "/c6OLXfKAk5BKeR6broC8pYiCquX.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "width": 2560
    },
    {
      "aspect_ratio": 1.778,
      "height": 1080,
      "iso_639_1": "en",
      "file_path": "/b9HyPoxwxjxkWEUL5ErZdhApQe2.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "width": 1920
    }
  ],
  "logos": [
    {
      "aspect_ratio": 4.638,
      "height": 389,
      "iso_639_1": "en",
      "file_path": "/7Uqhv24pGJs4Ns31NoOPWFJGWNG.png",
      "vote_average": 0,
      "vote_count": 0,
      "width": 1804
    },
    {
      "aspect_ratio": 0.848,
      "height": 1295,
      "iso_639_1": "en",
      "file_path": "/4XkF0Rf7gvSfea8fYLFbU5tmuJw.png",
      "vote_average": 0,
      "vote_count": 0,
      "width": 1098
    }
  ],
  "posters": [
    {
      "aspect_ratio": 0.667,
      "height": 3000,
      "iso_639_1": "en",
      "file_path": "/jSziioSwPVrOy9Yow3XhWIBDjq1.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "width": 2000
    },
    {
      "aspect_ratio": 0,
      "height": 0,
      "iso_639_1": null,
      "file_path": "/qkrH7rjYKU4KOwwIl6wF6H3ISvm.jpg",
      "vote_average": 0,
      "vote_count": 0,
      "width": 0
    }
  ]
}
```

Другі постэр паказвае запіс, памер якога невядомы. Файл усё роўна загружаецца.

## Як скласці URL выявы

Злучыце тры часткі: `https://img.amodb.dev/t/p/`, сегмент памеру і `file_path`. Шлях ужо пачынаецца з косай рыскі, таму `https://img.amodb.dev/t/p/w500` плюс `/jSziioSwPVrOy9Yow3XhWIBDjq1.jpg` ёсць поўным URL.

Памер ёсць `w` плюс шырыня ў пікселях, `h` плюс вышыня ў пікселях або `original` для захаванага файла. Хост аддае дзесяць памераў: `w92`, `w154`, `w185`, `w300`, `w342`, `w500`, `w780`, `w1280`, `h632` і `original`. Любы іншы памер, напрыклад `w400`, адказвае 404. `/3/configuration` пералічвае памеры, што пасуюць да кожнага віду выявы.

| Від           | Поле канфігурацыі | Памеры                                                    |
| ------------- | ----------------- | --------------------------------------------------------- |
| Постэр        | `poster_sizes`    | `w92`, `w154`, `w185`, `w342`, `w500`, `w780`, `original` |
| Фонавая выява | `backdrop_sizes`  | `w300`, `w780`, `w1280`, `original`                       |
| Лагатып       | `logo_sizes`      | `w92`, `w154`, `w185`, `w300`, `w500`, `original`         |
| Профіль       | `profile_sizes`   | `w185`, `h632`, `original`                                |
| Кадр          | `still_sizes`     | `w92`, `w185`, `w300`, `original`                         |

Хост не правярае від выявы, таму постэр таксама загружаецца ў памеры `w1280`. Трымайцеся памераў, пералічаных для віду, каб ваш код супадаў з канфігурацыяй і любым кліентам TMDB.

Хост выяў не патрабуе ключа, а edge захоўвае кожны файл 30 дзён. Паколькі ключ не перадаецца, загрузкі выяў не расходуюць ваш ліміт запытаў у хвіліну. Адказы нясуць `Access-Control-Allow-Origin: *`, таму браўзер можа загружаць іх з любой старонкі. Невядомы памер або невядомы файл адказвае 404 з целам JSON.

## Адаптыўныя выявы з srcset

Выбірайце найменшы памер, што ўсё яшчэ пакрывае шырыню паказу, памножаную на шчыльнасць экрана. Постэр шырынёй 171 CSS-піксель патрабуе `w342` на экране 2x. Гэты дапаможнік будуе `srcset` са захаванага шляху.

```js
const WIDTHS = [185, 342, 500, 780];

function posterSrcset(filePath) {
  return WIDTHS.map((w) => `https://img.amodb.dev/t/p/w${w}${filePath} ${w}w`).join(', ');
}

const path = '/jSziioSwPVrOy9Yow3XhWIBDjq1.jpg';
console.log(`<img src="https://img.amodb.dev/t/p/w342${path}" srcset="${posterSrcset(path)}" sizes="(max-width: 600px) 50vw, 342px" alt="Fight Club poster">`);
```

## Іншыя эндпоінты выяў

Усе шляхі ніжэй выкарыстоўваюць базу `https://api.amodb.dev/3` і вяртаюць масівы, названыя ў другой калонцы.

| Метад і шлях                                                                 | Якія масівы вяртаюцца                                 | Параметры                |
| ---------------------------------------------------------------------------- | ----------------------------------------------------- | ------------------------ |
| `GET /tv/{series_id}/images`                                                 | `backdrops`, `logos`, `posters`                       | `include_image_language` |
| `GET /tv/{series_id}/season/{season_number}/images`                          | `posters`, заўсёды пусты                              | няма                     |
| `GET /tv/{series_id}/season/{season_number}/episode/{episode_number}/images` | `stills`, адзін запіс з `width` і `height`, роўнымі 0 | няма                     |
| `GET /person/{person_id}/images`                                             | `profiles`                                            | няма                     |

Для фільмаў і серыялаў можна таксама дадаць `append_to_response=images` да выкліку дэталяў. `include_image_language` працуе і там. Далучаны блок не мае ўласнага `id`.

Профілі персон гэта адзінае месца, дзе `vote_average` нясе сапраўдную ацэнку. `id` у адказе па сезоне або эпізодзе гэта id сезона або эпізода. Бацькоўскія запісы гл. на старонках [персоны](https://amodb.dev/be/people/) і [серыялы](https://amodb.dev/be/tv-series/).

amodb не прапануе шляхі выяў для калекцый, кампаній і тэлеканалаў. Іх запісы ўжо ўтрымліваюць адзін `poster_path`, `backdrop_path` або `logo_path`, апісаны на старонках [калекцыі](https://amodb.dev/be/collections/) і [кампаніі і тэлеканалы](https://amodb.dev/be/companies-networks/).

## Эндпоінт канфігурацыі

`GET /3/configuration` вяртае блок `images` з `secure_base_url`, роўным `https://img.amodb.dev/t/p/`, `base_url` (просты варыянт http) і спісамі памераў `backdrop_sizes`, `logo_sizes`, `poster_sizes`, `profile_sizes` і `still_sizes`. Чытайце яго адзін раз пры старце, выкарыстоўвайце бяспечную форму і складайце URL па ім, а не жорстка задавайце памеры. Edge кэшуе яго на 24 гадзіны.

## Памылкі

| HTTP | status_code | Калі                                                                                   |
| ---- | ----------- | -------------------------------------------------------------------------------------- |
| 401  | 7           | Ключ адсутнічае або няправільны ў выкліку JSON.                                        |
| 402  | 36          | Тэрмін дзеяння плана скончыўся.                                                        |
| 404  | 34          | Няма персоны, сезона або эпізода з гэтым id, або невядомы памер ці файл на хосце выяў. |
| 405  | 37          | Вы выкарысталі метад запісу на шляху выяў.                                             |
| 429  | 25          | Вы перавысілі ліміт запытаў у хвіліну. Пачакайце `Retry-After` секунд.                 |

Id фільма або серыяла, якога не існуе, тут не памылка: шлях выяў адказвае 200 з пустымі масівамі, а шлях дэталяў адказвае 404. Поўны спіс гл. на старонцы [памылкі](https://amodb.dev/be/errors/). Запыты файлаў выяў гэта звычайныя HTTP-загрузкі, таму правярайце код статусу адказу, а не разбірайце цела JSON.

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

- Захоўвайце `file_path` у сваёй базе даных і складайце URL падчас адлюстравання. Тады новы памер або хост патрабуе адной змены ў кодзе.
- Перадавайце `include_image_language` з вашай мовай адлюстравання плюс `null`, напрыклад `ru,null`, каб не траплялі постэры з чужым тэкстам.
- Пусты масіў гэта нармальны 200. Звярніцеся да `poster_path` у запісе [дэталяў фільма](https://amodb.dev/be/movies/).
- Выкарыстоўвайце `w1280` для фонавых выяў на ўсю шырыню і `w780` для картак. `original` гэта захаваны файл у поўным разрозненні, і ён значна большы за `w780`.
- Копіі на edge жывуць 30 дзён і агульныя, таму файл, які запытаў адзін кліент, аддаецца з кэшу наступнаму.

## Пытанні і адказы

### Ці патрабуюць запыты выяў ключ API?

Не. Файлы па img.amodb.dev/t/p/{size}/{file} публічныя, таму іх можна выкарыстоўваць наўпрост у тэгах img і CSS. Ключ патрэбны толькі JSON-эндпоінтам, якія пералічваюць шляхі да файлаў.

### Якія памеры выяў можна запытаць?

w92, w154, w185, w300, w342, w500, w780, w1280, h632 і original. Любы іншы памер адказвае 404. /3/configuration паказвае, якія з іх пасуюць да кожнага тыпу выявы, а табліца памераў на гэтай старонцы паўтарае гэта.

### Як атрымаць постэры толькі на адной мове?

Перадайце include_image_language са спісам праз коску, напрыклад en,null. Значэнне null дадае выявы без тэксту. Вяртаюцца толькі пералічаныя мовы. Параметр language выявы не фільтруе.

### Чаму шлях да файла пачынаецца з косай рыскі?

Шляхі ў стылі TMDB уключаюць пачатковую косую рыску, каб іх можна было дадаваць наўпрост да сегмента памеру. Захоўвайце толькі шлях і складайце поўны URL падчас адлюстравання.

## Звязаныя старонкі

- [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 з сезонамі, тэлеканаламі і наступным эпізодам, плюс узроставыя рэйтынгі і сэрвісы прагляду.
- [API дэталяў персоны](https://amodb.dev/be/people/): API дэталяў персоны з тымі ж шляхамі і JSON, што ў TMDB v3. Акцёр ці член групы па id з біяграфіяй, фільмаграфіяй, вонкавымі id і спісам папулярных.
- [API калекцый](https://amodb.dev/be/collections/): API калекцый фільмаў з шляхамі TMDB v3: чытайце франшызу па id з усімі часткамі, belongs_to_collection у фільме і шукайце калекцыі па назве.
- [API постэраў фільмаў і CDN выяў](https://amodb.dev/be/movie-poster-api/): API постэраў фільмаў з хостам выяў без ключа. Абірайце памеры ад w92 да original, складайце srcset і выбірайце постэры па мове праз include_image_language.
- [Хуткі старт](https://amodb.dev/be/quickstart/): Першы выклік да amodb: атрымайце ключ, запытайце дэталі фільма ў curl, JavaScript, Python, PHP або Go і загрузіце постэр з img.amodb.dev. Менш за 2 хвіліны.

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