# 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.

## Endpoint

`GET /3/movie/{movie_id}/showtimes`

```bash
curl "https://api.amodb.dev/3/movie/550/showtimes?country=RU" \
  -H "Authorization: Bearer $AMODB_KEY"
```

Respuesta:

```json
{
  "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-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
        },
        {
          "date": "2026-10-20",
          "start": "2026-10-20T21: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/7f18e423-4a40-40f3-b68f-8664f4e3fa75/",
          "sold_out": false
        },
        {
          "date": "2026-10-21",
          "start": "2026-10-21T21: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/5ad6b82b-82b3-4ea6-9e65-79388d71b230/",
          "sold_out": false
        }
      ]
    },
    {
      "id": 1115,
      "name": "Мираж Синема ПИК",
      "chain": {
        "key": "mirage-ru",
        "name": "Мираж Синема"
      },
      "city": "Санкт-Петербург",
      "region": null,
      "address": "ул. Ефимова, д.2",
      "postal_code": null,
      "country": "RU",
      "timezone": "Europe/Moscow",
      "latitude": null,
      "longitude": null,
      "phone": null,
      "url": "https://www.mirage.ru/spb/cinema/27/",
      "showtimes": [
        {
          "date": "2026-10-19",
          "start": "2026-10-19T20:10",
          "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/1d143ca6-1bbe-48ee-954a-063b6088a32a/",
          "sold_out": false
        },
        {
          "date": "2026-10-20",
          "start": "2026-10-20T20:10",
          "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/8b2e0f6a-5b62-41eb-a398-1b709539f03d/",
          "sold_out": false
        },
        {
          "date": "2026-10-21",
          "start": "2026-10-21T20:10",
          "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/3723875b-a7df-426f-968a-4bdaa1a8bdd7/",
          "sold_out": false
        }
      ]
    }
  ],
  "countries": [
    {
      "country": "RU",
      "name": "Russia",
      "venues": 2,
      "cities": 1,
      "showtimes": 6,
      "first_day": "2026-10-19",
      "last_day": "2026-10-21"
    }
  ]
}
```

## Obtén los horarios de una película

`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. 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.

```bash
curl -sf "https://api.amodb.dev/3/movie/550/showtimes?country=RU" \
  -H "Authorization: Bearer $AMODB_KEY"
```

```js
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);
  }
}
```

```python
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
<?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;
    }
}
```

```go
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

| Parámetro  | En       | Obligatorio    | Descripción                                                                                              |
| ---------- | -------- | -------------- | -------------------------------------------------------------------------------------------------------- |
| `movie_id` | ruta     | sí             | ID numérico de la película, por ejemplo `550`.                                                           |
| `country`  | consulta | no             | Código de país de dos letras, como `RU`. Sin él solo obtienes el resumen por país. `region` es un alias. |
| `api_key`  | consulta | uno de los dos | Tu clave. Usa esta o el encabezado `Authorization: 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_url`                    | texto o null      | Enlace para reservar la butaca.                                                                                                    |
| `results[].showtimes[].sold_out`                       | 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

```json
{
  "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.

```bash
curl -sf "https://api.amodb.dev/3/movie/550/showtimes" \
  -H "Authorization: Bearer $AMODB_KEY"
```

```json
{
  "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_to_response=showtimes` 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                                                    |
| -------------------------------------------------------------- | ------------------------------------------------------------ |
| `/3/movie/550?append_to_response=showtimes&country=RU`         | Registro de la película más un bloque `showtimes` para Rusia |
| `/3/movie/550?append_to_response=credits,showtimes&country=RU` | 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 /3/tv/{tv_id}/showtimes`.

## 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 /3/movie/now_playing?region=RU&page=1`           | Hasta 20 películas por página, en caché 30 minutos |
| 2    | `GET /3/movie/{id}/showtimes?country=RU` 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`.

```js
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](https://amodb.dev/es/trending-lists/) 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](https://amodb.dev/es/errors/) y [límites de solicitudes](https://amodb.dev/es/rate-limits/).

## Notas prácticas

- La cobertura varía según el país y el título. Trata un array `results` vacío como desconocido, no como que la película no se proyecta.
- Muestra `start` exactamente 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_url` para enviar al visitante a la página de reservas del cine. Es `null` cuando el cine no da ningún enlace.
- Para ver el caso de uso completo, consulta la [API de horarios de cine](https://amodb.dev/es/cinema-showtimes-api/), y para el resto de datos de una película, consulta [películas](https://amodb.dev/es/movies/).

## Preguntas y respuestas

### ¿El parámetro country es obligatorio?

No, pero lo necesitas para obtener los cines. Envía un código de dos letras como RU o DE. Sin country, o con un código que no tenga dos letras, results llega vacío y la lista countries indica dónde hay sesiones. El parámetro region funciona como alias.

### ¿Qué significa un array results vacío?

Significa que no se conocen sesiones de ese título en ese país desde hoy en adelante. No prueba que la película no esté en cartelera. La lista countries sigue mostrando otros países con datos. Ofrece en su lugar la fecha de estreno de los detalles de la película.

### ¿Cómo encuentro las películas que están ahora en cines?

Llama a GET /3/movie/now_playing con el parámetro region y luego solicita las sesiones de los ids que te interesen. La lista se guarda en caché 30 minutos, así que puedes reutilizarla para todos los visitantes.

### ¿Las horas están en la zona horaria de mi visitante?

No. El valor start es la hora local del cine y no lleva desfase UTC. Cada cine también tiene un timezone como Europe/Moscow. Muestra start tal como llega y no lo conviertas con la zona horaria del visitante.

## Páginas relacionadas

- [API de horarios de cine](https://amodb.dev/es/cinema-showtimes-api/): API de horarios de cine: GET /3/movie/{movie_id}/showtimes con un código de país devuelve cines, horas y formatos cuando se conocen. Úsala con now_playing.
- [Endpoints de tendencias y listas](https://amodb.dev/es/trending-lists/): API de películas en tendencia con rutas TMDB v3: rankings diarios y semanales, más cartelera, populares, mejor valoradas y estrenos. Caché de 30 minutos.
- [API de detalles de película](https://amodb.dev/es/movies/): API de detalles de película con rutas y JSON de TMDB v3. Obtén una película por id y añade créditos, puntuaciones y moods con append_to_response, en 14 idiomas.
- [Puntuaciones de películas y series](https://amodb.dev/es/ratings/): API de puntuaciones de películas: IMDb, Kinopoisk, Metacritic, Rotten Tomatoes y TMDB de un título en una sola llamada, con null si falta una fuente.
- [Límites de solicitudes](https://amodb.dev/es/rate-limits/): amodb limita cada clave por solicitudes por minuto en una ventana deslizante de 60 segundos: 20, 40 o 120 según el plan. Lee los encabezados y gestiona el 429.
- [Inicio rápido](https://amodb.dev/es/quickstart/): Haz tu primera llamada a amodb: consigue una clave, pide los detalles de una película en curl, JavaScript, Python, PHP o Go y carga el póster. En 2 minutos.

Actualizado: 2026-10-18. Source: https://amodb.dev/es/showtimes/
