Horarios de cine
GET /3/movie/{movie_id}/showtimes?country=RU devuelve los cines que proyectan una película en un país, con las sesiones fechadas de cada uno. Sin country solo devuelve recuentos por país en una lista countries. La cobertura varía según el país y el título, y un array results vacío significa que no hay datos para ese par.
Obtén los horarios de una película
GET / devuelve los cines que proyectan una película en un país, con las sesiones fechadas de cada uno. El parámetro country acepta un código de dos letras, en mayúsculas o minúsculas. La cobertura varía según el país y el título, así que los datos aparecen donde se conocen y faltan donde no. Solo se devuelven los días de hoy en adelante.
El ejemplo solicita Fight Club en Rusia y gestiona una respuesta vacía.
curl -sf "https://api.amodb.dev/3/movie/550/showtimes?country=RU" \
-H "Authorization: Bearer $AMODB_KEY"const url = 'https://api.amodb.dev/3/movie/550/showtimes?country=RU';
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` } });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const data = await res.json();
if (data.results.length === 0) console.log('no showtimes known');
for (const venue of data.results) {
for (const s of venue.showtimes) {
console.log(venue.name, venue.city, s.start, s.formats.join(','), s.booking_url);
}
}import os
import requests
r = requests.get(
"https://api.amodb.dev/3/movie/550/showtimes",
params={"country": "RU"},
headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
timeout=10,
)
r.raise_for_status()
results = r.json()["results"]
if not results:
print("no showtimes known")
for venue in results:
for s in venue["showtimes"]:
print(venue["name"], venue["city"], s["start"], ",".join(s["formats"]))<?php
$url = 'https://api.amodb.dev/3/movie/550/showtimes?country=RU';
$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");
}
$results = json_decode($body, true)['results'];
if (!$results) {
echo 'no showtimes known', PHP_EOL;
}
foreach ($results as $venue) {
foreach ($venue['showtimes'] as $s) {
echo $venue['name'], ' ', $s['start'], ' ', implode(',', $s['formats']), PHP_EOL;
}
}package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
"strings"
"time"
)
type Venue struct {
Name string `json:"name"`
City string `json:"city"`
Showtimes []struct {
Start string `json:"start"`
Formats []string `json:"formats"`
BookingURL string `json:"booking_url"`
} `json:"showtimes"`
}
func main() {
url := "https://api.amodb.dev/3/movie/550/showtimes?country=RU"
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 body struct {
Results []Venue `json:"results"`
}
if err := json.NewDecoder(res.Body).Decode(&body); err != nil {
panic(err)
}
if len(body.Results) == 0 {
fmt.Println("no showtimes known")
}
for _, v := range body.Results {
for _, s := range v.Showtimes {
fmt.Println(v.Name, v.City, s.Start, strings.Join(s.Formats, ","))
}
}
}Parámetros
movie_idrutaobligatorioID numérico de la película, por ejemplo550.countryconsultaCódigo de país de dos letras, comoRU. Sin él solo obtienes el resumen por país.regiones un alias.api_keyconsultauno de los dosTu clave. Usa esta o el encabezadoAuthorization: Bearer.
Campos de la respuesta
| Campo | Tipo | Notas |
|---|---|---|
id | entero | ID de la película. |
country | texto o null | El código en mayúsculas que pediste, o null cuando falta country o no tiene dos letras. |
results | array | Un objeto por cine, ordenado por cine. Vacío cuando no se sabe nada o no se envió ningún país. Como máximo 1500 sesiones en total. |
results[].id | entero | ID del cine. |
results[].name | texto | Nombre del cine. |
results[].chain | objeto | key es la clave de la cadena y name es el nombre de la cadena o null. |
results[].city | texto o null | Ciudad. |
results[].region | texto o null | Región. |
results[].address | texto o null | Dirección postal. |
results[].postal_code | texto o null | Código postal. |
results[].country | texto | Código de país del cine. |
results[].timezone | texto o null | Zona horaria IANA, como Europe/Moscow. |
results[].latitude, results[].longitude | número o null | Posición del cine. |
results[].phone | texto o null | Número de teléfono. |
results[].url | texto o null | Página del cine. |
results[].showtimes | array | Sesiones de ese cine, ordenadas por hora de inicio. |
results[].showtimes[].date | texto | Día con el formato 2026-10-18. |
results[].showtimes[].start | texto | Inicio en la hora local del cine, como 2026-10-18T21:40, sin desfase UTC. |
results[].showtimes[].end | texto o null | Fin en la hora local del cine. |
results[].showtimes[].auditorium | texto o null | Nombre de la sala. |
results[].showtimes[].formats | array de textos | Formatos como 2D. |
results[].showtimes[].tags | array de textos | Etiquetas adicionales. A menudo vacío. |
results[].showtimes[].audio, subtitles, language | texto o null | Datos de audio, subtítulos e idioma cuando se conocen. |
results[].showtimes[].price | número o null | Precio de la entrada. |
results[].showtimes[].currency | texto o null | Moneda de price. |
results[].showtimes[].prices | cualquiera o null | Detalle de precios cuando un cine tiene varios. |
results[].showtimes[].booking_ | texto o null | Enlace para reservar la butaca. |
results[].showtimes[].sold_ | booleano | true cuando la sesión está agotada. |
countries | array | Resumen por país, ver más abajo. |
Lee por nombre las claves que uses e ignora las claves adicionales dentro de un objeto de cine o de sesión. Hoy muchos campos son null porque no todos los cines los envían.
Ejemplo de respuesta
{
"id": 550,
"country": "RU",
"results": [
{
"id": 1114,
"name": "Мираж Синема НА БОЛЬШОМ",
"chain": {
"key": "mirage-ru",
"name": "Мираж Синема"
},
"city": "Санкт-Петербург",
"region": null,
"address": "Большой пр. П.С., д. 35А",
"postal_code": null,
"country": "RU",
"timezone": "Europe/Moscow",
"latitude": null,
"longitude": null,
"phone": null,
"url": "https://www.mirage.ru/spb/cinema/1/",
"showtimes": [
{
"date": "2026-10-18",
"start": "2026-10-18T21:40",
"end": null,
"auditorium": null,
"formats": ["2D"],
"tags": [],
"audio": null,
"subtitles": null,
"language": null,
"price": null,
"currency": null,
"prices": null,
"booking_url": "https://www.mirage.ru/ticket_new/aca7b114-d587-4fc5-9df6-28568e8fa9b3/",
"sold_out": false
},
{
"date": "2026-10-19",
"start": "2026-10-19T22:20",
"end": null,
"auditorium": "Зал №4",
"formats": ["2D"],
"tags": [],
"audio": null,
"subtitles": null,
"language": null,
"price": null,
"currency": null,
"prices": null,
"booking_url": "https://www.mirage.ru/ticket_new/0c32e190-890a-4c81-a754-3300fefc4d5e/",
"sold_out": false
}
]
}
],
"countries": [
{
"country": "RU",
"name": "Russia",
"venues": 2,
"cities": 1,
"showtimes": 7,
"first_day": "2026-10-18",
"last_day": "2026-10-21"
}
]
}La lista se recortó a 1 de 2 cines y 2 de 4 sesiones. Solo existen sesiones de los días que aún no han pasado, así que esta respuesta cambia cada día.
Obtén el resumen por país
Omite country y la respuesta solo contiene recuentos. results queda vacío y country es null. El array countries lista hasta 60 países que aún tienen alguna sesión, con el que tiene más sesiones primero. Úsalo para saber dónde está en cartelera un título antes de pedir los cines.
curl -sf "https://api.amodb.dev/3/movie/550/showtimes" \
-H "Authorization: Bearer $AMODB_KEY"{
"id": 550,
"country": null,
"results": [],
"countries": [
{
"country": "RU",
"name": "Russia",
"venues": 2,
"cities": 1,
"showtimes": 7,
"first_day": "2026-10-18",
"last_day": "2026-10-21"
}
]
}| Campo | Tipo | Notas |
|---|---|---|
countries[].country | texto | Código de dos letras, listo para usar como parámetro country. |
countries[].name | texto | Nombre del país en inglés. |
countries[].venues | entero | Cines con alguna sesión. |
countries[].cities | entero | Ciudades con alguna sesión. |
countries[].showtimes | entero | Sesiones de hoy en adelante. |
countries[].first_day, countries[].last_day | texto | Primer y último día con alguna sesión. |
Un código de país sin datos, como country=US para esta película, responde con country igual a US, un results vacío y la misma lista countries. Un título sin sesiones en ningún lugar, como la serie 1396, tiene "countries": [].
Añade los horarios a una llamada de detalles
append_ incorpora el mismo bloque en una respuesta de detalles bajo la clave showtimes. Envía el código country en la misma solicitud. El bloque conserva sus propias claves id, country, results y countries.
| Solicitud | Resultado |
|---|---|
/ | Registro de la película más un bloque showtimes para Rusia |
/ | Añade los créditos a la misma llamada |
Cuenta como una sola solicitud, así que una página de película que muestra reparto y sesiones necesita una única llamada. El mismo endpoint existe para series como GET /.
Combina now_playing con region
La lista de películas en cartelera te da los títulos. El endpoint de horarios te da las sesiones de un título. Únelos en tu código.
| Paso | Solicitud | Resultado |
|---|---|---|
| 1 | GET / | Hasta 20 películas por página, en caché 30 minutos |
| 2 | GET / para cada id | Cines y horas, donde se conocen |
El bucle siguiente reintenta una o dos veces cuando se alcanza el límite del plan y espera el número de segundos indicado en Retry-After.
const base = 'https://api.amodb.dev/3';
const headers = { Authorization: `Bearer ${process.env.AMODB_KEY}` };
async function get(path, retries = 2) {
const res = await fetch(base + path, { headers });
if (res.status === 429 && retries > 0) {
const wait = Number(res.headers.get('Retry-After') ?? 60);
await new Promise((resolve) => setTimeout(resolve, wait * 1000));
return get(path, retries - 1);
}
if (!res.ok) throw new Error(`amodb returned ${res.status} for ${path}`);
return res.json();
}
const playing = await get('/movie/now_playing?region=RU&page=1');
for (const movie of playing.results) {
const data = await get(`/movie/${movie.id}/showtimes?country=RU`);
if (data.results.length > 0) console.log(movie.title, data.results.length, 'venues');
}Una página de 20 títulos son 20 solicitudes de horarios. En el plan de 20 solicitudes por minuto eso consume toda la ventana, así que guarda el resultado en tu propia caché. Consulta tendencias y listas para ver los parámetros de las listas.
Errores
El cuerpo del error sigue el formato de TMDB: success, status_code y status_message. Una clave incorrecta muestra status_code 7.
| HTTP | status_code | Cuándo |
|---|---|---|
| 401 | 7 | Falta la clave o es incorrecta. |
| 402 | 36 | El periodo del plan ha terminado. |
| 404 | 34 | No hay ninguna película con ese id. |
| 429 | 25 | Superaste tus solicitudes por minuto. Espera los segundos indicados en Retry-After. |
No tener sesiones no es un error: espera el estado 200 y un array results vacío. Un country ausente o no válido tampoco es un error. Consulta errores y límites de solicitudes.
Notas prácticas
- La cobertura varía según el país y el título. Trata un array
resultsvacío como desconocido, no como que la película no se proyecta. - Muestra
startexactamente como llega. Es la hora local del cine, sin desfase UTC, y la hora del propio cine es la que esperan los visitantes. - Las sesiones se guardan en la caché perimetral 30 minutos. No las solicites en cada visita a la página y mantén tu propia caché corta.
- Reutiliza una sola lista de películas en cartelera para todos los visitantes de una región. También se guarda 30 minutos en la caché perimetral.
- Usa
booking_urlpara enviar al visitante a la página de reservas del cine. Esnullcuando el cine no da ningún enlace. - Para ver el caso de uso completo, consulta la API de horarios de cine, y para el resto de datos de una película, consulta películas.