# API תמונות ושרת תמונות

> נקודות הקצה של תמונות מציגות את הפוסטרים, תמונות הרקע, הלוגואים, תמונות הפרופיל ותמונות הסצנה של כותר כנתיבי קבצים. אחר כך טוענים כל קובץ מ-img.amodb.dev בגודל קבוע, בלי מפתח ועם מטמון קצה של 30 יום. הנתיבים וה-JSON זהים ל-TMDB v3, ולכן קוד תמונות קיים עובד אחרי החלפת כתובת בסיס.

## נקודת קצה

`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`               | נתיב   | כן         | מזהה סרט מספרי, למשל `550`.                                                                                                             |
| `api_key`                | שאילתה | אחד משניים | המפתח שלכם. השתמשו בו או בכותרת `Authorization: Bearer`.                                                                                |
| `include_image_language` | שאילתה | לא         | קודי ISO 639-1 מופרדים בפסיקים. הוסיפו `null` כדי לכלול תמונות בלי טקסט, למשל `en,null`. רק השפות שברשימה חוזרות. בלעדיו מקבלים כל שפה. |
| `language`               | שאילתה | לא         | מתקבל אבל מתעלמים ממנו בנקודת הקצה הזו. השתמשו ב-`include_image_language` כדי לבחור שפות.                                               |

### שדות התגובה

| שדה                             | סוג             | הערות                                                                                                      |
| ------------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------- |
| `id`                            | integer         | מזהה הסרט.                                                                                                 |
| `backdrops`, `logos`, `posters` | array           | מערך אחד לכל סוג תמונה, בסדר המפתחות הזה. כל אחד יכול להיות ריק.                                           |
| `file_path`                     | string          | מתחיל בלוכסן. מצרפים אותו לגודל במארח התמונות. פוסטרים ותמונות רקע הם `.jpg`, לוגואים הם `.png` או `.svg`. |
| `width`, `height`               | integer         | גודל הקובץ המקורי בפיקסלים. `0` כשהגודל לא ידוע.                                                           |
| `aspect_ratio`                  | number          | רוחב חלקי גובה. פוסטרים קרובים ל-0.667, תמונות רקע קרובות ל-1.778. `0` כשהגודל לא ידוע.                    |
| `iso_639_1`                     | string או null  | שפת הטקסט שעל התמונה. `null` פירושו בלי טקסט.                                                              |
| `vote_average`, `vote_count`    | number, integer | תמיד `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
    }
  ]
}
```

הפוסטר השני מציג פריט שגודלו לא ידוע. הקובץ עדיין נטען.

## בניית כתובת תמונה

מחברים שלושה חלקים: `https://img.amodb.dev/t/p/`, קטע גודל וה-`file_path`. הנתיב כבר מתחיל בלוכסן, ולכן `https://img.amodb.dev/t/p/w500` ועוד `/jSziioSwPVrOy9Yow3XhWIBDjq1.jpg` היא כתובת שלמה.

גודל הוא `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.

מארח התמונות לא דורש מפתח, והקצה שומר כל קובץ 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` בתגובה של עונה או פרק הוא מזהה העונה או הפרק. את הרשומות האב ראו בעמודים [אנשים](https://amodb.dev/he/people/) ו[סדרות טלוויזיה](https://amodb.dev/he/tv-series/).

amodb לא מציע נתיבי תמונות לאוספים, לחברות ולרשתות. הרשומות שלהם כבר מחזיקות `poster_path`, `backdrop_path` או `logo_path` אחד, כמתואר בעמודים [אוספים](https://amodb.dev/he/collections/) ו[חברות ורשתות שידור](https://amodb.dev/he/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`. קראו אותו פעם אחת בהפעלה, השתמשו בצורה המאובטחת ובנו ממנו כתובות במקום לקבוע גדלים בקוד. הקצה שומר אותו במטמון 24 שעות.

## שגיאות

| HTTP | status_code | מתי                                                                          |
| ---- | ----------- | ---------------------------------------------------------------------------- |
| 401  | 7           | המפתח חסר או שגוי בקריאת JSON.                                               |
| 402  | 36          | תקופת המסלול הסתיימה.                                                        |
| 404  | 34          | אין אדם, עונה או פרק עם המזהה הזה, או שגודל או קובץ לא מוכרים במארח התמונות. |
| 405  | 37          | השתמשתם בשיטת כתיבה בנתיב תמונות.                                            |
| 429  | 25          | חרגתם מהבקשות שלכם לדקה. המתינו `Retry-After` שניות.                         |

מזהה סרט או סדרה שלא קיים אינו שגיאה כאן: נתיב התמונות עונה 200 עם מערכים ריקים, בעוד נתיב הפרטים עונה 404. את הרשימה המלאה ראו בעמוד [שגיאות](https://amodb.dev/he/errors/). בקשות לקבצי תמונה הן טעינות HTTP רגילות, ולכן בדקו את קוד הסטטוס של התגובה במקום לפענח גוף JSON.

## הערות מעשיות

- שמרו את `file_path` במסד הנתונים ובנו את הכתובת בזמן ההצגה. גודל חדש או מארח חדש עולים אז שינוי קוד אחד.
- העבירו את `include_image_language` עם שפת התצוגה שלכם ועוד `null`, למשל `ru,null`, כדי שפוסטרים עם טקסט זר לא יופיעו.
- מערך ריק הוא 200 רגיל. חזרו אל `poster_path` ברשומת [פרטי הסרט](https://amodb.dev/he/movies/).
- השתמשו ב-`w1280` לתמונות רקע ברוחב מלא וב-`w780` לכרטיסים. `original` הוא הקובץ השמור ברזולוציה מלאה והוא גדול בהרבה מ-`w780`.
- עותקי קצה חיים 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 כוללים את הלוכסן בהתחלה כדי שאפשר יהיה לצרף אותם ישירות לקטע הגודל. שמרו את הנתיב לבדו ובנו את הכתובת המלאה בזמן ההצגה.

## עמודים קשורים

- [API פרטי סרט](https://amodb.dev/he/movies/): API פרטי סרט עם אותם נתיבים ו-JSON כמו TMDB v3. קבלו סרט לפי מזהה, הוסיפו קרדיטים, דירוגים, מצבי רוח ופסקולים עם append_to_response, ב-14 שפות.
- [API סדרות טלוויזיה](https://amodb.dev/he/tv-series/): API סדרות טלוויזיה עם אותם נתיבים ו-JSON כמו TMDB v3. קבלו סדרה לפי מזהה ב-GET /3/tv/{series_id} עם עונות, רשתות והפרק הבא, וגם סיווגי גיל וספקי צפייה.
- [API פרטי אדם](https://amodb.dev/he/people/): API פרטי אדם עם אותם נתיבים ו-JSON כמו TMDB v3. קבלו שחקן או איש צוות לפי מזהה, עם ביוגרפיה, פילמוגרפיה, מזהים חיצוניים, תמונות פרופיל והרשימה הפופולרית.
- [API לאוספים](https://amodb.dev/he/collections/): API אוספי סרטים עם נתיבי TMDB v3: שלפו זיכיון ב-GET /3/collection/{collection_id} עם מערך parts, קראו את belongs_to_collection בסרט וחפשו אוספים לפי שם.
- [API לפוסטרים של סרטים ו-CDN לתמונות](https://amodb.dev/he/movie-poster-api/): API לפוסטרים של סרטים עם שרת תמונות בלי מפתח. בחרו גדלים מ-w92 עד original, בנו רשימות srcset ובחרו פוסטרים לפי שפה עם include_image_language.
- [מדריך למתחילים](https://amodb.dev/he/quickstart/): בצעו את הקריאה הראשונה ל-amodb: קבלו מפתח, בקשו פרטי סרט ב-curl, JavaScript, Python, PHP או Go, ואז טענו את הפוסטר מ-img.amodb.dev. פחות מ-2 דקות.

עודכן: 2026-10-18. Source: https://amodb.dev/he/images-api/
