API сезонов и серий сериала
Читайте один сезон со всеми сериями через GET /3/tv/{series_id}/season/{season_number} или отдельную серию уровнем глубже. JSON совпадает с TMDB v3: air_date, episode_number, runtime и still_path. У каждой серии есть crew и guest_stars, сезон 0 содержит спецвыпуски, а append_to_response добавляет credits, images и videos.
Получение сезона
GET / возвращает один сезон и полный массив episodes в одном ответе. Номера сезонов начинаются с 1, а 0 зарезервирован для спецвыпусков. Id сериала и номера сезонов берите из записи сериала.
Пример читает сезон 1 сериала Breaking Bad. Код выводит по одной строке на серию.
curl -sSf "https://api.amodb.dev/3/tv/1396/season/1?language=en-US" \
-H "Authorization: Bearer $AMODB_KEY"const url = 'https://api.amodb.dev/3/tv/1396/season/1?language=en-US';
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` } });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const season = await res.json();
for (const ep of season.episodes) {
console.log(String(ep.episode_number).padStart(2, '0'), ep.name, ep.air_date, `${ep.runtime ?? '?'} min`);
}import os
import requests
r = requests.get(
"https://api.amodb.dev/3/tv/1396/season/1",
params={"language": "en-US"},
headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
timeout=10,
)
r.raise_for_status()
season = r.json()
for ep in season["episodes"]:
print(f"{ep['episode_number']:02d}", ep["name"], ep["air_date"], ep["runtime"] or "?")<?php
$url = 'https://api.amodb.dev/3/tv/1396/season/1?language=en-US';
$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");
}
$season = json_decode($body, true);
foreach ($season['episodes'] as $ep) {
printf("%02d %s %s\n", $ep['episode_number'], $ep['name'], $ep['air_date']);
}package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
"time"
)
type Season struct {
Name string `json:"name"`
Episodes []struct {
EpisodeNumber int `json:"episode_number"`
Name string `json:"name"`
AirDate string `json:"air_date"`
Runtime int `json:"runtime"`
} `json:"episodes"`
}
func main() {
req, _ := http.NewRequest("GET", "https://api.amodb.dev/3/tv/1396/season/1?language=en-US", 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 s Season
if err := json.NewDecoder(res.Body).Decode(&s); err != nil {
panic(err)
}
for _, e := range s.Episodes {
fmt.Printf("%02d %s %s %d min\n", e.EpisodeNumber, e.Name, e.AirDate, e.Runtime)
}
}Параметры
series_idпутьобязателенЧисловой id сериала, например1396.season_numberпутьобязателенЦелочисленный номер сезона.0возвращает спецвыпуски.api_keyqueryодно из двухВаш ключ. Используйте его или заголовокAuthorization: Bearer.languagequeryТег TMDB, напримерen-USилиfr-FR. Обслуживаются 14 базовых языков. По умолчаниюen-US.append_to_responsequeryЗначения уровня сезона:credits,external_ids,images,videos. Остальные имена игнорируются.
Поля ответа
| Поле | Тип | Примечания |
|---|---|---|
id, season_number | целое число | Id сезона и его номер внутри сериала. |
name, overview | строка | Локализованный текст, пуст, если перевода нет. |
air_date | строка или null | Дата первой серии, YYYY-MM-DD. |
poster_path | строка или null | Добавляйте к https:/. |
vote_average | число | Суммарная пользовательская оценка сезона. |
episodes | массив | Все серии с полями, перечисленными в следующем разделе. |
Пример ответа
GET /. В сезоне 7 серий, поэтому episodes сокращен до одной записи, а массивы crew и guest_stars этой записи опущены:
{
"air_date": "2008-01-20",
"episodes": [
{
"air_date": "2008-01-20",
"episode_number": 1,
"episode_type": "standard",
"id": 62085,
"name": "Pilot",
"overview": "When an unassuming high school chemistry teacher discovers he has a rare form of lung cancer, he decides to...",
"production_code": "",
"runtime": 59,
"season_number": 1,
"show_id": 1396,
"still_path": "/ydlY3iPfeOAvu8gVqrxPoMvzNCn.jpg",
"vote_average": 0,
"vote_count": 0
}
],
"name": "Season 1",
"overview": "High school chemistry teacher Walter White's life is suddenly transformed by a dire medical diagnosis. Stre...",
"id": 3572,
"poster_path": "/91EIXdWxmp2mHNRsSuDW3WyDJLj.jpg",
"season_number": 1,
"vote_average": 0
}Каждая серия в ответе сезона также содержит массивы crew и guest_stars, форма записей описана в разделе актеры и съемочная группа. runtime может быть null для серии, которая еще не вышла.
Получение серии
GET / возвращает одну серию. Ответ сезона уже содержит каждую серию с crew и guest_stars, поэтому используйте этот эндпоинт, чтобы обновить одну запись, не перезагружая сезон. Он принимает language и append_to_response со значениями credits, external_ids, images, translations и videos. Запрос вида / стоит один запрос.
| Поле | Тип | Примечания |
|---|---|---|
id | целое число | Id серии. |
show_id | целое число | Id сериала. Есть в ответе сезона и в указателях сериала, но не в ответе для одной серии. |
season_number, episode_number | целое число | Позиция внутри сериала. Используйте их, чтобы построить путь запроса. |
name, overview | строка | Локализованный текст. |
air_date | строка или null | Только дата, без времени и часового пояса. Null, если серия не запланирована. |
episode_type | строка | standard для обычных серий. Чтобы распознать финал, сравните episode_number с episode_count этого сезона в записи сериала. |
runtime | целое число или null | Минуты. |
production_code | строка | Код студии, часто пуст. |
still_path | строка или null | Кадр серии. Берите w300 или original из https:/. |
vote_average, vote_count | число, целое число | Суммарная пользовательская оценка. |
crew, guest_stars | массив | Участники этой серии, см. актеры и съемочная группа. |
Следующая и последняя серии в записи сериала
Эндпоинт сериала возвращает next_episode_to_air и last_episode_to_air. Каждое из них это краткое описание серии с перечисленными выше полями, плюс show_id, но без crew и guest_stars. Следующая серия равна null для завершенных сериалов и для продолжающихся без подтвержденной даты. Пример читает South Park, продолжающийся сериал.
const headers = { Authorization: `Bearer ${process.env.AMODB_KEY}` };
const res = await fetch('https://api.amodb.dev/3/tv/2190', { headers });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const next = (await res.json()).next_episode_to_air;
console.log(next ? `Next: S${next.season_number}E${next.episode_number} on ${next.air_date}` : 'No upcoming episode');Для обратного отсчета сравнивайте air_date с местной датой зрителя. В значении нет времени суток, поэтому показывайте дату, а не время.
Подресурсы сезонов и серий
У путей сезонов и серий есть собственные подресурсы. Несколько из них сегодня возвращают пустые данные.
| Метод и путь | Что возвращает |
|---|---|
GET / | id, cast и crew сезона |
GET / | id и пустой массив posters |
GET / | id и пустой массив results |
GET / | id плюс tvdb_id, wikidata_id и другие id, все null |
GET / | id и пустой массив translations |
GET .../ | id, пустой cast, crew и guest_stars |
GET .../ | id и массив stills с кадром серии |
GET .../ | id и пустой массив results |
GET .../ | id плюс imdb_id, tvdb_id и другие id, все null |
GET .../ | id и массив translations с названием и описанием на каждом языке |
Участники сезонов и серий описаны в разделе актеры и съемочная группа, а кадры в разделе API изображений. amodb не предоставляет пути changes из TMDB и эндпоинт для серий одной группы эпизодов.
Ошибки
| HTTP | status_code | Когда |
|---|---|---|
| 401 | 7 | Ключ отсутствует или неверен. |
| 402 | 36 | Срок действия тарифа истек. |
| 404 | 34 | Сериала, сезона или серии не существует, например сезон 0 у сериала без спецвыпусков, либо путь не предоставляется. |
| 405 | 37 | Вы вызвали метод записи. |
| 429 | 25 | Превышено число запросов в минуту. Подождите число секунд из Retry-After. |
Полный формат тела ответа смотрите на странице ошибки, окна лимитов на странице лимиты запросов.
Практические заметки
- Сезоны и серии кэшируются на 6 часов. Пока сериал выходит, перечитывайте текущий сезон один-два раза в день.
- Сериалу из 10 сезонов нужно 10 вызовов сезонов. На тарифе с 20 запросами в минуту это половина лимита одной минуты, а повторный запуск в течение 6 часов обслуживается из кэша CDN.
- У невышедшей серии могут быть
air_dateравный null,runtimeравный null и пустойoverview. Показывайте заглушку, а не падайте с ошибкой. - Кадры это широкие изображения, а не постеры. В списках запрашивайте
w300, аoriginalтолько когда нужен просмотр в полном размере.