API de temporadas e episódios de séries

Leia uma temporada com todos os episódios em GET /3/tv/{series_id}/season/{season_number}, ou um único episódio um nível abaixo. O JSON segue o TMDB v3, com air_date, episode_number, runtime e still_path. Cada episódio traz crew e guest_stars, a temporada 0 guarda os especiais, e append_to_response acrescenta credits, images e videos.

Atualizado em Ver em Markdown

Obter uma temporada

GET /3/tv/{series_id}/season/{season_number} retorna uma temporada e o array episodes completo em uma só resposta. Os números de temporada começam em 1, e 0 é reservado aos especiais. Pegue o id da série e os números das temporadas no registro de séries de TV.

O exemplo lê a temporada 1 de Breaking Bad. O código imprime uma linha por episódio.

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)
	}
}

Parâmetros

  • series_idcaminhoobrigatório
    Id numérico da série, por exemplo 1396.
  • season_numbercaminhoobrigatório
    Número inteiro da temporada. 0 retorna os especiais.
  • api_keyconsultaum dos dois
    Sua chave. Use este parâmetro ou o header Authorization: Bearer.
  • languageconsulta
    Tag do TMDB como en-US ou fr-FR. 14 idiomas base são atendidos. Padrão en-US.
  • append_to_responseconsulta
    Valores no nível da temporada: credits, external_ids, images, videos. Outros nomes são ignorados.

Campos da resposta

CampoTipoObservações
id, season_numberinteiroId da temporada e o número dela dentro da série.
name, overviewstringTexto localizado, vazio quando não existe tradução.
air_datestring ou nullData do primeiro episódio, YYYY-MM-DD.
poster_pathstring ou nullAcrescente a https://img.amodb.dev/t/p/{size}.
vote_averagenúmeroNota agregada dos usuários para a temporada.
episodesarrayTodos os episódios, com os campos listados na próxima seção.

Exemplo de resposta

GET /3/tv/1396/season/1?language=en-US. A temporada tem 7 episódios, então episodes foi cortado para uma entrada, e os arrays crew e guest_stars dessa entrada ficaram de fora:

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
}

Todo episódio na resposta da temporada também traz os arrays crew e guest_stars, com o formato de entrada descrito em créditos. runtime pode ser null em um episódio ainda não exibido.

Obter um episódio

GET /3/tv/{series_id}/season/{season_number}/episode/{episode_number} retorna um episódio. A resposta da temporada já traz todos os episódios com crew e guest_stars, então use este endpoint para atualizar um registro sem recarregar a temporada. Ele aceita language e append_to_response com credits, external_ids, images, translations e videos. Uma requisição como /3/tv/1396/season/1/episode/1?append_to_response=credits custa uma requisição.

CampoTipoObservações
idinteiroId do episódio.
show_idinteiroId da série. Presente na resposta da temporada e nos ponteiros da série, mas não na resposta de um único episódio.
season_number, episode_numberinteiroPosição dentro da série. Use-os para montar o caminho da requisição.
name, overviewstringTexto localizado.
air_datestring ou nullSó a data, sem hora nem fuso horário. Null quando não há agenda.
episode_typestringstandard para episódios comuns. Para identificar um final, compare episode_number com o episode_count dessa temporada no registro da série.
runtimeinteiro ou nullMinutos.
production_codestringCódigo do estúdio, muitas vezes vazio.
still_pathstring ou nullStill do episódio. Use w300 ou original de https://img.amodb.dev/t/p/{size}.
vote_average, vote_countnúmero, inteiroNota agregada dos usuários.
crew, guest_starsarrayCréditos deste episódio, veja créditos.

Próximo e último episódio no registro da série

O endpoint da série retorna next_episode_to_air e last_episode_to_air. Cada um é um resumo de episódio com os campos acima, mais show_id e sem crew e guest_stars. O próximo é null para séries encerradas e para séries em andamento sem data confirmada. O exemplo lê South Park, uma série em andamento.

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');

Para uma contagem regressiva, compare air_date com a data local do espectador. O valor não traz hora do dia, então mostre uma data e não um horário.

Subrecursos de temporada e de episódio

Os caminhos de temporada e de episódio têm seus próprios subrecursos. Vários deles retornam dados vazios hoje.

Método e caminhoRetorna
GET /tv/{series_id}/season/{season_number}/creditsid, cast e crew da temporada
GET /tv/{series_id}/season/{season_number}/imagesid e um array posters vazio
GET /tv/{series_id}/season/{season_number}/videosid e um array results vazio
GET /tv/{series_id}/season/{season_number}/external_idsid mais tvdb_id, wikidata_id e outros ids, todos null
GET /tv/{series_id}/season/{season_number}/translationsid e um array translations vazio
GET .../episode/{episode_number}/creditsid, um cast vazio, crew e guest_stars
GET .../episode/{episode_number}/imagesid e um array stills com o still do episódio
GET .../episode/{episode_number}/videosid e um array results vazio
GET .../episode/{episode_number}/external_idsid mais imdb_id, tvdb_id e outros ids, todos null
GET .../episode/{episode_number}/translationsid e um array translations com nome e sinopse por idioma

Os créditos de temporada e de episódio estão em créditos, e os stills em imagens. O amodb não oferece os caminhos changes do TMDB nem um endpoint para os episódios de um grupo de episódios.

Erros

HTTPstatus_codeQuando
4017A chave está ausente ou incorreta.
40236O período do plano terminou.
40434A série, a temporada ou o episódio não existe, por exemplo a temporada 0 em uma série sem especiais, ou o caminho não é oferecido.
40537Você chamou um método de escrita.
42925Você passou do seu limite de requisições por minuto. Espere os segundos indicados em Retry-After.

Veja erros para o formato completo do corpo e limites de requisições para as janelas.

Notas práticas

  • Temporadas e episódios têm cache de 6 horas. Releia a temporada atual uma ou duas vezes por dia enquanto a série está no ar.
  • Uma série de 10 temporadas precisa de 10 chamadas de temporada. No plano de 20 requisições por minuto isso usa metade da cota de um minuto, e uma nova execução dentro de 6 horas é atendida pelo cache de borda.
  • Um episódio ainda não exibido pode ter air_date null, runtime null e overview vazio. Renderize um espaço reservado em vez de falhar.
  • Stills são quadros largos, não pôsteres. Peça w300 nas listas e original só quando precisar da visualização em tamanho total.