Horários de sessões de cinema

GET /3/movie/{movie_id}/showtimes?country=RU retorna os locais que exibem um filme em um país, com as sessões datadas de cada um. Sem country, retorna só as contagens por país em uma lista countries. A cobertura varia por país e título, e um array results vazio significa que nada é conhecido para esse par.

Atualizado em Ver em Markdown

Obter os horários de sessões de um filme

GET /3/movie/{movie_id}/showtimes?country=RU retorna os locais de exibição que mostram um filme em um país, com as sessões datadas de cada um. O parâmetro country recebe um código de duas letras, em maiúsculas ou minúsculas. A cobertura varia por país e título, então o dado aparece onde é conhecido e falta onde não é. Só voltam os dias a partir de hoje.

O exemplo pede Fight Club na Rússia e trata uma resposta vazia.

bashjspyphpgo
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_idcaminhoobrigatório
    Id numérico do filme, por exemplo 550.
  • countryconsulta
    Código de país de duas letras, como RU. Sem ele, você recebe só o resumo por país. region é um alias.
  • api_keyconsultaum dos dois
    Sua chave. Use este parâmetro ou o header Authorization: Bearer.

Campos da resposta

CampoTipoObservações
idinteiroId do filme.
countrystring ou nullO código em maiúsculas que você pediu, ou null quando country falta ou não tem duas letras.
resultsarrayUm objeto por local de exibição, ordenado por local. Vazio quando nada é conhecido ou nenhum país foi enviado. No máximo 1500 sessões no total.
results[].idinteiroId do local de exibição.
results[].namestringNome do local de exibição.
results[].chainobjetokey é a chave da rede, name é o nome da rede ou null.
results[].citystring ou nullCidade.
results[].regionstring ou nullRegião.
results[].addressstring ou nullEndereço.
results[].postal_codestring ou nullCódigo postal.
results[].countrystringCódigo de país do local de exibição.
results[].timezonestring ou nullFuso horário IANA, como Europe/Moscow.
results[].latitude, results[].longitudenúmero ou nullPosição do local de exibição.
results[].phonestring ou nullNúmero de telefone.
results[].urlstring ou nullPágina do local de exibição.
results[].showtimesarraySessões desse local, ordenadas pelo início.
results[].showtimes[].datestringDia no formato 2026-10-18.
results[].showtimes[].startstringInício na hora local do cinema, como 2026-10-18T21:40, sem deslocamento UTC.
results[].showtimes[].endstring ou nullFim na hora local do cinema.
results[].showtimes[].auditoriumstring ou nullNome da sala.
results[].showtimes[].formatsarray de stringsFormatos, como 2D.
results[].showtimes[].tagsarray de stringsRótulos extras. Muitas vezes vazio.
results[].showtimes[].audio, subtitles, languagestring ou nullDetalhes de áudio, legenda e idioma, quando conhecidos.
results[].showtimes[].pricenúmero ou nullPreço do ingresso.
results[].showtimes[].currencystring ou nullMoeda de price.
results[].showtimes[].pricesqualquer tipo ou nullDetalhes de preço quando um local tem vários.
results[].showtimes[].booking_urlstring ou nullLink para reservar o lugar.
results[].showtimes[].sold_outbooleanotrue quando a sessão está esgotada.
countriesarrayResumo por país, veja abaixo.

Leia pelo nome as chaves que você usa e ignore chaves extras dentro de um objeto de local ou de sessão. Hoje muitos campos são null, porque nem todo local os envia.

Exemplo de resposta

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"
    }
  ]
}

A lista foi cortada para 1 de 2 locais e 2 de 4 sessões. As sessões só existem para dias que ainda não passaram, então essa resposta muda todo dia.

Obter o resumo por país

Omita country e a resposta traz só contagens. results continua vazio e country é null. O array countries lista até 60 países que ainda têm uma sessão, com o de mais sessões primeiro. Use-o para saber onde um título está em cartaz antes de pedir os locais de exibição.

curl
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"
    }
  ]
}
CampoTipoObservações
countries[].countrystringCódigo de duas letras, pronto para usar como parâmetro country.
countries[].namestringNome do país em inglês.
countries[].venuesinteiroLocais de exibição com uma sessão.
countries[].citiesinteiroCidades com uma sessão.
countries[].showtimesinteiroSessões a partir de hoje.
countries[].first_day, countries[].last_daystringPrimeiro e último dia com uma sessão.

Um código de país sem dados, como country=US para este filme, responde com country igual a US, um results vazio e a mesma lista countries. Um título sem sessões em lugar nenhum, como a série 1396, tem "countries": [].

Juntar os horários a uma chamada de detalhes

append_to_response=showtimes junta o mesmo bloco a uma resposta de detalhes, sob a chave showtimes. Envie o código country na mesma requisição. O bloco mantém as próprias chaves id, country, results e countries.

RequisiçãoResultado
/3/movie/550?append_to_response=showtimes&country=RURegistro do filme mais um bloco showtimes para a Rússia
/3/movie/550?append_to_response=credits,showtimes&country=RUAcrescenta os créditos à mesma chamada

Conta como uma requisição, então uma página de filme que mostra elenco e sessões precisa de uma única chamada. O mesmo endpoint existe para séries, como GET /3/tv/{tv_id}/showtimes.

Combinar com now_playing e region

A lista de filmes em cartaz dá os títulos. O endpoint de horários dá as sessões de um título. Una os dois no seu código.

PassoRequisiçãoResultado
1GET /3/movie/now_playing?region=RU&page=1Até 20 filmes por página, com cache de 30 minutos
2GET /3/movie/{id}/showtimes?country=RU para cada idLocais de exibição e horários, onde conhecidos

O laço abaixo tenta de novo uma ou duas vezes quando o limite do plano é atingido, esperando o número de segundos de Retry-After.

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

Uma página de 20 títulos são 20 requisições de horários. No plano de 20 requisições por minuto isso usa a janela inteira, então guarde o resultado em cache do seu lado. Veja em alta e listas para os parâmetros das listas.

Erros

O corpo do erro segue o TMDB: success, status_code e status_message. Uma chave inválida mostra status_code 7.

HTTPstatus_codeQuando
4017A chave está ausente ou incorreta.
40236O período do plano terminou.
40434Nenhum filme com esse id.
42925Você passou do seu limite de requisições por minuto. Espere os segundos indicados em Retry-After.

Não ter sessões não é um erro: espere o status 200 e um array results vazio. Um country ausente ou inválido também não é um erro. Veja erros e limites de requisições.

Notas práticas

  • A cobertura varia por país e título. Trate um array results vazio como desconhecido, e não como fora de cartaz.
  • Mostre start exatamente como retornado. É a hora local do local de exibição, sem deslocamento UTC, e o relógio do próprio cinema é o que os visitantes esperam.
  • Os horários ficam em cache de borda por 30 minutos. Não os peça a cada visualização de página e mantenha seu próprio cache curto.
  • Reutilize uma única lista de filmes em cartaz para todos os visitantes de uma região. Ela também tem cache de borda de 30 minutos.
  • Use booking_url para enviar o visitante à página de reservas do local de exibição. Ele é null quando o local não informa um link.
  • Para a visão do caso de uso, veja API de horários de sessões de cinema, e para os outros dados de um filme, veja filmes.