{
  "openapi": "3.0.1",
  "info": {
    "title": "UK Cinema API",
    "description": "Cinema, showtime and film data for the United Kingdom and the Republic of Ireland.",
    "contact": {
      "name": "UK Cinema API",
      "url": "https://uk-cinema-api.co.uk",
      "email": "support@uk-cinema-api.co.uk"
    },
    "version": "4.0.0"
  },
  "servers": [
    {
      "url": "https://uk-cinema-api.co.uk/api/v4/",
      "description": "Base URL"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "films",
      "description": "Operations about films"
    },
    {
      "name": "cinemas",
      "description": "Operations about cinemas"
    },
    {
      "name": "showtimes",
      "description": "Operations about showtimes"
    },
    {
      "name": "attributes",
      "description": "Operations about showtime attributes"
    },
    {
      "name": "chains",
      "description": "Operations about cinema chains"
    },
    {
      "name": "countries",
      "description": "Operations about the countries served"
    }
  ],
  "paths": {
    "/films": {
      "get": {
        "tags": ["films"],
        "description": "Get a paginated list of films currently showing in cinemas in the countries the request reads.",
        "summary": "Get films",
        "operationId": "listFilms",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "Page offset to fetch.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "items",
            "in": "query",
            "description": "Number of items to return per page.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Use cursor pagination. Send an empty `cursor` for the first page. Then send **`meta.next_cursor`** from each response as `cursor`. When `next_cursor` is `null`, you have all the results.\n\nA cursor walk gives films in `id` order, not in page order. You get a film that is added during the walk only if its `id` is after the cursor.\n\nWith a cursor, `meta` has `next_cursor` and not `page`, and the API ignores the `page` parameter. You cannot use `cursor` with `search_query`.",
            "schema": {
              "type": "string"
            },
            "example": ""
          },
          {
            "$ref": "#/components/parameters/Country"
          },
          {
            "name": "cinema_id",
            "in": "query",
            "description": "Filter by a specific cinema.",
            "schema": {
              "type": "integer"
            },
            "example": 748
          },
          {
            "name": "include_outdated",
            "in": "query",
            "description": "Include films that are no longer showing in cinemas.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "search_query",
            "in": "query",
            "description": "Search for films by title, director name, TMDB ID, or IMDB ID.",
            "schema": {
              "type": "string"
            },
            "example": "Carmen"
          },
          {
            "name": "tmdb_id",
            "in": "query",
            "description": "Filter by a specific TMDB ID.",
            "schema": {
              "type": "integer"
            },
            "example": 1702759
          },
          {
            "name": "imdb_id",
            "in": "query",
            "description": "Filter by a specific IMDB ID.",
            "schema": {
              "type": "string"
            },
            "example": "tt43657998"
          }
        ],
        "responses": {
          "200": {
            "description": "Returns films with pagination metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FilmsResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/films/{id}": {
      "get": {
        "tags": ["films"],
        "description": "Returns a film.",
        "summary": "Get film",
        "operationId": "getFilm",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Film ID.",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "example": 579691593
          },
          {
            "$ref": "#/components/parameters/Country"
          }
        ],
        "responses": {
          "200": {
            "description": "Returns a film.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Film"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/cinemas": {
      "get": {
        "tags": ["cinemas"],
        "description": "Get a paginated list of cinemas.",
        "summary": "Get cinemas",
        "operationId": "listCinemas",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "Page offset to fetch.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "items",
            "in": "query",
            "description": "Number of items to return per page.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "$ref": "#/components/parameters/Country"
          },
          {
            "$ref": "#/components/parameters/Latitude"
          },
          {
            "$ref": "#/components/parameters/Longitude"
          },
          {
            "$ref": "#/components/parameters/RadiusKm"
          }
        ],
        "responses": {
          "200": {
            "description": "Returns cinemas with pagination metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CinemasResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/cinemas/{id}": {
      "get": {
        "tags": ["cinemas"],
        "description": "Return a cinema.",
        "summary": "Get cinema",
        "operationId": "getCinema",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Cinema ID.",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "example": 748
          },
          {
            "$ref": "#/components/parameters/Country"
          }
        ],
        "responses": {
          "200": {
            "description": "Returns a cinema.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Cinema"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/cinemas/{chain}/external/{external_id}": {
      "get": {
        "tags": ["cinemas"],
        "description": "Get a cinema by cinema chain and the chain's native external ID.",
        "summary": "Get cinema by chain and external ID",
        "operationId": "getCinemaByExternalId",
        "parameters": [
          {
            "name": "chain",
            "in": "path",
            "description": "The cinema chain identifier.",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ChainEnum"
            },
            "example": "picturehouse"
          },
          {
            "name": "external_id",
            "in": "path",
            "description": "The cinema chain's native cinema identifier.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "029"
          },
          {
            "$ref": "#/components/parameters/Country"
          }
        ],
        "responses": {
          "200": {
            "description": "Returns a cinema matching the external ID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Cinema"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/showtimes": {
      "get": {
        "tags": ["showtimes"],
        "description": "Get a paginated list of showtimes.",
        "summary": "Get showtimes",
        "operationId": "listShowtimes",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "Page offset to fetch.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "items",
            "in": "query",
            "description": "Number of items to return per page.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Use cursor pagination. Send an empty `cursor` for the first page. Then send **`meta.next_cursor`** from each response as `cursor`. When `next_cursor` is `null`, you have all the results.\n\nShowtimes that are added or removed do not affect the cursor. But if the **`showing_at`** of a showtime changes, you can get that showtime two times or not at all.\n\nWith a cursor, `meta` has `next_cursor` and not `page`, and the API ignores the `page` parameter.",
            "schema": {
              "type": "string"
            },
            "example": ""
          },
          {
            "$ref": "#/components/parameters/Country"
          },
          {
            "name": "cinema_id",
            "in": "query",
            "description": "Filter by a specific cinema.",
            "schema": {
              "type": "integer"
            },
            "example": 748
          },
          {
            "name": "film_id",
            "in": "query",
            "description": "Filter by a specific film: returns the showtimes whose `film_ids` include it.",
            "schema": {
              "type": "integer"
            },
            "example": 579691593
          },
          {
            "name": "tmdb_id",
            "in": "query",
            "description": "Filter by a film's TMDB ID: returns the showtimes whose `film_ids` include it.",
            "schema": {
              "type": "integer"
            },
            "example": 1702759
          },
          {
            "name": "imdb_id",
            "in": "query",
            "description": "Filter by a film's IMDB ID: returns the showtimes whose `film_ids` include it.",
            "schema": {
              "type": "string"
            },
            "example": "tt43657998"
          },
          {
            "name": "from",
            "in": "query",
            "description": "Get only the showtimes that start at or after this time. Use ISO 8601, for example `2027-11-10T18:00:00+00:00`. If the value has no offset, the time is in the time zone of the cinema, as in showing_at. A date with no time is midnight.",
            "schema": {
              "type": "string"
            },
            "example": "2027-11-10T18:00:00+00:00"
          },
          {
            "name": "to",
            "in": "query",
            "description": "Get only the showtimes that start before this time (see from). `to` must be later than `from`.",
            "schema": {
              "type": "string"
            },
            "example": "2027-11-11T00:00:00+00:00"
          },
          {
            "$ref": "#/components/parameters/Latitude"
          },
          {
            "$ref": "#/components/parameters/Longitude"
          },
          {
            "$ref": "#/components/parameters/RadiusKm"
          },
          {
            "name": "attributes",
            "in": "query",
            "description": "Get only the showtimes that have all of these attributes: comma-separated IDs from `GET /attributes`, for example `imax` or `imax,dolby-atmos`. An unknown ID gives 400. A request that reads a country where your key has lite gives 403, because attribute codes are not included on that plan.",
            "schema": {
              "type": "string"
            },
            "example": "imax"
          }
        ],
        "responses": {
          "200": {
            "description": "Returns showtimes with pagination metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShowtimesResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/showtimes/{id}": {
      "get": {
        "tags": ["showtimes"],
        "description": "Return a showtime.",
        "summary": "Get showtime",
        "operationId": "getShowtime",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Showtime ID.",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "example": 30993718
          },
          {
            "$ref": "#/components/parameters/Country"
          }
        ],
        "responses": {
          "200": {
            "description": "Returns a showtime.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Showtime"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/showtimes/{chain}/external/{external_id}": {
      "get": {
        "tags": ["showtimes"],
        "description": "Get a showtime by cinema chain and the chain's native external ID.",
        "summary": "Get showtime by chain and external ID",
        "operationId": "getShowtimeByExternalId",
        "parameters": [
          {
            "name": "chain",
            "in": "path",
            "description": "The cinema chain identifier.",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ChainEnum"
            },
            "example": "picturehouse"
          },
          {
            "name": "external_id",
            "in": "path",
            "description": "The cinema chain's native showtime identifier.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "029-48021-1825873200-HO00018057"
          },
          {
            "$ref": "#/components/parameters/Country"
          }
        ],
        "responses": {
          "200": {
            "description": "Returns a showtime matching the external ID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Showtime"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/attributes": {
      "get": {
        "tags": ["attributes"],
        "description": "Get all available showtime attribute codes with their descriptions and categories.",
        "summary": "Get showtime attributes",
        "operationId": "listAttributes",
        "responses": {
          "200": {
            "description": "Returns all available showtime attributes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AttributesResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/chains": {
      "get": {
        "tags": ["chains"],
        "description": "Get a list of all cinema chains that have at least one cinema in the countries the request reads, with cinema counts.",
        "summary": "Get chains",
        "operationId": "listChains",
        "parameters": [
          {
            "$ref": "#/components/parameters/Country"
          }
        ],
        "responses": {
          "200": {
            "description": "Returns chains with metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChainsResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/chains/{id}": {
      "get": {
        "tags": ["chains"],
        "description": "Returns a single cinema chain by its identifier.",
        "summary": "Get chain",
        "operationId": "getChain",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Chain identifier.",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ChainEnum"
            },
            "example": "picturehouse"
          },
          {
            "$ref": "#/components/parameters/Country"
          }
        ],
        "responses": {
          "200": {
            "description": "Returns a chain.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Chain"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/chains/{id}/cinemas": {
      "get": {
        "tags": ["chains"],
        "description": "Get a paginated list of cinemas belonging to a specific chain.",
        "summary": "Get chain cinemas",
        "operationId": "listChainCinemas",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Chain identifier.",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ChainEnum"
            },
            "example": "picturehouse"
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page offset to fetch.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "items",
            "in": "query",
            "description": "Number of items to return per page.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "$ref": "#/components/parameters/Country"
          }
        ],
        "responses": {
          "200": {
            "description": "Returns cinemas with pagination metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CinemasResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/countries": {
      "get": {
        "tags": ["countries"],
        "description": "Get every country the API serves, and whether your key includes it. Without a `country` parameter, every other endpoint reads the countries your key includes.",
        "summary": "Get countries",
        "operationId": "listCountries",
        "responses": {
          "200": {
            "description": "Returns the countries served.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CountriesResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Send your API token in the Authorization header: `Authorization: Bearer YOUR_API_TOKEN`. Create a token on the API tokens page of your account, https://uk-cinema-api.co.uk/api_tokens."
      }
    },
    "parameters": {
      "Country": {
        "name": "country",
        "in": "query",
        "description": "Get results only for these countries: comma-separated ISO 3166-1 alpha-2 codes, for example `IE` or `GB,IE`. Without it, you get all the countries that your key includes. A country that your key does not include gives 403. A country that the API does not serve gives 400. `GET /countries` lists both.",
        "schema": {
          "type": "string"
        },
        "example": "GB,IE"
      },
      "Latitude": {
        "name": "latitude",
        "in": "query",
        "description": "Latitude of the center of the search, in decimal degrees. Send it with `longitude` and `radius_km`. If you send one of these three parameters, you must send all three.",
        "schema": {
          "type": "number",
          "minimum": -90,
          "maximum": 90
        },
        "example": 51.5103
      },
      "Longitude": {
        "name": "longitude",
        "in": "query",
        "description": "Longitude of the center of the search, in decimal degrees (see latitude).",
        "schema": {
          "type": "number",
          "minimum": -180,
          "maximum": 180
        },
        "example": -0.1301
      },
      "RadiusKm": {
        "name": "radius_km",
        "in": "query",
        "description": "Get results only for cinemas in this distance from `latitude` and `longitude`, in kilometres. The distance is the great-circle distance to the cinema. The value must be more than 0 and not more than 100 (see latitude).",
        "schema": {
          "type": "number",
          "exclusiveMinimum": true,
          "minimum": 0,
          "maximum": 100
        },
        "example": 5
      }
    },
    "schemas": {
      "ChainEnum": {
        "type": "string",
        "enum": [
          "abbey_abingdon",
          "aberystwyth_arts_centre",
          "abbeygate_cinema",
          "act_one_cinema",
          "aldeburgh_cinema",
          "alnwick_playhouse",
          "apollo_leisure",
          "arc_cinema",
          "arthouse_crouch_end",
          "ashford_cinema",
          "baker_street_abergavenny",
          "barbican",
          "beam_hertford",
          "bijou_southport",
          "birks_cinema",
          "bishop_auckland_town_hall",
          "bfi",
          "bonington_theatre",
          "breweryarts",
          "broadway",
          "broadway_douglas",
          "broadway_letchworth",
          "brynamman_cinema",
          "brunswick_movie_bowl",
          "buncrana_cinema",
          "buxton_opera_house",
          "campbeltown_picture_house",
          "campus_west",
          "castle_cinema",
          "castle_theatre",
          "cellb",
          "central_cinema_fakenham",
          "century_cinemas",
          "chalmers_group",
          "chapter",
          "chiswick_cinema",
          "dorking_halls",
          "chichester_cinema",
          "chipping_norton_theatre",
          "cine_lumiere",
          "cinebowl",
          "cinema_co",
          "cinema_killarney",
          "cinema_museum",
          "cinemac",
          "cinemax_bantry",
          "clonakilty_park_cinema",
          "close_up_film_centre",
          "commodore_cinema",
          "commodore_ryde",
          "cork_film_festival",
          "corn_exchange",
          "corn_exchange_newbury",
          "cineworld",
          "coliseum_brecon",
          "courtyard",
          "cromarty_cinema",
          "cross_hands_cinema",
          "cultplex",
          "cube_cinema",
          "curzon",
          "curzon_clevedon",
          "customs_house",
          "dartington",
          "david_lean_cinema",
          "derby_quad",
          "dominion_cinema",
          "dukeslancaster",
          "dundee_contemporary_arts",
          "east_coast_cinema",
          "eastgate_theatre",
          "eclipse_cinemas",
          "eden_court",
          "electric_cinema",
          "elite_ashbourne",
          "em_forster_theatre",
          "electric_palace",
          "electric_palace_cannock",
          "electric_palace_hastings",
          "exeter_phoenix",
          "plymouth_arts_cinema",
          "glasgow_science_centre_imax",
          "empire_consett",
          "empire_holyhead",
          "empire_sandwich",
          "empire_theatre",
          "everyman",
          "eye_cinema",
          "farnham_maltings",
          "festival_drayton_centre",
          "filmhouse",
          "firstsite",
          "flower_bowl",
          "fraser_centre",
          "forum_bridlington",
          "forum_hexham",
          "futurist_cinema",
          "gaiety_cinema",
          "gala_durham",
          "galeri_caernarfon",
          "hebden_bridge",
          "helensburgh_cinema",
          "garden_cinema",
          "genesis_cinema",
          "glasgow_film_theatre",
          "gloucester_guildhall",
          "grove_theatre",
          "gulbenkian_cinema",
          "gwyn_hall",
          "hailsham_pavilion",
          "heart_of_hawick",
          "hpph",
          "highland_cinema",
          "hippodrome_cinema",
          "home_mcr",
          "ica",
          "irish_film_institute",
          "jam_jar_cinema",
          "junction_goole",
          "jw3",
          "kavanagh_cinema",
          "imc_cinema",
          "ilkley_cinema",
          "keswick_alhambra",
          "kiln_theatre",
          "king_street",
          "kings_cinema_newmarket",
          "kings_lynn_corn_exchange",
          "kirkgate_arts",
          "kinema_in_the_woods",
          "kino_cinema",
          "kino_digital",
          "kino_teatr",
          "lanternhouse_cinema",
          "las_portree",
          "leatherhead_theatre",
          "leigh_film_factory",
          "leiston_film_theatre",
          "lewes_depot",
          "libanus_1877",
          "lexi_cinema",
          "mallard_cinema",
          "malt_cinema",
          "maltings_berwick",
          "maona_cinema",
          "market_pavilion",
          "marina_theatre",
          "market_hall_cinema",
          "lonsdale_alhambra",
          "lonsdale_annan",
          "magic_lantern",
          "lowther_pavilion",
          "light_house_cinema",
          "lighthousepoole",
          "living_room_cinema",
          "loewen_cinema",
          "ludlow_assembly_rooms",
          "lumiere",
          "macrobert_arts_centre",
          "malvern_theatres",
          "lynton_cinema",
          "malton_palace",
          "mayo_movie_world",
          "merlin",
          "metro_cinema",
          "midlands_arts_centre",
          "mk_gallery",
          "mockingbird",
          "monmouth_savoy",
          "montrose_playhouse",
          "moray_playhouse",
          "movie_starr",
          "movie_house",
          "movies_at",
          "neo_cinema_woolacombe",
          "new_picture_house",
          "newcastle_community_cinema",
          "newlyn_filmhouse",
          "nickel_cinema",
          "newton_stewart_cinema",
          "northampton_filmhouse",
          "northern_light",
          "northern_morris",
          "nova_cinema",
          "number_30_huntly",
          "number_8_pershore",
          "odeon_gb",
          "odeon_ie",
          "old_market_hall",
          "odyssey_cinema",
          "totnes_cinema",
          "omniplex",
          "olympic_studios",
          "orion",
          "oxford_cinema",
          "palace_broadstairs",
          "palace_cinderford",
          "palace_douglas",
          "palace_haverfordwest",
          "palace_cinemas",
          "parade_cinema",
          "parkway_cinemas",
          "peckhamplex",
          "pdj_cinemas",
          "penarth_pier_pavilion",
          "penistone_paramount",
          "phoenix_cinema",
          "phoenix_leicester",
          "piccadilly_leicester",
          "pickaquoy",
          "picturedrome",
          "picturehouse",
          "plaza_cinema",
          "pontardawe_arts_centre",
          "pontio",
          "regal_evesham",
          "regal_fordingbridge",
          "regal_melton",
          "regal_stowmarket",
          "regal_tenbury",
          "regent_centre",
          "regent_cinema",
          "regent_newtown",
          "regent_street_cinema",
          "rex",
          "rosehill_theatre",
          "rex_wareham",
          "rex_wilmslow",
          "rheged",
          "ritz",
          "ritz_cookstown",
          "ritz_thirsk",
          "ritz_workington",
          "the_riverside",
          "theatr_gwaun",
          "tower_cinema",
          "towner_cinema",
          "prince_charles",
          "queens_film_theatre",
          "rct_theatres",
          "reading_biscuit_factory",
          "rebel_cinema",
          "red_carpet_cinema",
          "reel",
          "rich_mix",
          "rio_burnham",
          "rio_cinema",
          "riverfront_newport",
          "riverside_studios",
          "robert_burns_centre",
          "rooftop_cinema_club",
          "roses_theatre",
          "roxy_movies",
          "royal_faversham",
          "royal_spa_centre",
          "royalty_bowness",
          "saffron_screen",
          "sandb",
          "sandpit_theatre",
          "savoy",
          "scala_ilkeston",
          "science_and_media_museum",
          "science_museum_imax",
          "savoy_heaton_moor",
          "scott_cinema",
          "scotsman_group",
          "shaftesbury_arts_centre",
          "sherborne_cinema",
          "sheringham_little_theatre",
          "shetlandarts",
          "showcase",
          "showroom_cinema",
          "silver_screen_folkestone",
          "south_holland_centre",
          "southhill_park",
          "sjt",
          "st_georges_theatre",
          "spey_valley_cinema",
          "stag_theatre",
          "stamford_arts_centre",
          "star_and_shadow",
          "station_cinema",
          "stella_cinema",
          "storyhouse",
          "taliesin_arts_centre",
          "tavistock_wharf",
          "the_arzner",
          "the_atrium",
          "the_devlin",
          "the_film_place",
          "the_flavel",
          "the_light",
          "theatr_clwyd",
          "theatr_colwyn",
          "theatr_mwldan",
          "the_poly",
          "the_reel_picture",
          "the_w_cinema",
          "tipperary_excel",
          "torch_theatre",
          "triskel_christchurch",
          "tyneside",
          "uckfield_picture_house",
          "upp",
          "vault_cinema",
          "vue",
          "warwick_arts_centre",
          "watermans",
          "watershed",
          "wellington_orbit",
          "wells_film_centre",
          "wem_town_hall",
          "west_coast_cinemas",
          "wetherby_cinema",
          "weymouth_pavilion",
          "windmill_cinema",
          "winter_garden_bute",
          "wtw_cinema",
          "worthing_theatres",
          "wotton_electric_picture_house",
          "wyeside",
          "wyllyotts_theatre",
          "york_student_cinema",
          "zeffirellis"
        ],
        "description": "The identifier of a cinema chain. GET /chains lists the chains in the countries that your key includes."
      },
      "CountryEnum": {
        "type": "string",
        "description": "ISO 3166-1 alpha-2. `GB` is the whole United Kingdom, Northern Ireland included; `IE` is the Republic of Ireland.",
        "enum": ["GB", "IE"]
      },
      "CurrencyCode": {
        "type": "string",
        "description": "ISO 4217: `GBP` in the United Kingdom, `EUR` in the Republic of Ireland.",
        "pattern": "^[A-Z]{3}$"
      },
      "MetaInfo": {
        "type": "object",
        "required": ["total_count"],
        "properties": {
          "page": {
            "type": "integer",
            "description": "Current page number"
          },
          "per_page": {
            "type": "integer",
            "description": "The number of items on each page (see the `items` parameter)."
          },
          "total_count": {
            "type": "integer",
            "description": "Total number of items across all pages"
          },
          "next_cursor": {
            "type": "string",
            "nullable": true,
            "description": "Opaque cursor for the next page, or null on the last page. Present only when the request used cursor pagination. Pass it back as `cursor` to fetch the next page."
          }
        },
        "description": "Information about a list: the total count, and the page or the cursor.",
        "example": {
          "page": 1,
          "per_page": 20,
          "total_count": 562
        }
      },
      "Cinema": {
        "type": "object",
        "required": [
          "id",
          "chain",
          "name",
          "address",
          "latitude",
          "longitude",
          "link",
          "google_place_id",
          "closed",
          "country",
          "currency"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32",
            "description": "Our identifier for the cinema."
          },
          "chain": {
            "$ref": "#/components/schemas/ChainEnum"
          },
          "name": {
            "type": "string",
            "description": "The name of the cinema. At a chain, it is often only the location, for example \"London West End\"."
          },
          "address": {
            "type": "string",
            "description": "The postal address of the cinema, on one line."
          },
          "latitude": {
            "type": "number",
            "format": "float",
            "description": "The latitude of the cinema, in decimal degrees."
          },
          "longitude": {
            "type": "number",
            "format": "float",
            "description": "The longitude of the cinema, in decimal degrees."
          },
          "link": {
            "type": "string",
            "description": "The URL of the page for this cinema on the website of the cinema or its chain."
          },
          "google_place_id": {
            "type": "string",
            "nullable": true,
            "description": "The Google Maps place ID of the cinema. Null if we do not know it."
          },
          "closed": {
            "type": "boolean",
            "description": "Whether the cinema is permanently closed."
          },
          "country": {
            "$ref": "#/components/schemas/CountryEnum"
          },
          "currency": {
            "$ref": "#/components/schemas/CurrencyCode"
          }
        },
        "additionalProperties": true,
        "example": {
          "id": 495,
          "chain": "odeon_gb",
          "name": "London West End",
          "address": "38 Leicester Square, London, WC2H 7DX",
          "latitude": 51.5104,
          "longitude": -0.1293,
          "link": "https://www.odeon.co.uk/cinemas/london-west-end",
          "google_place_id": "ChIJc2nSALkEdkgRkuoJJBfzkUI",
          "closed": false,
          "country": "GB",
          "currency": "GBP"
        },
        "description": "One cinema venue."
      },
      "CinemasResponse": {
        "type": "object",
        "required": ["meta", "data"],
        "properties": {
          "meta": {
            "$ref": "#/components/schemas/MetaInfo"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Cinema"
            },
            "description": "The cinemas on this page."
          }
        },
        "example": {
          "meta": {
            "page": 1,
            "per_page": 20,
            "total_count": 562
          },
          "data": [
            {
              "id": 495,
              "chain": "odeon_gb",
              "name": "London West End",
              "address": "38 Leicester Square, London, WC2H 7DX",
              "latitude": 51.5104,
              "longitude": -0.1293,
              "link": "https://www.odeon.co.uk/cinemas/london-west-end",
              "google_place_id": "ChIJc2nSALkEdkgRkuoJJBfzkUI",
              "closed": false,
              "country": "GB",
              "currency": "GBP"
            }
          ]
        },
        "description": "A page of cinemas."
      },
      "Chain": {
        "type": "object",
        "required": ["id", "name", "cinemas_count"],
        "properties": {
          "id": {
            "$ref": "#/components/schemas/ChainEnum"
          },
          "name": {
            "type": "string",
            "description": "The name of the chain, for example \"Picturehouses\"."
          },
          "cinemas_count": {
            "type": "integer",
            "format": "int32",
            "description": "Number of cinemas belonging to this chain in the countries the request reads."
          }
        },
        "additionalProperties": true,
        "example": {
          "id": "arc_cinema",
          "name": "Arc Cinema",
          "cinemas_count": 8
        },
        "description": "A cinema chain. A chain has one or more cinemas."
      },
      "ChainsResponse": {
        "type": "object",
        "required": ["meta", "data"],
        "properties": {
          "meta": {
            "$ref": "#/components/schemas/MetaInfo"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Chain"
            },
            "description": "The chains."
          }
        },
        "example": {
          "meta": {
            "total_count": 51
          },
          "data": [
            {
              "id": "arc_cinema",
              "name": "Arc Cinema",
              "cinemas_count": 8
            }
          ]
        },
        "description": "All the chains in the countries that the request reads."
      },
      "Film": {
        "type": "object",
        "required": [
          "id",
          "title",
          "original_title",
          "events_count",
          "imdb_id",
          "tmdb_id",
          "release_year",
          "runtime",
          "original_language"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32",
            "description": "Our identifier for the film."
          },
          "title": {
            "type": "string",
            "description": "The title of the film."
          },
          "original_title": {
            "type": "string",
            "description": "The title of the film in its original language."
          },
          "events_count": {
            "type": "integer",
            "format": "int32",
            "description": "Approved showtimes in the countries the request reads. In a country where your key has lite, only the showtimes at the cinemas that you chose."
          },
          "imdb_id": {
            "type": "string",
            "nullable": true,
            "description": "The IMDb identifier of the film, for example \"tt0133093\". Null if we do not know it."
          },
          "tmdb_id": {
            "type": "integer",
            "nullable": true,
            "description": "The TMDB identifier of the film. Null if we do not know it."
          },
          "release_year": {
            "type": "integer",
            "nullable": true,
            "description": "The year of the first release of the film. Null if we do not know it."
          },
          "runtime": {
            "type": "integer",
            "nullable": true,
            "description": "The length of the film, in minutes. Null if we do not know it."
          },
          "original_language": {
            "type": "string",
            "nullable": true,
            "description": "The language that the film is spoken in, as an ISO 639-3 code, for example eng or deu. Compare it with the screening_language of a showtime to see if the showtime is in the original language. Null if we do not know the language, and for a film that has no dialogue.",
            "example": "eng"
          }
        },
        "additionalProperties": true,
        "example": {
          "id": 296557755,
          "title": "Scream 7",
          "original_title": "Scream 7",
          "events_count": 17308,
          "imdb_id": "tt27047903",
          "tmdb_id": 1159559,
          "release_year": 2026,
          "runtime": 114,
          "original_language": "eng"
        },
        "description": "A film. A showtime names its films by id (see Showtime)."
      },
      "FilmsResponse": {
        "type": "object",
        "required": ["meta", "data"],
        "properties": {
          "meta": {
            "$ref": "#/components/schemas/MetaInfo"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Film"
            },
            "description": "The films on this page."
          }
        },
        "example": {
          "meta": {
            "page": 1,
            "per_page": 20,
            "total_count": 1116
          },
          "data": [
            {
              "id": 296557755,
              "title": "Scream 7",
              "original_title": "Scream 7",
              "events_count": 17308,
              "imdb_id": "tt27047903",
              "tmdb_id": 1159559,
              "release_year": 2026,
              "runtime": 114,
              "original_language": "eng"
            }
          ]
        },
        "description": "A page of films."
      },
      "Showtime": {
        "type": "object",
        "description": "price_from_amount, prices_observed_at, ticket_prices and fee_basis are Ultra only. If your key has Pro in the country of the showtime, these keys are not in the response. A missing key means that prices are not in your plan. A null or empty value means that we do not know the price. One response can have both. Some cinemas show the price only after you select a seat. We cannot get these prices, so price_from_amount is null for those showtimes.",
        "required": [
          "id",
          "cinema_id",
          "film_ids",
          "showing_at",
          "booking_link",
          "film_page_link",
          "sold_out",
          "last_seen_at",
          "chain",
          "latitude",
          "longitude",
          "on_sale_from",
          "on_sale_from_verified",
          "auditorium",
          "attribute_codes",
          "screening_language",
          "subtitle_language",
          "country",
          "currency"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32",
            "description": "Our identifier for the showtime. The API stops serving a showtime when it starts, or earlier if the cinema stops listing it."
          },
          "cinema_id": {
            "type": "integer",
            "format": "int32",
            "description": "The id of the cinema that shows the showtime (see Cinema)."
          },
          "film_ids": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int32"
            },
            "minItems": 1,
            "description": "The films this showtime screens, in the order the cinema bills them. A single film has one id; a double bill or other programme lists each of its films. Each id can be looked up with GET /films/{id}."
          },
          "showing_at": {
            "type": "string",
            "format": "date-time",
            "description": "Local time at the cinema, as ISO 8601 with the UTC offset of the cinema on that date. In the UK and Ireland, the offset is +00:00 in winter and +01:00 in summer."
          },
          "sold_out": {
            "type": "boolean",
            "description": "True if the cinema shows the showtime as sold out."
          },
          "last_seen_at": {
            "type": "string",
            "format": "date-time",
            "description": "The time our last crawl saw this showtime at the cinema, as ISO 8601 with its UTC offset (see showing_at). If we do not see a showtime for 48 hours, it is not in the API. If our crawl sees no showtimes at a cinema, we keep the showtimes of that cinema for 2 more days.",
            "example": "2026-10-09T07:15:00+01:00"
          },
          "booking_link": {
            "type": "string",
            "nullable": true,
            "description": "Direct link to book this performance. Null when online booking is not available, and after the cinema stops online sales for the performance. Then use film_page_link."
          },
          "film_page_link": {
            "type": "string",
            "nullable": true,
            "description": "The cinema's page for this film, where available. May provide film information and ticketing, and can be used as a fallback when booking_link is null."
          },
          "chain": {
            "$ref": "#/components/schemas/ChainEnum"
          },
          "latitude": {
            "type": "number",
            "format": "float",
            "description": "The latitude of the cinema, in decimal degrees (see cinema_id)."
          },
          "longitude": {
            "type": "number",
            "format": "float",
            "description": "The longitude of the cinema, in decimal degrees (see cinema_id)."
          },
          "on_sale_from": {
            "type": "string",
            "format": "date-time",
            "description": "The venue's on-sale time when known, otherwise the time the film was first observed."
          },
          "on_sale_from_verified": {
            "type": "boolean",
            "description": "Whether on_sale_from was provided by the venue."
          },
          "auditorium": {
            "type": "string",
            "nullable": true,
            "description": "The screen or auditorium name/number where the film is showing."
          },
          "attribute_codes": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            },
            "description": "Array of attribute codes describing format, accessibility, and event type (e.g., 'imax', '3d', 'audio-described'). Null on a showtime in a country where your key has lite: attribute codes are not included on that plan. An empty array means the showtime has no attributes."
          },
          "screening_language": {
            "type": "string",
            "nullable": true,
            "description": "The audio language of this showtime, as an ISO 639-3 code, for example eng or nld. If the cinema does not give it, the value is eng when the film is in English and the showtime is not dubbed. Otherwise the value is null. The value is also null in a country where your key has lite.",
            "example": "eng"
          },
          "subtitle_language": {
            "type": "string",
            "nullable": true,
            "description": "The language of the subtitles of this showtime, as an ISO 639-3 code. Use it with the subtitled attribute code: Dutch subtitles on an English film are nld. Null if the showtime has no subtitles, if the cinema does not give their language, and in a country where your key has lite.",
            "example": "nld"
          },
          "country": {
            "$ref": "#/components/schemas/CountryEnum"
          },
          "currency": {
            "$ref": "#/components/schemas/CurrencyCode"
          },
          "price_from_amount": {
            "type": "integer",
            "format": "int32",
            "nullable": true,
            "description": "Ultra only (see Showtime). The lowest price of an adult ticket for this showtime, in minor units: 1150 is £11.50 in GBP and €11.50 in EUR. Where the showtime has no adult ticket, the lowest price of a child, teen, senior, student or concession ticket. Member, family and other tickets do not count. Before you compare it between cinemas, read fee_basis. Null if we do not know a price."
          },
          "prices_observed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Ultra only (see Showtime). When we last read the prices of this showtime from the cinema. Null if we have not read them."
          },
          "ticket_prices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TicketPrice"
            },
            "description": "Ultra only (see Showtime). Each ticket type that the cinema sells online for this showtime, in the order of the cinema. Empty if we do not know the tickets. If the cinema gives only a \"from\" price, that price is in price_from_amount."
          },
          "fee_basis": {
            "type": "string",
            "enum": [
              "itemised",
              "included",
              "added_at_checkout",
              "per_order",
              "none",
              "unknown"
            ],
            "description": "Ultra only (see Showtime). How the booking fee relates to amount and price_from_amount. itemised: booking_fee gives the fee for each ticket, and amount does not include it. If a ticket has a null booking_fee, the cinema shows no fee for it. included: amount includes the fee. added_at_checkout: the checkout adds a fee for each ticket. per_order: the cinema charges a fee one time for each order. none: the cinema charges no booking fee. unknown: we do not know if amount includes a fee. For included, added_at_checkout, per_order and none, booking_fee is null. To compare prices between cinemas, add booking_fee to an itemised amount."
          }
        },
        "additionalProperties": true,
        "example": {
          "id": 24768133,
          "cinema_id": 495,
          "film_ids": [496804583],
          "showing_at": "2026-03-08T20:40:00+00:00",
          "booking_link": "https://www.odeon.co.uk/ticketing/seat-picker/?showtimeId=155-12801",
          "film_page_link": null,
          "sold_out": false,
          "last_seen_at": "2026-03-08T06:05:00+00:00",
          "chain": "odeon_gb",
          "latitude": 51.5104,
          "longitude": -0.1293,
          "on_sale_from": "2025-12-11T02:04:41+00:00",
          "on_sale_from_verified": false,
          "auditorium": "2",
          "attribute_codes": ["imax"],
          "screening_language": "eng",
          "subtitle_language": null,
          "country": "GB",
          "currency": "GBP",
          "price_from_amount": 1049,
          "prices_observed_at": "2026-03-08T04:12:31+00:00",
          "ticket_prices": [
            {
              "name": "Adult",
              "category": "adult",
              "amount": 1349,
              "booking_fee": 95,
              "seat_area": null
            },
            {
              "name": "Child",
              "category": "child",
              "amount": 1049,
              "booking_fee": 95,
              "seat_area": null
            }
          ],
          "fee_basis": "itemised"
        }
      },
      "ShowtimesResponse": {
        "type": "object",
        "description": "Showtimes with pagination metadata. In cursor mode `meta` carries `next_cursor` and omits `page`.",
        "required": ["meta", "data"],
        "properties": {
          "meta": {
            "$ref": "#/components/schemas/MetaInfo"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Showtime"
            },
            "description": "The showtimes on this page."
          }
        },
        "example": {
          "meta": {
            "page": 1,
            "per_page": 20,
            "total_count": 156310
          },
          "data": [
            {
              "id": 24768133,
              "cinema_id": 495,
              "film_ids": [496804583],
              "showing_at": "2026-03-08T20:40:00+00:00",
              "booking_link": "https://www.odeon.co.uk/ticketing/seat-picker/?showtimeId=155-12801",
              "film_page_link": null,
              "sold_out": false,
              "last_seen_at": "2026-03-08T06:05:00+00:00",
              "chain": "odeon_gb",
              "latitude": 51.5104,
              "longitude": -0.1293,
              "on_sale_from": "2025-12-11T02:04:41+00:00",
              "on_sale_from_verified": false,
              "auditorium": "2",
              "attribute_codes": ["imax"],
              "screening_language": "eng",
              "subtitle_language": null,
              "country": "GB",
              "currency": "GBP"
            },
            {
              "id": 28324938,
              "cinema_id": 1231,
              "film_ids": [579248882],
              "showing_at": "2026-08-20T20:00:00+01:00",
              "booking_link": null,
              "film_page_link": "https://lyntoncinema.co.uk/movie/details/69a99274a0b75565827e2f43",
              "sold_out": false,
              "last_seen_at": "2026-08-20T07:42:00+01:00",
              "chain": "lynton_cinema",
              "latitude": 51.230407,
              "longitude": -3.83687,
              "on_sale_from": "2026-08-19T22:07:26+01:00",
              "on_sale_from_verified": false,
              "auditorium": null,
              "attribute_codes": [],
              "screening_language": "eng",
              "subtitle_language": null,
              "country": "GB",
              "currency": "GBP"
            }
          ]
        }
      },
      "Attribute": {
        "type": "object",
        "required": ["id", "title", "description", "category"],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the attribute (e.g., 'imax', '3d', 'audio-described')."
          },
          "title": {
            "type": "string",
            "description": "Human-readable title (e.g., 'IMAX', '3D', 'Audio Described')."
          },
          "description": {
            "type": "string",
            "description": "Description of what the attribute means."
          },
          "category": {
            "type": "string",
            "enum": ["accessibility", "event", "format"],
            "description": "Category of the attribute."
          }
        },
        "description": "A feature of a showtime, for example IMAX or subtitles. A showtime gives its attributes by id in attribute_codes.",
        "example": {
          "id": "imax",
          "title": "IMAX",
          "description": "Large-format IMAX presentation",
          "category": "format"
        }
      },
      "AttributesResponse": {
        "type": "object",
        "required": ["meta", "data"],
        "properties": {
          "meta": {
            "$ref": "#/components/schemas/MetaInfo"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Attribute"
            },
            "description": "The attributes."
          }
        },
        "example": {
          "meta": {
            "total_count": 43
          },
          "data": [
            {
              "id": "imax",
              "title": "IMAX",
              "description": "Large-format IMAX presentation",
              "category": "format"
            }
          ]
        },
        "description": "All the attributes that a showtime can have."
      },
      "APIError": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "format": "int32",
            "description": "The HTTP status code of the response."
          },
          "message": {
            "type": "string",
            "description": "What went wrong, in English."
          }
        },
        "description": "The body of an error response.",
        "example": {
          "status": 404,
          "message": "Not found"
        }
      },
      "Country": {
        "type": "object",
        "required": ["iso_code", "name", "is_access_granted", "tier"],
        "properties": {
          "iso_code": {
            "$ref": "#/components/schemas/CountryEnum"
          },
          "name": {
            "type": "string",
            "description": "The name of the country, in English."
          },
          "is_access_granted": {
            "type": "boolean",
            "description": "Whether your key includes this country."
          },
          "tier": {
            "type": "string",
            "enum": ["lite", "pro", "ultra", null],
            "nullable": true,
            "description": "Your key's plan in this country. On lite, the API serves only the cinemas that you chose, with their showtimes and films, and its showtimes carry no prices and a null attribute_codes. On ultra, its showtimes carry price_from_amount, prices_observed_at, ticket_prices and fee_basis. On pro, they leave those keys out. Null where is_access_granted is false."
          }
        },
        "additionalProperties": true,
        "example": {
          "iso_code": "IE",
          "name": "Ireland",
          "is_access_granted": true,
          "tier": "ultra"
        },
        "description": "A country that the API serves, and the access that your key has to it."
      },
      "CountriesResponse": {
        "type": "object",
        "required": ["meta", "data"],
        "properties": {
          "meta": {
            "$ref": "#/components/schemas/MetaInfo"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Country"
            },
            "description": "The countries."
          }
        },
        "example": {
          "meta": {
            "total_count": 2
          },
          "data": [
            {
              "iso_code": "GB",
              "name": "United Kingdom",
              "is_access_granted": true,
              "tier": "ultra"
            },
            {
              "iso_code": "IE",
              "name": "Ireland",
              "is_access_granted": false,
              "tier": null
            }
          ]
        },
        "description": "All the countries that the API serves."
      },
      "TicketPrice": {
        "type": "object",
        "required": ["name", "category", "amount", "booking_fee", "seat_area"],
        "properties": {
          "name": {
            "type": "string",
            "description": "The ticket type as the cinema names it, verbatim: \"Adult\", \"Snr Citizen\", \"Over 60s\"."
          },
          "category": {
            "type": "string",
            "enum": [
              "adult",
              "child",
              "teen",
              "senior",
              "student",
              "concession",
              "member",
              "family",
              "other"
            ],
            "description": "Our category for this ticket type, the same at all cinemas: for example, \"Snr Citizen\" and \"Over 60s\" are both senior. name is the cinema's own label. A later release can change the category of a ticket type. member, family and other tickets do not count towards price_from_amount."
          },
          "amount": {
            "type": "integer",
            "format": "int32",
            "description": "The price that the cinema shows for this ticket type, in minor units of the showtime's currency. If booking_fee has a value, amount does not include it. If booking_fee is null, fee_basis tells you if amount includes a fee. A family or package ticket usually gives the price for all its seats, but some cinemas give the price for one seat. The ticket does not say how many seats it covers."
          },
          "booking_fee": {
            "type": "integer",
            "format": "int32",
            "nullable": true,
            "description": "The booking fee that the cinema shows for this ticket type, in minor units of the showtime's currency. It is for the same unit as amount: for example, the whole family ticket, or one seat. Null if the cinema shows no fee for this ticket. Null does not mean that there is no fee (see fee_basis)."
          },
          "seat_area": {
            "type": "string",
            "nullable": true,
            "description": "The cinema's name for the seating area of this price, for example \"Recliner\" or \"Premier\". Null if the cinema gives no area. Also null if all tickets at the showtime have the same price-band code, such as \"Band A\" or \"All\". That code does not tell you where you sit. We keep two or more band codes, because they tell the prices apart."
          }
        },
        "additionalProperties": true,
        "example": {
          "name": "Adult",
          "category": "adult",
          "amount": 1349,
          "booking_fee": 95,
          "seat_area": null
        },
        "description": "One ticket type at a showtime, and its price. Ultra only (see Showtime)."
      }
    },
    "responses": {
      "UnauthorizedError": {
        "description": "Unauthorized – the request requires valid authentication.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/APIError"
            },
            "example": {
              "status": 401,
              "message": "Unauthorized"
            }
          }
        }
      },
      "ForbiddenError": {
        "description": "Forbidden – authentication succeeded but access is denied (e.g., expired subscription, or a country your key does not include).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/APIError"
            },
            "example": {
              "status": 403,
              "message": "Your subscription has expired. Please visit https://uk-cinema-api.co.uk/pricing"
            }
          }
        }
      },
      "RateLimitError": {
        "description": "Too Many Requests – the limit is 5 requests per second for a Pro key. A key with Ultra in one or more countries has 20. A key with Lite in all its countries has 1, and 1000 requests each day. The day starts at 00:00 UTC. The limit is for the key, not for each country. The error message gives the limit that applied.",
        "headers": {
          "Retry-After": {
            "description": "Number of seconds to wait before making another request.",
            "schema": {
              "type": "integer",
              "example": 1
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/APIError"
            },
            "example": {
              "status": 429,
              "message": "Rate limit exceeded. Maximum 5 requests per second."
            }
          }
        }
      },
      "NotFoundError": {
        "description": "Not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/APIError"
            },
            "example": {
              "status": 404,
              "message": "Not found"
            }
          }
        }
      },
      "InternalServerError": {
        "description": "Internal Server Error – something went wrong on our end.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/APIError"
            },
            "example": {
              "status": 500,
              "message": "Internal server error"
            }
          }
        }
      },
      "BadRequestError": {
        "description": "Bad request – e.g. an invalid cursor, a country the API does not serve, a filter that is not valid, or a query parameter that the endpoint does not have. The message names the parameter.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/APIError"
            },
            "example": {
              "status": 400,
              "message": "Invalid cursor"
            }
          }
        }
      }
    }
  }
}
