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.

Обновлено Открыть в Markdown

Получение сезона

GET /3/tv/{series_id}/season/{season_number} возвращает один сезон и полный массив episodes в одном ответе. Номера сезонов начинаются с 1, а 0 зарезервирован для спецвыпусков. Id сериала и номера сезонов берите из записи сериала.

Пример читает сезон 1 сериала Breaking Bad. Код выводит по одной строке на серию.

bashjspyphpgo
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://img.amodb.dev/t/p/{size}.
vote_averageчислоСуммарная пользовательская оценка сезона.
episodesмассивВсе серии с полями, перечисленными в следующем разделе.

Пример ответа

GET /3/tv/1396/season/1?language=en-US. В сезоне 7 серий, поэтому episodes сокращен до одной записи, а массивы crew и guest_stars этой записи опущены:

JSON
{
  "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 /3/tv/{series_id}/season/{season_number}/episode/{episode_number} возвращает одну серию. Ответ сезона уже содержит каждую серию с crew и guest_stars, поэтому используйте этот эндпоинт, чтобы обновить одну запись, не перезагружая сезон. Он принимает language и append_to_response со значениями credits, external_ids, images, translations и videos. Запрос вида /3/tv/1396/season/1/episode/1?append_to_response=credits стоит один запрос.

ПолеТипПримечания
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://img.amodb.dev/t/p/{size}.
vote_average, vote_countчисло, целое числоСуммарная пользовательская оценка.
crew, guest_starsмассивУчастники этой серии, см. актеры и съемочная группа.

Следующая и последняя серии в записи сериала

Эндпоинт сериала возвращает next_episode_to_air и last_episode_to_air. Каждое из них это краткое описание серии с перечисленными выше полями, плюс show_id, но без crew и guest_stars. Следующая серия равна null для завершенных сериалов и для продолжающихся без подтвержденной даты. Пример читает South Park, продолжающийся сериал.

JavaScript
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 /tv/{series_id}/season/{season_number}/creditsid, cast и crew сезона
GET /tv/{series_id}/season/{season_number}/imagesid и пустой массив posters
GET /tv/{series_id}/season/{season_number}/videosid и пустой массив results
GET /tv/{series_id}/season/{season_number}/external_idsid плюс tvdb_id, wikidata_id и другие id, все null
GET /tv/{series_id}/season/{season_number}/translationsid и пустой массив translations
GET .../episode/{episode_number}/creditsid, пустой cast, crew и guest_stars
GET .../episode/{episode_number}/imagesid и массив stills с кадром серии
GET .../episode/{episode_number}/videosid и пустой массив results
GET .../episode/{episode_number}/external_idsid плюс imdb_id, tvdb_id и другие id, все null
GET .../episode/{episode_number}/translationsid и массив translations с названием и описанием на каждом языке

Участники сезонов и серий описаны в разделе актеры и съемочная группа, а кадры в разделе API изображений. amodb не предоставляет пути changes из TMDB и эндпоинт для серий одной группы эпизодов.

Ошибки

HTTPstatus_codeКогда
4017Ключ отсутствует или неверен.
40236Срок действия тарифа истек.
40434Сериала, сезона или серии не существует, например сезон 0 у сериала без спецвыпусков, либо путь не предоставляется.
40537Вы вызвали метод записи.
42925Превышено число запросов в минуту. Подождите число секунд из Retry-After.

Полный формат тела ответа смотрите на странице ошибки, окна лимитов на странице лимиты запросов.

Практические заметки

  • Сезоны и серии кэшируются на 6 часов. Пока сериал выходит, перечитывайте текущий сезон один-два раза в день.
  • Сериалу из 10 сезонов нужно 10 вызовов сезонов. На тарифе с 20 запросами в минуту это половина лимита одной минуты, а повторный запуск в течение 6 часов обслуживается из кэша CDN.
  • У невышедшей серии могут быть air_date равный null, runtime равный null и пустой overview. Показывайте заглушку, а не падайте с ошибкой.
  • Кадры это широкие изображения, а не постеры. В списках запрашивайте w300, а original только когда нужен просмотр в полном размере.