Contents

UK Cinema API documentation

Version 4.0.0 · https://uk-cinema-api.co.uk/api/v4

The UK Cinema API gives you showtimes, cinemas and films across the UK and Ireland, with ticket pricing for UK and Irish showtimes on the Ultra plan. It's a REST API with predictable, resource-oriented URLs, JSON responses and standard HTTP status codes.

This page documents v4. v3 remains available for existing UK integrations. Every endpoint, with its parameters, is in the endpoint reference, and every field in Schemas.


Quick start

To check your token works, list the films showing in cinemas. Replace YOUR_API_TOKEN with one of your tokens (see Authentication):

The response lists the films in data, 20 to a page, with pagination details in meta. This is an illustration, cut to one film, from 3 November 2026. Your counts and films will differ:

Response
{
  "meta": {
    "page": 1,
    "per_page": 20,
    "total_count": 2089
  },
  "data": [
    {
      "id": 89350,
      "title": "The Matrix",
      "original_title": "The Matrix",
      "events_count": 2,
      "imdb_id": "tt0133093",
      "tmdb_id": 603,
      "release_year": 1999,
      "runtime": 136,
      "original_language": "eng"
    }
  ]
}

Authentication

The API uses API tokens to authenticate requests. You can view and manage your tokens on the API tokens page.

Your API tokens give access to your plan, so keep them secure. Don't share them in publicly accessible places, such as GitHub.

Send your token as a bearer token in the Authorization header:

Authorization: Bearer YOUR_API_TOKEN

Requests without a valid token fail with 401 Unauthorized.


Examples

Every request needs your API token (see Authentication). Lists come in pages of 20 unless you send items (see Pagination).

A cinema's programme for the week

Each cinema has an id. List the UK's cinemas, and keep the IDs of the ones you want. To list one chain's, use /chains/{id}/cinemas:

That's the first 100. Page through the rest (see Pagination). Showcase Bristol Avonmeads is 330. Ask for its showtimes in the coming week:

Then get each film once with /films/{id}, or ask /films?cinema_id=330 for all of them.

If you have a chain's own ID for a cinema or a showtime, look it up with /cinemas/{chain}/external/{external_id} or /showtimes/{chain}/external/{external_id}.

Retrieve every showtime

To retrieve every showtime, use cursor pagination rather than page numbers.

  1. Request /showtimes?items=100&cursor= to get the first page.
  2. Use the returned meta.next_cursor to request the next page.
  3. Repeat until meta.next_cursor is null.

Cursor pagination remains stable when showtimes are added or removed during the process. However, if a showtime's showing_at changes, it may appear twice or be missed.

We update showtimes overnight, so we recommend fetching a fresh copy each morning.

Every showtime of a film

Search for the film by its title. A title can match several films, so choose yours by release_year, runtime, tmdb_id or imdb_id, not by its place in the list:

On 3 November 2026, these were the first three:

Response
{
  "meta": {
    "page": 1,
    "per_page": 3,
    "total_count": 29
  },
  "data": [
    {
      "id": 383865,
      "title": "Wildwood",
      "original_title": "Wildwood",
      "events_count": 7238,
      "imdb_id": "tt2056785",
      "tmdb_id": 791523,
      "release_year": 2026,
      "runtime": 130,
      "original_language": "eng"
    },
    {
      "id": 579710649,
      "title": "Wildwood Nights",
      "original_title": "Wildwood Nights",
      "events_count": 0,
      "imdb_id": null,
      "tmdb_id": 1722901,
      "release_year": 1990,
      "runtime": 29,
      "original_language": "eng"
    },
    {
      "id": 579691715,
      "title": "Wildwood",
      "original_title": "Wildwood",
      "events_count": 0,
      "imdb_id": "tt3611258",
      "tmdb_id": 1702928,
      "release_year": 2014,
      "runtime": 11,
      "original_language": "eng"
    }
  ]
}
Show all 42 lines

Then ask for the 2026 film's showtimes by its id:

If you already have the film's TMDB ID, skip the search and ask for its showtimes directly:

Or by its IMDb ID:

A showtime can screen more than one film, such as a double bill. film_ids lists each film in the order the cinema bills them, and the film filters find the showtime by any of them.

Accessible screenings

/attributes lists every attribute code. The accessibility category has codes such as audio-described, subtitled, captioned, relaxed and dementia-friendly. Send one or more codes in attributes, and you get the showtimes that have all of them:

Each showtime it finds has relaxed among its attribute_codes. Attribute codes aren't included on Lite.

What's on near a place

Send latitude, longitude and radius_km together. Add from and to for a time window. A time without an offset is UK time. This finds what's on within 5 km of central Bristol today:

Here's an example showtime returned on 3 November 2026. Your response will contain current showtimes:

A showtime
{
  "id": 30906259,
  "cinema_id": 1037,
  "film_ids": [579320449],
  "showing_at": "2026-11-03T21:30:00+00:00",
  "sold_out": false,
  "last_seen_at": "2026-11-03T06:16:12+00:00",
  "booking_link": "https://www.odeon.co.uk/ticketing/seat-picker/?showtimeId=315-13575",
  "film_page_link": null,
  "chain": "odeon_gb",
  "latitude": 51.458805,
  "longitude": -2.585495,
  "on_sale_from": "2026-05-02T02:08:25+01:00",
  "on_sale_from_verified": false,
  "auditorium": "3",
  "attribute_codes": ["audio-described", "laser", "watchword", "closed-captioned"],
  "screening_language": "eng",
  "subtitle_language": null,
  "country": "GB",
  "currency": "GBP",
  "price_from_amount": 695,
  "prices_observed_at": "2026-11-03T12:32:48+00:00",
  "ticket_prices": [
    {
      "name": "Adult",
      "category": "adult",
      "amount": 695,
      "booking_fee": 100,
      "seat_area": "Recliner Saver"
    },
    {
      "name": "Adult",
      "category": "adult",
      "amount": 795,
      "booking_fee": 100,
      "seat_area": "Recliner Popular"
    },
    {
      "name": "Extras Ticket",
      "category": "member",
      "amount": 200,
      "booking_fee": 0,
      "seat_area": "Premier Recliner"
    },
    {
      "name": "Adult",
      "category": "adult",
      "amount": 745,
      "booking_fee": 100,
      "seat_area": "Recliner"
    },
    {
      "name": "Adult",
      "category": "adult",
      "amount": 895,
      "booking_fee": 100,
      "seat_area": "Premier Recliner"
    }
  ],
  "fee_basis": "itemised"
}
Show all 61 lines

The price fields are on Ultra only (see Ticket prices). To list the cinemas rather than their showtimes, send the same three parameters to /cinemas.


Pagination

Endpoints that return films, cinemas or showtimes are paginated. Use page to choose a page, and items to set the number of results returned per page, from 1 to 100. items defaults to 20.

The response's meta object describes the page. On 3 November 2026 it was:

Response
{
  "meta": {
    "page": 2,
    "per_page": 50,
    "total_count": 2089
  }
}

/showtimes also supports cursor-based pagination, which stays consistent while showtimes are added or removed. See the API reference for details.


Countries

The API covers the United Kingdom (GB, including Northern Ireland) and Ireland (IE). Your plan determines which countries your API token can access.

By default, a request returns results from every country your plan includes. To limit a request to specific countries, pass country with one or more comma-separated codes:

Requesting a country your plan doesn't include returns 403 Forbidden, and a country the API doesn't cover returns 400 Bad Request.

Each cinema and showtime includes a country and a currency. The currency is GBP in the UK and EUR in Ireland.

To check which countries your token can access, call /countries. A country's is_access_granted is true if your plan includes it, and its tier is lite, pro or ultra, or null if your plan doesn't include it:

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

To add or remove a country, change your plan on the Billing page.


Ticket prices

Ultra adds ticket pricing to showtimes in the UK and Ireland. Plans are set per country, so pricing is only included for showtimes in countries where you subscribe to Ultra. To check your plan in each country, call /countries (see Countries).

A showtime with pricing has four more fields:

  • price_from_amount – The lowest amount among the showtime's adult tickets, or, where it has none, among its child, teen, senior, student and concession tickets, in the minor units of the showtime's currency, so 1049 is £10.49 in GBP, or €10.49 in EUR. Member, family and other tickets don't count. Where a cinema publishes only a from-price, it's the cinema's own. Whether it includes a booking fee depends on fee_basis.
  • ticket_prices – The ticket types the cinema sells online, in the order the cinema lists them. name is the cinema's own name for the ticket, and category is the UK Cinema API's category for it, the same across every cinema: one of adult, child, teen, senior, student, concession, member, family or other. amount is the price the cinema shows for the ticket, and booking_fee is the fee it shows for the ticket, if any, in the same minor units. seat_area names the seating area, such as Recliner, where the cinema prices areas differently.
  • fee_basis – How booking fees apply to this showtime's ticket prices, including price_from_amount:
    • itemised – booking_fee gives each ticket's fee, and amount doesn't include it.
    • included – amount includes the fee.
    • added_at_checkout – The checkout adds a fee for each ticket.
    • per_order – The cinema charges a fee once per order.
    • none – The cinema charges no booking fee.
    • unknown – We don't know whether amount includes a fee.

    Under included, added_at_checkout, per_order and none, booking_fee is null.

  • prices_observed_at – When we last successfully read these prices from the cinema, or null if we never have.
Response
{
  "id": 30892783,
  "cinema_id": 495,
  "film_ids": [355995],
  "showing_at": "2026-11-04T20:10:00+00:00",
  "sold_out": false,
  "last_seen_at": "2026-11-03T06:15:50+00:00",
  "booking_link": "https://www.odeon.co.uk/ticketing/seat-picker/?showtimeId=155-15183",
  "film_page_link": null,
  "chain": "odeon_gb",
  "latitude": 51.509922,
  "longitude": -0.13018,
  "on_sale_from": "2026-03-26T02:00:27+00:00",
  "on_sale_from_verified": false,
  "auditorium": "2",
  "attribute_codes": ["audio-described", "laser", "captioned"],
  "screening_language": "eng",
  "subtitle_language": null,
  "country": "GB",
  "currency": "GBP",
  "price_from_amount": 1850,
  "prices_observed_at": "2026-11-02T06:47:50+00:00",
  "ticket_prices": [
    {
      "name": "Adult",
      "category": "adult",
      "amount": 1850,
      "booking_fee": 100,
      "seat_area": "Recliner Saver"
    },
    {
      "name": "Adult",
      "category": "adult",
      "amount": 2250,
      "booking_fee": 100,
      "seat_area": "Recliner Popular"
    },
    {
      "name": "Adult",
      "category": "adult",
      "amount": 1900,
      "booking_fee": 100,
      "seat_area": "Recliner"
    }
  ],
  "fee_basis": "itemised"
}
Show all 47 lines

In this example, fee_basis is itemised, so the cheapest adult ticket, in Recliner Saver, is £18.50 plus its £1.00 booking fee, £19.50 in all. The from-price is that £18.50, before its fee. For itemised prices, add booking_fee to amount to include the known per-ticket fee. For included prices, the fee is already included. For none, there's no booking fee to add. With added_at_checkout, per_order or unknown, the final checkout cost may be higher than the ticket price, so those prices don't compare directly with the others.

Under itemised, price_from_amount is before fees. If its ticket has a fee, the fee is in that ticket's booking_fee. A from-price that a cinema publishes without a ticket list is never itemised. It has the chain's stated basis, or unknown.

Family and package tickets need care when you compare prices. One usually gives the price for all its seats, but some cinemas give the price for one seat, and the ticket doesn't say how many seats it covers.

Categories are the UK Cinema API's, so "Snr Citizen" at one cinema and "Over 60s" at another are both senior. A later release can move a ticket to a better-fitting category, while name always stays the cinema's own.

Pricing isn't available for a showtime when price_from_amount is null and ticket_prices is empty. Some cinemas show the price only after you select a seat, so their showtimes have no pricing. Some cinemas publish only a from-price, so price_from_amount is set and ticket_prices is empty. A showtime whose only tickets are member, family or other tickets lists them in ticket_prices, with a null price_from_amount. In a country where your plan includes Pro rather than Ultra, the four fields are left out entirely.

A null booking_fee doesn't necessarily mean there's no booking fee. Check fee_basis to see how fees are handled. A null seat_area means the cinema gives no seating area, or every ticket at the showtime has the same price-band code, such as Band A, which doesn't say where you sit.

To add ticket pricing, choose Ultra on the Pricing page, or change your plan on the Billing page if you already subscribe. The API reference describes every field in full.


Dates and times

Times are ISO 8601 strings in local time at the cinema, with their offset from UTC. For example, 2026-10-03T19:30:00+01:00 is 7:30pm at the cinema, and 18:30 UTC.

The UK and Ireland keep the same time, so the offset is +01:00 in summer and +00:00 in winter in both.


Rate limits

Your rate limit depends on your plan. Each API token can make up to 5 requests per second, or 20 requests per second if your plan includes Ultra in any country. If you exceed the limit, the API returns 429 Too Many Requests, with a Retry-After header that gives the number of seconds to wait before you retry. The error's message gives the limit that applied.

A Lite plan has 1 request per second and 1,000 requests a day. The day's count starts again at 00:00 UTC, and the Retry-After header gives the seconds until then. A Lite token reads only the cinemas you chose, and only on v4: v1, v2 and v3 return 403 Forbidden.


Errors

The API uses conventional HTTP response codes to indicate whether a request succeeded. Codes in the 2xx range indicate success. Codes in the 4xx range indicate an error with the request, such as a missing token or a country your plan doesn't include. Codes in the 5xx range indicate an error on our side (these are rare).

  • 200 OK – Everything worked as expected.
  • 400 Bad Request – A parameter is invalid, such as a country the API doesn't cover.
  • 401 Unauthorized – No valid API token was provided.
  • 403 Forbidden – The token is valid but doesn't have access. Your subscription might have ended, or the request names a country your plan doesn't include.
  • 404 Not Found – The requested resource doesn't exist.
  • 429 Too Many Requests – Too many requests hit the API too quickly.
  • 500 Internal Server Error – Something went wrong on our side.

Error responses include the status and a human-readable message:

Response
{
  "message": "Unknown country FR. v4 serves GB, IE.",
  "status": 400
}

Upgrading from v3

v3 remains available for existing UK integrations. v4 adds multi-country support, including Ireland, along with several backward-incompatible changes. Ireland is only available through v4. To upgrade, change /api/v3/ to /api/v4/ in your requests, and update your integration for these changes:

  • Showtimes return film_ids, an array of film IDs in the order the cinema bills them, instead of film_id. A double bill includes every film it shows.
  • Showtimes rename movie_page_link to film_page_link.
  • Cinemas and showtimes include country and currency.

The v3 documentation remains available.


Support

If you have questions or want to request a feature, email [email protected].