Сеансы в кинотеатрах
GET /3/movie/{movie_id}/showtimes?country=RU возвращает кинотеатры, где идет фильм в одной стране, с датированными сеансами в каждом. Без country вернутся только счетчики по странам в списке countries. Покрытие зависит от страны и фильма, а пустой массив results значит, что для этой пары данных нет.
Сеансы фильма
GET / возвращает кинотеатры, где идет фильм в одной стране, с датированными сеансами в каждом. Параметр country принимает двухбуквенный код в верхнем или нижнем регистре. Покрытие зависит от страны и фильма: данные есть там, где они известны, и отсутствуют там, где нет. Возвращаются только дни начиная с сегодняшнего.
Пример запрашивает Fight Club в России и обрабатывает пустой ответ.
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, ","))
}
}
}Параметры
movie_idпутьобязателенЧисловой id фильма, например550.countryqueryДвухбуквенный код страны, напримерRU. Без него вернется только сводка по странам.regionработает как псевдоним.api_keyqueryодно из двухВаш ключ. Используйте его или заголовокAuthorization: Bearer.
Поля ответа
| Поле | Тип | Примечания |
|---|---|---|
id | целое число | Id фильма. |
country | строка или null | Код в верхнем регистре, который вы запросили, или null, если country не передан или состоит не из двух букв. |
results | массив | Один объект на кинотеатр, упорядочены по кинотеатрам. Пуст, если данных нет или страна не передана. Всего не более 1500 сеансов. |
results[].id | целое число | Id кинотеатра. |
results[].name | строка | Название кинотеатра. |
results[].chain | объект | key это ключ сети, name это название сети или null. |
results[].city | строка или null | Город. |
results[].region | строка или null | Регион. |
results[].address | строка или null | Адрес. |
results[].postal_code | строка или null | Почтовый индекс. |
results[].country | строка | Код страны кинотеатра. |
results[].timezone | строка или null | Часовой пояс IANA, например Europe/Moscow. |
results[].latitude, results[].longitude | число или null | Координаты кинотеатра. |
results[].phone | строка или null | Номер телефона. |
results[].url | строка или null | Страница кинотеатра. |
results[].showtimes | массив | Сеансы в этом кинотеатре, упорядочены по началу. |
results[].showtimes[].date | строка | День в формате 2026-10-18. |
results[].showtimes[].start | строка | Начало по местному времени кинотеатра, например 2026-10-18T21:40, без смещения UTC. |
results[].showtimes[].end | строка или null | Окончание по местному времени кинотеатра. |
results[].showtimes[].auditorium | строка или null | Название зала. |
results[].showtimes[].formats | массив строк | Форматы, например 2D. |
results[].showtimes[].tags | массив строк | Дополнительные метки. Часто пусто. |
results[].showtimes[].audio, subtitles, language | строка или null | Сведения об аудио, субтитрах и языке, если они известны. |
results[].showtimes[].price | число или null | Цена билета. |
results[].showtimes[].currency | строка или null | Валюта price. |
results[].showtimes[].prices | любой тип или null | Подробности цен, если в кинотеатре их несколько. |
results[].showtimes[].booking_ | строка или null | Ссылка для бронирования места. |
results[].showtimes[].sold_ | логическое значение | true, если билеты на сеанс распроданы. |
countries | массив | Сводка по странам, см. ниже. |
Читайте нужные ключи по имени и пропускайте лишние ключи внутри объекта кинотеатра или сеанса. Сегодня многие поля равны null, потому что не каждый кинотеатр их передает.
Пример ответа
{
"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"
}
]
}Список сокращен до 1 кинотеатра из 2 и 2 сеансов из 4. Сеансы есть только на дни, которые еще не прошли, поэтому ответ меняется каждый день.
Сводка по странам
Не передавайте country, и в ответе будут только счетчики. results остается пустым, а country равен null. Массив countries содержит до 60 стран, где еще есть сеансы, первой идет страна с наибольшим числом сеансов. Используйте его, чтобы узнать, где фильм идет в кино, прежде чем запрашивать кинотеатры.
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"
}
]
}| Поле | Тип | Примечания |
|---|---|---|
countries[].country | строка | Двухбуквенный код, готовый для параметра country. |
countries[].name | строка | Название страны на английском. |
countries[].venues | целое число | Кинотеатры с сеансами. |
countries[].cities | целое число | Города с сеансами. |
countries[].showtimes | целое число | Сеансы начиная с сегодняшнего дня. |
countries[].first_day, countries[].last_day | строка | Первый и последний день с сеансом. |
Код страны без данных, например country=US для этого фильма, дает country равный US, пустой results и тот же список countries. Для названия без сеансов где-либо, например сериала 1396, получится "countries": [].
Добавление сеансов к запросу деталей
append_ добавляет тот же блок в ответ с деталями под ключом showtimes. Передайте код country в том же запросе. Блок сохраняет собственные ключи id, country, results и countries.
| Запрос | Результат |
|---|---|
/ | Запись фильма и блок showtimes для России |
/ | Добавляет актерский состав и съемочную группу в тот же вызов |
Это считается одним запросом, поэтому странице фильма с актерским составом и сеансами хватит одного вызова. Такой же эндпоинт есть для сериалов: GET /.
Сочетание с now_playing и region
Список now playing дает названия фильмов. Эндпоинт сеансов дает показы одного фильма. Объедините их в своем коде.
| Шаг | Запрос | Результат |
|---|---|---|
| 1 | GET / | До 20 фильмов на страницу, кэш на 30 минут |
| 2 | GET / для каждого id | Кинотеатры и время, где известно |
Цикл ниже делает одну-две повторные попытки при достижении лимита тарифа, ожидая число секунд из 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');
}Страница из 20 фильмов это 20 запросов сеансов. На тарифе с 20 запросами в минуту это все окно, поэтому кэшируйте результат у себя. Параметры списков описаны в разделе списки трендов.
Ошибки
Тело ошибки соответствует TMDB: success, status_code и status_message. Неверный ключ дает status_code 7.
| HTTP | status_code | Когда |
|---|---|---|
| 401 | 7 | Ключ отсутствует или неверен. |
| 402 | 36 | Срок действия тарифа истек. |
| 404 | 34 | Нет фильма с таким id. |
| 429 | 25 | Превышено число запросов в минуту. Подождите число секунд из Retry-After. |
Отсутствие сеансов не ошибка: ожидайте статус 200 и пустой массив results. Отсутствующий или неверный country тоже не ошибка. Подробнее: ошибки и лимиты запросов.
Практические заметки
- Покрытие зависит от страны и фильма. Считайте пустой массив
resultsпризнаком отсутствия данных, а не того, что фильм не идет. - Показывайте
startровно в том виде, как он пришел. Это местное время кинотеатра без смещения UTC, и именно по часам кинотеатра ориентируются посетители. - Сеансы кэшируются на CDN на 30 минут. Не запрашивайте их при каждом просмотре страницы и держите собственный кэш коротким.
- Используйте один список now playing для всех посетителей региона. Он тоже кэшируется на CDN на 30 минут.
- Через
booking_urlотправляйте посетителя на страницу бронирования кинотеатра. Он равенnull, если кинотеатр не дает ссылку. - Обзор сценария использования смотрите в API сеансов кинотеатров, а остальные данные о фильме в разделе фильмы.