API de temporadas y episodios de TV
Lee una temporada con todos sus episodios en GET /3/tv/{series_id}/season/{season_number}, o un solo episodio un nivel más abajo. El JSON coincide con TMDB v3 con air_date, episode_number, runtime y still_path. Cada episodio trae crew y guest_stars, la temporada 0 reúne los especiales, y append_to_response añade credits, images y videos.
Obtén una temporada
GET / devuelve una temporada y su array episodes completo en una sola respuesta. Los números de temporada empiezan en 1, y 0 se reserva para los especiales. Toma el id de la serie y los números de temporada del registro de series de TV.
El ejemplo lee la temporada 1 de Breaking Bad. El código imprime una línea por episodio.
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_idrutaobligatorioID numérico de la serie de TV, por ejemplo1396.season_numberrutaobligatorioNúmero entero de temporada.0devuelve los especiales.api_keyconsultauno de los dosTu clave. Usa esta o el encabezadoAuthorization: Bearer.languageconsultaEtiqueta TMDB comoen-USofr-FR. Se sirven 14 idiomas base. Por defectoen-US.append_to_responseconsultaValores a nivel de temporada:credits,external_ids,images,videos. Los demás nombres se ignoran.
Campos de la respuesta
| Campo | Tipo | Notas |
|---|---|---|
id, season_number | entero | ID de la temporada y su número dentro de la serie. |
name, overview | texto | Texto localizado, vacío cuando no existe traducción. |
air_date | texto o null | Fecha del primer episodio, YYYY-MM-DD. |
poster_path | texto o null | Se añade a https:/. |
vote_average | número | Puntuación agregada de los usuarios para la temporada. |
episodes | array | Todos los episodios, con los campos de la sección siguiente. |
Ejemplo de respuesta
GET /. La temporada tiene 7 episodios, así que episodes se recortó a una entrada, y los arrays crew y guest_stars de esa entrada se omitieron:
{
"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
}Cada episodio de la respuesta de temporada también trae arrays crew y guest_stars, con la estructura de entrada descrita en créditos. runtime puede ser null en un episodio que aún no se ha emitido.
Obtén un episodio
GET / devuelve un episodio. La respuesta de temporada ya contiene todos los episodios con crew y guest_stars, así que usa este endpoint para actualizar un registro sin volver a cargar la temporada. Acepta language y append_to_response con credits, external_ids, images, translations y videos. Una solicitud como / cuesta una sola solicitud.
| Campo | Tipo | Notas |
|---|---|---|
id | entero | ID del episodio. |
show_id | entero | ID de la serie. Aparece en la respuesta de temporada y en los punteros de la serie, no en la respuesta de un solo episodio. |
season_number, episode_number | entero | Posición dentro de la serie. Úsalos para construir la ruta de la solicitud. |
name, overview | texto | Texto localizado. |
air_date | texto o null | Solo fecha, sin hora ni zona horaria. Null cuando no está programado. |
episode_type | texto | standard para episodios normales. Para detectar un final, compara episode_number con el episode_count de esa temporada en el registro de la serie. |
runtime | entero o null | Minutos. |
production_code | texto | Código del estudio, a menudo vacío. |
still_path | texto o null | Fotograma del episodio. Usa w300 u original de https:/. |
vote_average, vote_count | número, entero | Puntuación agregada de los usuarios. |
crew, guest_stars | array | Créditos de este episodio, ver créditos. |
Próximo y último episodio en el registro de la serie
El endpoint de series devuelve next_episode_to_air y last_episode_to_air. Cada uno es un resumen de episodio con los campos de arriba, más show_id y sin crew ni guest_stars. El próximo es null en las series terminadas y en las series en curso sin fecha confirmada. El ejemplo lee South Park, una serie en curso.
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 una cuenta atrás, compara air_date con la fecha local del espectador. El valor no lleva hora del día, así que muestra una fecha y no una hora.
Subrecursos de temporada y episodio
Las rutas de temporada y episodio tienen sus propios subrecursos. Varios de ellos devuelven hoy datos vacíos.
| Método y ruta | Devuelve |
|---|---|
GET / | id, cast y crew de la temporada |
GET / | id y un array posters vacío |
GET / | id y un array results vacío |
GET / | id más tvdb_id, wikidata_id y otros ids, todos null |
GET / | id y un array translations vacío |
GET .../ | id, un cast vacío, crew y guest_stars |
GET .../ | id y un array stills con el fotograma del episodio |
GET .../ | id y un array results vacío |
GET .../ | id más imdb_id, tvdb_id y otros ids, todos null |
GET .../ | id y un array translations con nombre y sinopsis por idioma |
Los créditos de temporada y episodio se explican en créditos, y los fotogramas en imágenes. amodb no ofrece las rutas changes de TMDB ni un endpoint para los episodios de un grupo de episodios.
Errores
| HTTP | status_code | Cuándo |
|---|---|---|
| 401 | 7 | Falta la clave o es incorrecta. |
| 402 | 36 | El periodo del plan ha terminado. |
| 404 | 34 | La serie, la temporada o el episodio no existe, por ejemplo la temporada 0 en una serie sin especiales, o la ruta no se ofrece. |
| 405 | 37 | Llamaste a un método de escritura. |
| 429 | 25 | Superaste tus solicitudes por minuto. Espera los segundos indicados en Retry-After. |
Consulta errores para ver el formato completo del cuerpo y límites de solicitudes para las ventanas.
Notas prácticas
- Las temporadas y los episodios se guardan en caché 6 horas. Vuelve a leer la temporada actual una o dos veces al día mientras se emite la serie.
- Una serie de 10 temporadas necesita 10 llamadas de temporada. En el plan de 20 solicitudes por minuto eso usa la mitad del cupo de un minuto, y una repetición dentro de las 6 horas se responde desde la caché perimetral.
- Un episodio sin emitir puede tener
air_datenull,runtimenull yoverviewvacío. Muestra un marcador de posición en lugar de fallar. - Los fotogramas son tomas panorámicas, no pósteres. Pide
w300en las listas yoriginalsolo cuando necesites una vista a tamaño completo.