International Showtimes API
Version: 5
Base URI: https://api.internationalshowtimes.com/v5
Introduction
Welcome
Welcome to the Documentation for the International Showtimes API. We include movie metadata, showtimes data, ticket deep linking in one simple API for your online or offline content, apps or services. We are delivering best data for Europe, USA, Oceania, Asia Pacific, South America and other planets you might be looking for.
Support
Please raise any questions or report issues regarding the API via our JIRA Service Desk System.
Authentication
An apikey
must be sent with every request. To get your API-Key sign up for a free trial.
There are multiple options to send the apikey
:
- HTTP Authentication: Token Access Authentication
- Example:
curl "https://api.internationalshowtimes.com/v5/cinemas/" -H "Authorization: Token token=YOUR_API_KEY"
- Example:
- HTTP Header 'X-API-Key'
- Example:
curl "https://api.internationalshowtimes.com/v5/cinemas/" -H "X-Api-Key: YOUR_API_KEY"
- Example:
- URL parameter
- Example:
curl "https://api.internationalshowtimes.com/v5/cinemas/?apikey=YOUR_API_KEY"
- Example:
Please avoid sending the apikey
via URL parameter if possible. Use one of the HTTP Headers options instead!
Example Requests
The following examples demonstrate the usage of basic query parameters for some use simple cases. Most of the available parameters work like filters and be combined according to your needs. Values in curly braces are placeholder.
Get all cinemas in a specific country
GET https://api.internationalshowtimes.com/v5/cinemas/?countries=DE
Get all cinemas at a specific coordinate within a distance of 30 kilometres.
GET https://api.internationalshowtimes.com/v5/cinemas/?location=52.5,13.37&distance=30
How to get all movies playing in a particular cinema
GET https://api.internationalshowtimes.com/v5/movies/?cinema_id={ID}
Search for a movie by german title
GET https://api.internationalshowtimes.com/v5/movies?search_query=Avengers&search_field=title&lang=de
Get a list of upcoming movies for Germany
GET https://api.internationalshowtimes.com/v5/movies?include_upcomings=true&countries=DE&release_date_from={DATE}
release_date_from
should be set to a date slightly in the future to exclude current movies, for example tomorrow or today + 1 week.
Fetch only a subset of available fields for a particular movie
GET https://api.internationalshowtimes.com/v5/movies/30767?fields=id,title,original_title,release_dates,imdb_id
Get all showtimes of a movie playing in all theatres within a radius of 30 kilometres around a certain coordinate
GET https://api.internationalshowtimes.com/v5/showtimes?movie_id=18047&location=52.331705,13.37&distance=30
Get all showtimes per movie in a specific City
GET https://api.internationalshowtimes.com/v5/showtimes?city_ids=1&movie_id=12345
Localization
Movie metadata is available in different languages and locales. To specify the locale for retrieving movie metadata include a supported locale via one of the following ways. The locale can be specified for any requests which include movie data (such as the movies or the showtimes endpoints).
URL parameter lang
- Example:
curl "https://api.internationalshowtimes.com/v5/movies/?lang=de"
HTTP Header Accept-Language
Any valid value as specified in RFC2616 will be handled.
- Example:
curl "https://api.internationalshowtimes.com/v5/movies/" -H "Accept-Language: de"
Fetch the Locale - index endpoint to see which locales are available.
Miscellaneous
Identifiers
All identifiers are of type string
even if they could actually also be integer
. The reason for that is simply the role of these values being nothing but identifiers. This means even if the strings are serial numbers or any other logic, there is no guarantee it will stay the same. Hence, building anything based on any identifier structure may break in the future.
JSON Keys
When comes to naming JSON keys there are many debates about CamelCase vs underscores. Considering JSON actually standing for JavaScript Object Notation means it should be CamelCase - as that's native to JavaScript, we think underscores have a better readability.
API Updates
As of mid 2019 the API has been updated with a new major version. Click over here if you need to access the documentation for the previous version.
2023-12-14:
New
Movies endpoint
Added a new field
age_limits_descriptors
that contains the descriptors information with age rating for Germany (DE
). Information is provided in English (en
) and German (de
) translations. It is different information that is visible in age_limitsExample:
"age_limits_descriptors": {"DE": {"age": "12", "descriptors": [{"en": "violence", "de": "Gewalt"}]}}
2023-01-18:
New
- Showtimes endpoint
- Added new filter for
attribute_codes
property to retrieve showtimes
- Added new filter for
2021-01-14:
New
- Showtimes endpoint
- Added
changed_since
query parameter, that allows to fetch incremental showtimes updates.
- Added
2019-05-05: V4 → V5
New
- new Attribute endpoint
Model Updates
Country Model Updates
change | description |
---|---|
new | continent property |
Showtimes Model Updates
change | description |
---|---|
new | attribute_codes property |
removed | is_3d is now covered via of new attributes property |
removed | is_imax is now covered via of new attributes property |
FAQS
What are the best practices to implement your Cinema Showtimes API?
Regarding the implementation process, each API user has its unique approach when it comes to utilizing our API. In most cases, the users tend to retrieve data for the entire market, store it locally, and then develop their own functionalities on top of it.
How many API calls can I make in a specific timeframe?
The distinction in question pertains to whether your utilization involves our shared server infrastructure or a dedicated server arrangement. Furthermore, it's noteworthy that the performance attributes of a dedicated server are contingent upon its particular configuration. To illustrate, an illustrative instance of a dedicated server showcases a request potential of up to 20,000 requests per hour. Importantly, we wish to emphasize that, at present, there are no explicit constraints imposed on the quantity of API calls you may make.
How can I understand the 200 and 301 response upon reloading or subsequent API queries?
Our application utilizes a Load Balancer to distribute incoming network traffic across multiple servers for optimal performance and reliability. The HTTP 301 status code you're experiencing indicates this redirection process, designed to maintain service performance. We suggest using a library that automatically follows HTTP redirects or implementing a solution where your application retries requests until a non-301 response is received.
Why do we receive showtimes data from the day before?
Our API covers a diverse range of countries, each operating in different time zones. This necessitates the consideration of various time differences when it comes to showtimes. To ensure that our users have accurate and up-to-date information, we maintain old showtimes on our API for up to 24 hours before they eventually disappear. This approach allows us to accommodate the varying timeframes in which showtimes might be relevant across different regions.
How can I understand if a cinema removed showtimes?
It's important to note that our dataset undergoes updates several times daily. When cinemas modify their schedules, we conduct reimports of the showtimes data. During this process, if a showtime has already passed or has been deleted by the cinema, it naturally ceases to be visible within our API. Consequently, there is no requirement for us to implement specific markers on our end for such instances, as they are inherently excluded from our dataset.
How can I query showtimes through a daily bulk export, with the potential inclusion of incremental updates (deltas)?
In our API implementation, we have integrated HTTP-Caching mechanisms which can be found here
https://api.internationalshowtimes.com/documentation/v5/#HTTP-Caching--advanced-
When you make a request to our API, it will provide a complete response if there have been any changes in the API data since your last request. If there have been no alterations in the data, the API will respond with an empty response body accompanied by the status code 304 (Not Modified).
How can I query all showtimes for a specific city?
First, obtain a list of cities available in a country with this API request:
https://api.internationalshowtimes.com/v5/cities/?apikey={YOUR_API_KEY}&countries={ADD_COUNTRY_ISO_CODE}
Once you have the city's unique identifier (ID), retrieve the showtimes for that city using this example API request:
https://api.internationalshowtimes.com/v5/showtimes/?city_ids={ADD_CITY_ID}&apikey={YOUR_API_KEY}&countries={ADD_COUNTRY_ISO_CODE}
These steps allow you to retrieve screening schedules within the specified city.
How can I query showtimes for a movie and user location and then streamline retrieved details for multiple cinemas in one API call?
You can retrieve the required information by using this format:
https://api.internationalshowtimes.com/v5/showtimes?location=39.894543631101804,-86.38220454013391&distance=30&apikey={YOUR_API_KEY}&append=cinemas&movie_id={ADD_MOVIE_ID}
With the 'append' parameter, you specify to include relevant movies and/or cinemas in the response.
How can I utilize the IMDB, TMDB, and Rentrak IDs as filtering criteria for showtimes?
IMDB, TMDB and/or Rentrak ID-s are only used for getting movie details or identifying our internal movie ID, not as a filter for showtimes. For example, to retrieve movies by IMDb_ID, use:
https://api.internationalshowtimes.com/v5/movies?imdb_id=tt10293406&apikey={YOUR_API_KEY}
This request gets movie details based on the provided IMDb_ID. The same logic would count for TMDB (tmdb_id) and Rentrak (rentrak_film_id).
Can we link our standard movie IDs (aligned with TMDB IDs) to ISA movie IDs and send a request parameter containing multiple movie IDs (our internal or TMDB IDs) to the showtimes endpoint?
You can link your internal movie ID with an ISA movie ID by using this request:
https://api.internationalshowtimes.com/v5/movies?tmdb_id={ADD_TMDB_ID}&apikey={YOUR_API_KEY}
For a list of available movies in our API, use:
https://api.internationalshowtimes.com/v5/movies/?apikey={YOUR_API_KEY}&countries={ADD_ISO_CODE}&include_upcomings=true&all_fields=true
However, there's currently no parameter for multiple movie IDs, whether internal or TMDB IDs.
Why is there a redirection to a different cinema ID when retrieving showtimes for a specific cinema?
At International Showtimes, we ensure data accuracy by consolidating duplicate venue entries. If you request showtimes for a cinema ID flagged for removal due to duplication, our system automatically redirects you to the correct and existing cinema ID, maintaining accurate information.
How can I query movies that will be released in the future?
We source our movie metadata from TMDB, ensuring that any movie listed on TMDB can also be retrieved through our API. To include movies in the movies table that do not yet have associated showtimes, you can enable this functionality by adding the parameter 'include_upcomings=true' to your request.
Please note that specifying the relevant countries is necessary. An example of the request format is as follows:
https://api.internationalshowtimes.com/v5/movies/?apikey={YOUR_API_KEY}&countries={COUNTRY_ISO_CODE}&include_upcomings=true
By utilizing this parameter in conjunction with the specified countries, you can access movies without showtimes in the Movies table.
How can I query movie information like plot summaries, cast, director, movie distributor, and ratings from IMDB or Rotten Tomatoes?
We offer an endpoint tailored to provide comprehensive movie metadata for specific films, with the exception of information regarding the movie distributor. You can initiate a request using the following format, as demonstrated here for the movie with ID 30121:
https://api.internationalshowtimes.com/v5/movies/30121?apikey={YOUR_API_KEY}
Through this endpoint, you can access a wealth of information, including details about the movie's runtime, cast, director, synopsis, and TMDB ratings.
How can I filter movies by specific language preferences?
You can filter movie content by language using the 'lang' parameter, but please note that 'scene_images' cannot be filtered by language. For example, you can make the following request:
https://api.internationalshowtimes.com/v4/movies/{ADD_MOVIE_ID}?lang=en&apikey={YOUR_API_KEY}
This allows you to effectively filter movie content to your desired language.
What is the rationale behind certain movies having alphanumeric phrases as slugs, as opposed to having slugs that are more easily comprehensible by humans?
The presence of alphanumeric slugs, particularly in the case of movies with non-English characters or special symbols, is a result of our reliance on TMDB for movie metadata importation. This occurrence may extend to various other films that exhibit similar characteristics.
API Endpoints
Attributes
Movie screenings are held in a variety of differnt experiences by showing different version of the movies (e.g. 3D or IMAX) or adding other features to the event. Each experience added to a showtime is considered an attribute of it.
Retrieve the list of all attributes.
Use HEAD requests to query total number / count of a attributes. Allows to apply all filters as available via GET.
Locales
Countries
Cinema data, as well as showtime data, is available in many countries. However, access may be only granted to a limited subset for a given API-key. Use this endpoint to see which countries are available in general and to your apikey.
Retrieve the list of all countries.
Use HEAD requests to query total number / count of a countries. Allows to apply all filters as available via GET.
Cities
Cinemas
The collection of cinemas.
Retrieve the list of all cinemas, optionally filtered.
Use HEAD requests to query total number / count of a cinemas. Allows to apply all filters as available via GET.
Cinema Chains
Movies
The collection of movies.
Retrieve a shallow list of movies (in theatres if not specified otherwise). See the fields
query parameters default value for the list of included fields.
Use HEAD requests to query total number / count of a movies. Allows to apply all filters as available via GET.
Genres
Showtimes
The collection of showtimes.
Retrieve the list of all showtimes, optionally filtered.
Use HEAD requests to query total number / count of a showtimes. Allows to apply all filters as available via GET.
Advanced
Connectivity
HTTPS only
The API uses TLS to provide a secure way to deliver its data. Even though the API just supplies cinema and showtime data, we think that it's the right thing to do to encrypt the entire traffic. Furthermore, we only support TLS v1.0, v1.1 and v1.2. We do not support SSL v2 or v3 for a good reason. If your client uses HTTP to connect, the API redirects (HTTP code 301) to https://api.internationalshowtimes.com/v5/.
IPv6 ready
We enabled IPv6 on api.internationalshowtimes.com and videos.internationalshowtimes.com improve connectivity and have your API client ready for the future. Read more about IPv6.
Get DNS AAAA records (IPv6) using dig: dig AAAA api.internationalshowtimes.com
What is IPv6 and why do we need it?
The Internet operates by transferring data between networks in packets. In order to communicate and send/receive packets of data, each host, computer or other device connected to the Internet must be identified by a unique IP address. IPv4 has approximately four billion IP addresses (the sequence of numbers assigned to each Internet-connected device). The explosion in the number of people, devices, and web services on the Internet means that IPv4 is running out of space. IPv6, the next-generation Internet protocol which provides more than 340 trillion, trillion, trillion addresses, will connect the billions of people not connected today, allow a huge range of devices to connect directly with one another, and help ensure the Internet can continue its current growth rate indefinitely. Both IPv4 and IPv6 (and many other protocols at the core of the Internet) were developed by the Internet Engineering Task Force (IETF).
HTTP Caching
This API supports HTTP caching, which is highly recommended to take advantage of in order to avoid unnecessary transfer of data.
The main idea is that data will only be sent to the client, if something has changed. To make use of this approach this API provides a Last-Modified
header for each response. Once the client receives it, it should save the modification date to pass it to subsequent requests using If-Modified-Since
header. This header makes a request (GET or HEAD) conditional: the server will send back the requested data only if it has been modified after the given timestamp. Otherwise, an empty response with a 304 Not Modified status code will be returned. This is especially useful for checking about showtime updates frequently.
Learn more:
- Understanding HTTP/304 Responses
- HTTP Caching by Mozilla
Errors
Errors may be returned with a JSON payload which is structured as followed:
{
"error": {
"code": <Numeric error code>,
"user_message": <string message ready to be display to the user>
"debug_message": <string message intended for the developer to help resolving the error>
}
}
The internal_message
is not present for all errors and may not be exposed according to the apikey
's permissions.
Error codes are structured by error domains:
Range | Error Domain |
---|---|
10000 | General: Retrieving data (Cinemas, Movies, Showtimes etc.) |
20000 | Ticketing |
30000 | User management |
Error Codes
Code | Error |
---|---|
10001 | Service unavailable for maintenance |
10002 | Unauthorized due to missing apikey |
10003 | Unauthorized due to unknown apikey |
10004 | Requested countries are forbidden for given apikey |
10005 | Unauthorized due to expired apikey |
10006 | Parameter validation failed |
10007 | Resource not found |
10008 | Undefined route / endpoint |
10009 | Resource was deleted due to duplicate. |
10010 | No permission to access requested resource. |
Maintenance
In case of maintenance either all calls or specific calls will return a 503
response with the following payload (body). Make sure you also check the error code 10001
given with the response payload.
{
"error": {
"code": 10001,
"user_message": "service unavailable for maintenance"
}
}
Code Examples
The following code examples fetch a list of movies from Great Britains cinemas.
cURL
curl -X "GET" "https://api.internationalshowtimes.com/v5/movies/?countries=GB" -H "X-API-Key: YOUR_API_KEY"
GO
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func sendList() {
// Create client
client := &http.Client{}
// Create request
req, err := http.NewRequest("GET", "https://api.internationalshowtimes.com/v5/movies/?countries=GB", nil)
// Headers
req.Header.Add("X-API-Key", "YOUR_API_KEY")
parseFormErr := req.ParseForm()
if parseFormErr != nil {
fmt.Println(parseFormErr)
}
// Fetch Request
resp, err := client.Do(req)
if err != nil {
fmt.Println("Failure : ", err)
}
// Read Response Body
respBody, _ := ioutil.ReadAll(resp.Body)
// Display Results
fmt.Println("response Status : ", resp.Status)
fmt.Println("response Headers : ", resp.Header)
fmt.Println("response Body : ", string(respBody))
}
JavaScript + jQuery
jQuery.ajax({
url: "https://api.internationalshowtimes.com/v5/movies/",
type: "GET",
data: {
"countries": "GB",
},
headers: {
"X-API-Key": "YOUR_API_KEY",
},
})
.done(function(data, textStatus, jqXHR) {
console.log("HTTP Request Succeeded: " + jqXHR.status);
console.log(data);
})
.fail(function(jqXHR, textStatus, errorThrown) {
console.log("HTTP Request Failed");
})
.always(function() {
/* ... */
});
Java (Apache HttpClient via Fluent API)
import java.io.IOException;
import org.apache.http.client.fluent.*;
public class SendRequest
{
public static void main(String[] args) {
sendRequest();
}
private static void sendRequest() {
try {
// Create request
Content content = Request.Get("https://api.internationalshowtimes.com/v5/movies/?countries=GB")
// Add headers
.addHeader("X-API-Key", "YOUR_API_KEY")
// Fetch request and return content
.execute().returnContent();
// Print content
System.out.println(content);
}
catch (IOException e) { System.out.println(e); }
}
}
Node.js
(function(callback) {
'use strict';
const httpTransport = require('https');
const responseEncoding = 'utf8';
const httpOptions = {
hostname: 'api.internationalshowtimes.com',
port: '443',
path: '/v5/movies/?countries=GB',
method: 'GET',
headers: {"X-API-Key":"YOUR_API_KEY"}
};
httpOptions.headers['User-Agent'] = 'node ' + process.version;
// Paw Store Cookies option is not supported
const request = httpTransport.request(httpOptions, (res) => {
let responseBufs = [];
let responseStr = '';
res.on('data', (chunk) => {
if (Buffer.isBuffer(chunk)) {
responseBufs.push(chunk);
}
else {
responseStr = responseStr + chunk;
}
}).on('end', () => {
responseStr = responseBufs.length > 0 ?
Buffer.concat(responseBufs).toString(responseEncoding) : responseStr;
callback(null, res.statusCode, res.headers, responseStr);
});
})
.setTimeout(120000)
.on('error', (error) => {
callback(error);
});
request.write("")
request.end();
})((error, statusCode, headers, body) => {
console.log('ERROR:', error);
console.log('STATUS:', statusCode);
console.log('HEADERS:', JSON.stringify(headers));
console.log('BODY:', body);
});
PHP + cURL
<?php
// Get cURL resource
$ch = curl_init();
// Set url
curl_setopt($ch, CURLOPT_URL, 'https://api.internationalshowtimes.com/v5/movies/?countries=GB');
// Set method
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
// Set options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Set headers
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"X-API-Key: YOUR_API_KEY",
]
);
// Send the request & save response to $resp
$resp = curl_exec($ch);
if(!$resp) {
die('Error: "' . curl_error($ch) . '" - Code: ' . curl_errno($ch));
} else {
echo "Response HTTP Status Code : " . curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo "\nResponse HTTP Body : " . $resp;
}
// Close request to clear up some resources
curl_close($ch);
Python + Requests
# Install the Python Requests library:
# `pip install requests`
import requests
def send_request():
try:
response = requests.get(
url="https://api.internationalshowtimes.com/v5/movies/",
params={
"countries": "GB",
},
headers={
"X-API-Key": "YOUR_API_KEY",
},
)
print('Response HTTP Status Code: {status_code}'.format(
status_code=response.status_code))
print('Response HTTP Response Body: {content}'.format(
content=response.content))
except requests.exceptions.RequestException:
print('HTTP Request failed')
Ruby
require 'net/http'
require 'net/https'
def send_request
uri = URI('https://api.internationalshowtimes.com/v5/movies/?countries=GB')
# Create client
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
# Create Request
req = Net::HTTP::Get.new(uri)
# Add headers
req.add_field "X-API-Key", "YOUR_API_KEY"
# Fetch Request
res = http.request(req)
puts "Response HTTP Status Code: #{res.code}"
puts "Response HTTP Response Body: #{res.body}"
rescue StandardError => e
puts "HTTP Request failed (#{e.message})"
end
Swift
class MyRequestController {
func sendRequest() {
/* Configure session, choose between:
* defaultSessionConfiguration
* ephemeralSessionConfiguration
* backgroundSessionConfigurationWithIdentifier:
And set session-wide properties, such as: HTTPAdditionalHeaders,
HTTPCookieAcceptPolicy, requestCachePolicy or timeoutIntervalForRequest.
*/
let sessionConfig = URLSessionConfiguration.default
/* Create session, and optionally set a URLSessionDelegate. */
let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
guard var URL = URL(string: "https://api.internationalshowtimes.com/v5/movies/") else {return}
let URLParams = [
"countries": "GB",
]
URL = URL.appendingQueryParameters(URLParams)
var request = URLRequest(url: URL)
request.httpMethod = "GET"
// Headers
request.addValue("YOUR_API_KEY", forHTTPHeaderField: "X-API-Key")
/* Start a new Task */
let task = session.dataTask(with: request, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) -> Void in
if (error == nil) {
// Success
let statusCode = (response as! HTTPURLResponse).statusCode
print("URL Session Task Succeeded: HTTP \(statusCode)")
}
else {
// Failure
print("URL Session Task Failed: %@", error!.localizedDescription);
}
})
task.resume()
session.finishTasksAndInvalidate()
}
}
protocol URLQueryParameterStringConvertible {
var queryParameters: String {get}
}
extension Dictionary : URLQueryParameterStringConvertible {
/**
This computed property returns a query parameters string from the given NSDictionary. For
example, if the input is @{@"day":@"Tuesday", @"month":@"January"}, the output
string will be @"day=Tuesday&month=January".
@return The computed parameters string.
*/
var queryParameters: String {
var parts: [String] = []
for (key, value) in self {
let part = String(format: "%@=%@",
String(describing: key).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!,
String(describing: value).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)
parts.append(part as String)
}
return parts.joined(separator: "&")
}
}
extension URL {
/**
Creates a new URL by adding the given query parameters.
@param parametersDictionary The query parameter dictionary to add.
@return A new URL.
*/
func appendingQueryParameters(_ parametersDictionary : Dictionary<String, String>) -> URL {
let URLString : String = String(format: "%@?%@", self.absoluteString, parametersDictionary.queryParameters)
return URL(string: URLString)!
}
}