Cinema showtimes

GET /3/movie/{movie_id}/showtimes?country=RU returns the venues that show a movie in one country, with dated showtimes at each. Without country it returns only per-country counts in a countries list. Coverage varies by country and title, and an empty results array means nothing is known for that pair.

Get showtimes for a movie

GET /3/movie/{movie_id}/showtimes?country=RU returns the venues that show a movie in one country, with the dated showtimes at each. The country parameter takes a two letter code, in upper or lower case. Coverage varies by country and title, so the data is present where it is known and missing where it is not. Only days from today on are returned.

The sample asks for Fight Club in Russia and handles an empty answer.

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, ","))
		}
	}
}

Parameters

ParameterInRequiredDescription
movie_idpathyesNumeric movie id, for example 550.
countryquerynoTwo letter country code such as RU. Without it you get the per-country summary only. region is an alias.
api_keyqueryone of twoYour key. Use this or the Authorization: Bearer header.

Response fields

FieldTypeNotes
idintegerMovie id.
countrystring or nullThe upper case code you asked for, or null when country is missing or not two letters.
resultsarrayOne object per venue, ordered by venue. Empty when nothing is known or no country was sent. At most 1500 showtimes in total.
results[].idintegerVenue id.
results[].namestringVenue name.
results[].chainobjectkey is the chain key, name is the chain name or null.
results[].citystring or nullCity.
results[].regionstring or nullRegion.
results[].addressstring or nullStreet address.
results[].postal_codestring or nullPostal code.
results[].countrystringCountry code of the venue.
results[].timezonestring or nullIANA time zone such as Europe/Moscow.
results[].latitude, results[].longitudenumber or nullVenue position.
results[].phonestring or nullPhone number.
results[].urlstring or nullVenue page.
results[].showtimesarrayScreenings at that venue, ordered by start.
results[].showtimes[].datestringDay as 2026-10-18.
results[].showtimes[].startstringStart in venue local time like 2026-10-18T21:40, with no UTC offset.
results[].showtimes[].endstring or nullEnd in venue local time.
results[].showtimes[].auditoriumstring or nullHall name.
results[].showtimes[].formatsarray of stringsFormats such as 2D.
results[].showtimes[].tagsarray of stringsExtra labels. Often empty.
results[].showtimes[].audio, subtitles, languagestring or nullAudio, subtitle and language details when known.
results[].showtimes[].pricenumber or nullTicket price.
results[].showtimes[].currencystring or nullCurrency of price.
results[].showtimes[].pricesany or nullPrice details when a venue has several.
results[].showtimes[].booking_urlstring or nullLink to book the seat.
results[].showtimes[].sold_outbooleantrue when the screening is sold out.
countriesarrayPer-country summary, see below.

Read the keys you use by name and skip extra keys inside a venue or showtime object. Many fields are null today because not every venue sends them.

Example response

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

The list is cut to 1 of 2 venues and 2 of 4 showtimes. Showtimes only exist for days that have not passed, so this answer changes every day.

Get the per-country summary

Leave country out and the reply holds counts only. results stays empty and country is null. The countries array lists up to 60 countries that still have a screening, the one with the most showtimes first. Use it to learn where a title is on screen before you ask for venues.

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"
    }
  ]
}
FieldTypeNotes
countries[].countrystringTwo letter code, ready to use as the country parameter.
countries[].namestringEnglish country name.
countries[].venuesintegerVenues with a screening.
countries[].citiesintegerCities with a screening.
countries[].showtimesintegerScreenings from today on.
countries[].first_day, countries[].last_daystringFirst and last day with a screening.

A country code with no data, such as country=US for this film, answers country as US, an empty results and the same countries list. A title with no showtimes anywhere, such as the series 1396, has "countries": [].

Add showtimes to a details call

append_to_response=showtimes merges the same block into a details reply under the showtimes key. Send the country code in the same request. The block keeps its own id, country, results and countries keys.

RequestResult
/3/movie/550?append_to_response=showtimes&country=RUMovie record plus a showtimes block for Russia
/3/movie/550?append_to_response=credits,showtimes&country=RUAdds credits to the same call

It counts as one request, so a movie page that shows cast and screenings needs a single call. The same endpoint exists for series as GET /3/tv/{tv_id}/showtimes.

Combine with now_playing and region

The now playing list gives you titles. The showtimes endpoint gives you screenings for one title. Join them in your code.

StepRequestResult
1GET /3/movie/now_playing?region=RU&page=1Up to 20 movies per page, cached for 30 minutes
2GET /3/movie/{id}/showtimes?country=RU for each idVenues and times, where known

The loop below retries once or twice when the plan limit is reached, waiting the number of seconds in 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');
}

A page of 20 titles is 20 showtime requests. On the 20 requests per minute plan that uses the whole window, so cache the result on your side. See trending and lists for the list parameters.

Errors

The error body follows TMDB: success, status_code and status_message. A bad key shows status_code 7.

HTTPstatus_codeWhen
4017The key is missing or wrong.
40236The plan period has ended.
40434No movie with that id.
42925Over your requests per minute. Wait for the Retry-After seconds.

No showtimes is not an error: expect status 200 and an empty results array. A missing or invalid country is not an error either. See errors and rate limits.

Practical notes

  • Coverage varies by country and title. Treat an empty results array as unknown, not as not showing.
  • Show start exactly as returned. It is the venue's local time with no UTC offset, and the venue's own clock is what visitors expect.
  • Showtimes are cached at the edge for 30 minutes. Do not request them for every page view, and keep your own cache short.
  • Reuse one now playing list for all visitors in a region. It is cached for 30 minutes at the edge too.
  • Use booking_url to send a visitor to the venue's booking page. It is null when the venue gives no link.
  • For the use case overview, see cinema showtimes API, and for the other data on a movie, see movies.