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
| Parameter | In | Required | Description |
|---|---|---|---|
movie_id | path | yes | Numeric movie id, for example 550. |
country | query | no | Two letter country code such as RU. Without it you get the per-country summary only. region is an alias. |
api_key | query | one of two | Your key. Use this or the Authorization: Bearer header. |
Response fields
| Field | Type | Notes |
|---|---|---|
id | integer | Movie id. |
country | string or null | The upper case code you asked for, or null when country is missing or not two letters. |
results | array | One object per venue, ordered by venue. Empty when nothing is known or no country was sent. At most 1500 showtimes in total. |
results[].id | integer | Venue id. |
results[].name | string | Venue name. |
results[].chain | object | key is the chain key, name is the chain name or null. |
results[].city | string or null | City. |
results[].region | string or null | Region. |
results[].address | string or null | Street address. |
results[].postal_code | string or null | Postal code. |
results[].country | string | Country code of the venue. |
results[].timezone | string or null | IANA time zone such as Europe/Moscow. |
results[].latitude, results[].longitude | number or null | Venue position. |
results[].phone | string or null | Phone number. |
results[].url | string or null | Venue page. |
results[].showtimes | array | Screenings at that venue, ordered by start. |
results[].showtimes[].date | string | Day as 2026-10-18. |
results[].showtimes[].start | string | Start in venue local time like 2026-10-18T21:40, with no UTC offset. |
results[].showtimes[].end | string or null | End in venue local time. |
results[].showtimes[].auditorium | string or null | Hall name. |
results[].showtimes[].formats | array of strings | Formats such as 2D. |
results[].showtimes[].tags | array of strings | Extra labels. Often empty. |
results[].showtimes[].audio, subtitles, language | string or null | Audio, subtitle and language details when known. |
results[].showtimes[].price | number or null | Ticket price. |
results[].showtimes[].currency | string or null | Currency of price. |
results[].showtimes[].prices | any or null | Price details when a venue has several. |
results[].showtimes[].booking_url | string or null | Link to book the seat. |
results[].showtimes[].sold_out | boolean | true when the screening is sold out. |
countries | array | Per-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
{
"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 -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"
}
]
}| Field | Type | Notes |
|---|---|---|
countries[].country | string | Two letter code, ready to use as the country parameter. |
countries[].name | string | English country name. |
countries[].venues | integer | Venues with a screening. |
countries[].cities | integer | Cities with a screening. |
countries[].showtimes | integer | Screenings from today on. |
countries[].first_day, countries[].last_day | string | First 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.
| Request | Result |
|---|---|
/3/movie/550?append_to_response=showtimes&country=RU | Movie record plus a showtimes block for Russia |
/3/movie/550?append_to_response=credits,showtimes&country=RU | Adds 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.
| Step | Request | Result |
|---|---|---|
| 1 | GET /3/movie/now_playing?region=RU&page=1 | Up to 20 movies per page, cached for 30 minutes |
| 2 | GET /3/movie/{id}/showtimes?country=RU for each id | Venues 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.
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.
| HTTP | status_code | When |
|---|---|---|
| 401 | 7 | The key is missing or wrong. |
| 402 | 36 | The plan period has ended. |
| 404 | 34 | No movie with that id. |
| 429 | 25 | Over 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
resultsarray as unknown, not as not showing. - Show
startexactly 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_urlto send a visitor to the venue's booking page. It isnullwhen the venue gives no link. - For the use case overview, see cinema showtimes API, and for the other data on a movie, see movies.