# 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/bg/people/) и [сериали](https://amodb.dev/bg/tv-series/) за родителските записи.

amodb не предлага пътища за изображения за колекции, компании и мрежи. Записите им вече съдържат по един `poster_path`, `backdrop_path` или `logo_path`, описани на страниците [колекции](https://amodb.dev/bg/collections/) и [компании и мрежи](https://amodb.dev/bg/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/bg/errors/) за пълния списък. Заявките за файлове с изображения са обикновени HTTP зареждания, затова проверявайте статус кода на отговора, вместо да разчитате тяло JSON.

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

- Пазете `file_path` в базата си и градете URL адреса при показване. Тогава нов размер или хост струва една промяна в кода.
- Подайте `include_image_language` с езика си за показване плюс `null`, например `ru,null`, за да не се появяват постери с чужд текст.
- Празен масив е нормален 200. Върнете се към `poster_path` в записа с [детайли за филм](https://amodb.dev/bg/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/bg/movies/): API за детайли на филм със същите пътища и JSON като TMDB v3. Един филм по id, а актьори, рейтинги и настроения през append_to_response, на 14 езика.
- [API за сериали](https://amodb.dev/bg/tv-series/): API за сериали със същите пътища и JSON като TMDB v3. Сериал по id със сезони, мрежи и следващ епизод, плюс възрастови рейтинги и доставчици за гледане.
- [API за детайли на личност](https://amodb.dev/bg/people/): API за детайли на личност със същите пътища и JSON като TMDB v3. Актьор или член на екип по id с биография, филмография, външни id и списък с популярни.
- [API за колекции](https://amodb.dev/bg/collections/): API за колекции от филми с пътища на TMDB v3: франчайз по id с всичките му части, belongs_to_collection във филм и търсене на колекции по име.
- [API за постери на филми и CDN за изображения](https://amodb.dev/bg/movie-poster-api/): API за постери на филми с хост за изображения без ключ. Размери от w92 до original, srcset и избор на постери по език с include_image_language.
- [Бърз старт](https://amodb.dev/bg/quickstart/): Първата ви заявка към amodb: вземете ключ, поискайте детайли за филм с curl, JavaScript, Python, PHP или Go и заредете постера от img.amodb.dev. До 2 минути.

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