Cinema showtimes API

Documentation · v1 (0.1.0)

Cinema showtimes in France and the United States (country filter). Authentication with an API key (Authorization: Bearer ac_live_…), created from the dashboard. Times are wall-clock times in each cinema's time zone (cinema.timezone).

Movie titles, synopses, genres and TMDB ids come from TMDB once the movie is matched (tmdbId set); rawTitle keeps the title as published by the cinema. This product uses the TMDB API but is not endorsed or certified by TMDB.

Use of the API is subject to the terms of use: one account per client, API keys kept server-side, no resale or bulk redistribution of the data, no working around the quotas.

Examples

Every call needs your API key. Lists are paginated (limit, cursor), and without date or from showtimes start from now, in each cinema's local time.

Every showtime of a film in France, from its Allociné or TMDB id

The Allociné id is the number in the film page URL (allocine.fr/film/fichefilm_gen_cfilm=1000013045.html for L'Odyssée); the TMDB id is the one in themoviedb.org/movie/1368337. You do not need our movie id:

Terminal
curl "https://api.api-cinema.com/v1/showtimes?allocine_id=1000013045&country=FR&limit=100" -H "Authorization: Bearer ac_live_…"
curl "https://api.api-cinema.com/v1/showtimes?tmdb_id=1368337&country=FR&limit=100" -H "Authorization: Bearer ac_live_…"

To get our movie ids (for /v1/movies/{id}), look the film up by the same ids:

Terminal
curl "https://api.api-cinema.com/v1/movies?allocine_id=1000013045" -H "Authorization: Bearer ac_live_…"
# → two rows, one per country, same tmdbId 1368337:
#   { "id": "065ec55d-…", "title": "L'Odyssée", "allocineId": "1000013045", "tmdbId": 1368337 }
#   { "id": "e125e88f-…", "title": "The Odyssey", "allocineId": null, "tmdbId": 1368337 }

Every showtime of a film, from its name

No Allociné or TMDB id at hand? Search the film by name first, then read its showtimes:

Terminal
# 1. find the film among the movies showing in France
curl "https://api.api-cinema.com/v1/movies?q=spider&playing=true&country=FR" -H "Authorization: Bearer ac_live_…"
# → { "id": "a1…", "title": "Spider-Man : Brand New Day", "rawTitle": "SPIDER-MAN : BRAND NEW DAY", "tmdbId": 969681 }
#   { "id": "b2…", "title": "Spider-Man : Brand New Day", "rawTitle": "SPIDERMAN", "tmdbId": 969681 }
#   { "id": "c3…", "title": "Spider-Man : New Generation", "rawTitle": "Spider-Man : New Generation", "tmdbId": 324857 }

# 2. pick the film, then every showtime of it (both rows above) by its tmdbId
curl "https://api.api-cinema.com/v1/showtimes?tmdb_id=969681&country=FR&limit=100" -H "Authorization: Bearer ac_live_…"

If the film you picked has no tmdbId yet (titleSource: "raw"), read the showtimes of each row with GET /v1/movies/{id}/showtimes instead.

How the title search (q) works

  • Your text and the titles are compared after the same normalization: lower case, accents and punctuation removed, a leading article dropped (le, la, les, l', un, une, des, the, a, an). L'Odyssée, l odyssee and ODYSSEE are the same search.
  • It is a contains match on the title as published by the cinema (rawTitle), not on the TMDB title nor the original title: in France, q=odyssee finds L'Odyssée but q=the odyssey finds nothing (US rows carry the English title).
  • Cinemas write titles their own way (SPIDERMAN, SPIDER-MAN : BRAND NEW DAY): search a short, distinctive word (spider) rather than the full title.
  • Several films can match (q=odyssee also returns 2001 : L'Odyssée de l'espace), and one film can come as several rows (one per published title or per country): pick by title, year or tmdbId, never blindly the first result, then continue with tmdb_id.
  • Add playing=true to keep only films with upcoming showtimes, and country to stay in one country. Results are sorted by title and paginated (limit, offset).

What's on in New York

city is an exact match ("New York" leaves out "Brooklyn"): search around a point instead. Times Square, 5 km:

Terminal
curl "https://api.api-cinema.com/v1/showtimes?country=US&near=40.758,-73.9855&radius_km=5&limit=200" -H "Authorization: Bearer ac_live_…"

Add date=2026-09-25 for one day only; each showtime carries cinema.distanceKm. The cinemas themselves, nearest first:

Terminal
curl "https://api.api-cinema.com/v1/cinemas?country=US&near=40.758,-73.9855&radius_km=5" -H "Authorization: Bearer ac_live_…"

Tonight near me, in original version with subtitles

The same search as a JSON body (POST …/search), easier to build from code:

JavaScript
const res = await fetch('https://api.api-cinema.com/v1/showtimes/search', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer ac_live_…', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    near: { lat: 45.764, lng: 4.8357, radiusKm: 3 }, // Lyon city centre
    from: '2026-09-25T18:00', // tonight, local time of each cinema
    to: '2026-09-25T23:59',
    version: 'VOST',
    include: ['movie', 'cinema'],
    limit: 100,
  }),
})
const { data } = await res.json()
for (const s of data)
  console.log(s.startsAt.slice(11, 16), s.movie.title, '—', s.cinema.name, `${s.cinema.distanceKm} km`)

A cinema's programme for the week

Find the cinema by name, then read its showtimes (the path takes its id or its slug):

Terminal
curl "https://api.api-cinema.com/v1/cinemas?q=champo&country=FR" -H "Authorization: Bearer ac_live_…"
# → { "id": "cnc_8422", "slug": "le-champo-paris-5e-arrondissement", "name": "Le Champo", … }
curl "https://api.api-cinema.com/v1/cinemas/le-champo-paris-5e-arrondissement/showtimes?from=2026-09-24&to=2026-09-30" -H "Authorization: Bearer ac_live_…"

Without from / to, a cinema's showtimes default to today. Past showtimes are kept 7 days.

To pick from the cinemas of one postal code (or ZIP code in the US), pass zip_code; its first digits are enough, zip_code=69 lists a whole French department:

Terminal
curl "https://api.api-cinema.com/v1/cinemas?zip_code=75005" -H "Authorization: Bearer ac_live_…"

Films showing now in a country

Terminal
curl "https://api.api-cinema.com/v1/movies?playing=true&country=FR&limit=100" -H "Authorization: Bearer ac_live_…"
curl "https://api.api-cinema.com/v1/movies?q=odyssey&playing=true&country=US" -H "Authorization: Bearer ac_live_…"

Group films by tmdbId: the same film has one id per country, and one per published title until it is matched on TMDB.

Keep a local copy up to date

Import everything once, then only fetch changes with updated_since: see Incremental sync below.

What's new

2026-10-30 — Find cinemas by postal / ZIP code

New filter on /v1/cinemas: zip_code (zipCode in the body of POST /v1/cinemas/search, and on the MCP tool search_cinemas). It keeps cinemas whose postalCode starts with the given digits, 2 to 5: zip_code=75005 for one code, zip_code=75 for a whole French department, zip_code=100 for a range of US ZIP codes. It combines with the other filters. Cinemas without a known postalCode are left out.

What to do if you already use the API

  • Nothing to do. If you turned a postal code into a city or a point to search, you can pass it directly.

2026-10-29 — One account per client: 403 account_suspended

When an account is signed up from a connection that already has one, its API access is suspended: every request answers 403 with the code account_suspended, and the account receives an e-mail. The terms of use allow one account per client (section 2); the account created first is not affected.

What to do if you already use the API

  • Nothing to do for a single account. If several people or companies share one connection (a shared office, for instance), write to support@api-cinema.com.

2026-10-22 — Free plan: 150 requests a week, non-commercial use

The Free plan now allows 150 requests a week (was 250), all its API keys together, and is reserved for trials and non-commercial projects (terms of use, section 4). A website or app that earns revenue or serves a business, a cinema’s website included, needs a paid plan (Starter, €12 a month, 10,000 requests a week). Paid plans and accounts on a quote are unchanged.

What to do if you already use the API

  • If you are on the Free plan, check your weekly use in the dashboard: past 150 requests the API answers 429 with weekly_quota_exceeded until Monday 00:00 UTC.
  • If your use is commercial, move to a paid plan from the dashboard.

2026-10-22 — city=Paris finds every arrondissement

Paris cinemas are filed by arrondissement ("city": "Paris 5e Arrondissement"), so city=Paris used to return nothing. It now matches Paris and all its arrondissements, on /v1/cinemas, /v1/showtimes and their search variants; an arrondissement (city=Paris 5e Arrondissement) still works on its own. Every other city keeps an exact match.

What to do if you already use the API

  • If you worked around it by listing the arrondissements or by searching around a point, you can switch to city=Paris.

2026-10-19 — One week of past showtimes

Past showtimes are now kept 7 days: a date or from earlier than a week ago returns nothing for the days before. Upcoming showtimes and updated_since sync are unchanged; past showtimes simply drop out after a week, without a removal entry.

What to do if you already use the API

  • If you need a longer history, store the showtimes on your side as you import them.

2026-09-27 — Faster responses, new database

The API now runs on PostgreSQL. Heavy queries are much faster (films showing in a country, all the showtimes of a film: 2 to 7 times), the others as fast or faster. Responses are unchanged, with two small improvements: q searches now ignore the case of accented letters too (an upper-case accented name finds its lower-case spelling), and films sharing a title are always listed in the same order. A revoked API key is now refused within a minute rather than immediately.

2026-09-24 — Terms of use

The API now has published terms of use, linked at the top of this page and from the OpenAPI info.termsOfService. They spell out what was already expected: one account per client, API keys kept server-side and never shared, no resale or bulk redistribution of the data, and no working around the quotas with extra keys or accounts.

What to do if you already use the API

  • Check that your API keys are only used server-side (never in a web page or mobile app).
  • If you need more volume, ask support rather than adding keys or accounts.

2026-09-24 — Weekly quota per account

An account can now have a weekly request quota (Monday 00:00 UTC → Sunday, all its API keys together). When it has one, responses carry X-Weekly-Quota-Limit, X-Weekly-Quota-Remaining and X-Weekly-Quota-Reset, and past the quota the API answers 429 with the code weekly_quota_exceeded. Accounts without a weekly quota see no change.

What to do if you already use the API

  • If you handle 429 responses, also expect the weekly_quota_exceeded code: its Retry-After can be several days.

2026-09-23 — JSON search (POST)

Every list with filters now has a POST …/search twin taking its filters in a JSON body, with typed values and camelCase names (tmdbId, near: { lat, lng, radiusKm }, include: ["movie"]…): no more long URLs to build. Same response, same pagination (cursor), same quota; unknown keys are refused (400).

GET (URL parameters) POST (JSON body)
/v1/showtimes /v1/showtimes/search
/v1/cinemas /v1/cinemas/search
/v1/movies /v1/movies/search
/v1/cinemas/{id}/showtimes /v1/cinemas/{id}/showtimes/search
/v1/movies/{id}/showtimes /v1/movies/{id}/showtimes/search

2026-09-23 — Showtimes by TMDB or Allociné id

/v1/showtimes and /v1/movies accept tmdb_id and allocine_id (the id in allocine.fr/film/fichefilm_gen_cfilm=<id>.html): every showtime of a film, whatever the title each cinema publishes. allocine_id also finds showtimes read from other sources once the film is matched on TMDB. Movies expose a new allocineId field (set when the movie was read from Allociné).

2026-09-23 — Cinemas in the United States

The API now covers cinemas in the United States as well as France. Without a country parameter, lists return both countries: /v1/cinemas, /v1/showtimes, /v1/movies and /v1/movies/{id}/showtimes include US cinemas and showtimes.

  • New country filter (FR or US) on these four lists, and in the MCP tools.
  • New cinema fields: country and timezone (IANA zone, e.g. America/New_York). In the US, region holds the state code (NY) and postalCode the ZIP code.
  • startsAt is still a local time without offset, but it is now the cinema's local time (cinema.timezone), no longer always Europe/Paris.
  • Without date or from, "now" and "today" are evaluated in each cinema's time zone. date, from and to are read in each cinema's local time.
  • Outside France, cncId, inseeCode, department and artEtEssai are null.
  • US showtimes: version is VO (original version) or VOST (subtitled), UNKNOWN for a dubbed screening.
  • Movies of US cinemas have their own rows, separate from French ones, with TMDB title, synopsis and genres in English. A film shown in both countries therefore has one id per country and the same tmdbId.

What to do if you already use the API

  • To keep exactly your current scope, add country=FR to your list calls (cinemas, showtimes, movies, showtimes of a movie). Calls by id (/v1/cinemas/{id}, /v1/movies/{id}) do not change.
  • To turn startsAt into an instant (UTC, display in another zone), use cinema.timezone instead of assuming Europe/Paris.
  • If your code reads cncId, inseeCode, department or artEtEssai, accept null for cinemas outside France.
  • If you group movies by film, use tmdbId rather than id or the title (one id per country).
  • If you validate country or timezone against a strict schema, add both fields.

Versions

The URL carries the major version (/v1/…); the selector at the top of the page shows the documentation of each version, the latest by default.

  • Additions (new routes, new optional parameters, new response fields) ship to every supported version without a version change: ignore fields you do not know.
  • A breaking change (another default behaviour, a removed or renamed field, a stricter validation) opens a new major version; your current version does not change.
  • A replaced version keeps being served for at least 6 months. Its responses then carry the Deprecation, Sunset (last day of service) and Link: <…>; rel="successor-version" headers.
Version Released Status
/v1 (this page) 2026-09-15 current

Full showtime import

  • Walk GET /v1/showtimes with limit=1000 and cursor (the meta.nextCursor of the previous page).
  • include picks the nested objects: movie,cinema by default, include=movie or include= (empty) for much lighter pages. movieId and cinemaId are always there: load movies and cinemas once, separately.
  • Group one film by movie.tmdbId: two cinemas publishing different titles give two movie.id for the same tmdbId. movie.titleSource is tmdb or raw; GET /v1/movies/unmatched lists showing movies still without a tmdbId.
  • cinema.programmeCheckedAt is the last successful read of the cinema's programme: past 2 days, it may be stale.
  • showtime.id is stable: a showtime keeps its id as long as its cinema, movie, time and version do not change.

Rather than a long URL, send the filters in a JSON body (camelCase names, typed values): every list has its POST …/search twin (/v1/showtimes/search, /v1/cinemas/search, /v1/movies/search, /v1/cinemas/{id}/showtimes/search, /v1/movies/{id}/showtimes/search). Response, pagination and quota are the same as with GET.

JavaScript
const res = await fetch('https://api.api-cinema.com/v1/showtimes/search', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer ac_live_…', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    country: 'FR',
    allocineId: '1000013045',
    near: { lat: 45.764, lng: 4.8357, radiusKm: 5 },
    from: '2026-09-25T18:00',
    to: '2026-09-26',
    version: 'VOST',
    include: ['movie'],
    limit: 100,
  }),
})
const { data, meta } = await res.json() // next page: same body + cursor: meta.nextCursor

Incremental sync

  1. Full import: walk GET /v1/showtimes and keep meta.syncedAt of the first page.
  2. Then: GET /v1/showtimes?updated_since=<syncedAt> (same from/to… filters) returns only the showtimes added, changed or removed since, ordered by updatedAt, with the same cursor. Keep the meta.syncedAt of its first page again.
  3. A showtime with removedAt set is no longer listed by the cinema (cancelled or withdrawn): delete it on your side. Normal lists never return a removed showtime.
  4. GET /v1/movies?updated_since=… gives the changed movies (TMDB match, title, synopsis).

syncedAt is taken a few minutes before the request: a showtime may come twice, apply changes by id. Removed showtimes are kept 30 days: past that without a sync, do a full import again.

Rate limits

Each API key has a request quota per 60-second window, set by its plan. Windows start at every full minute (hh:mm:00).

Plan Requests per minute, per key
Standard 60
Pro 600

Every authenticated response gives the key's exact count:

HTTP
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 41
X-RateLimit-Reset: 23
RateLimit-Policy: "standard";q=60;w=60
RateLimit: "standard";r=41;t=23

X-RateLimit-Remaining counts the current request; X-RateLimit-Reset is the number of seconds before the next window. The last two lines follow the IETF draft RateLimit header fields.

Past the quota, the API answers 429 Too Many Requests with Retry-After (seconds until the next window) and X-RateLimit-Remaining: 0. The body details the limit:

JSON
{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded: 60 requests per 60 s for this API key. Retry in 23 s.",
    "details": { "limit": 60, "windowSeconds": 60, "retryAfterSeconds": 23, "plan": "standard" }
  }
}

Wait for Retry-After before retrying: refused requests count in the window too. For a higher quota, contact support from the dashboard: spreading requests over several keys or accounts to get past it breaks the terms of use.

Weekly quota

Some accounts also have a weekly quota, set with your plan: a number of requests per week (Monday 00:00 UTC → Sunday), counting every API key of the account together. When your account has one, every response carries:

HTTP
X-Weekly-Quota-Limit: 10000
X-Weekly-Quota-Remaining: 8412
X-Weekly-Quota-Reset: 302400

X-Weekly-Quota-Remaining counts the current request; X-Weekly-Quota-Reset is the number of seconds until Monday 00:00 UTC. Past the quota, the API answers 429 with the code weekly_quota_exceeded and Retry-After set to the reset; refused requests do not count. Without a weekly quota, these headers are absent.

Walking every showtime

Showtime lists (/v1/showtimes, /v1/cinemas/{id}/showtimes, /v1/movies/{id}/showtimes) accept limit up to 1000. To go through everything, follow the cursor rather than offset: the order is stable (startsAt then id) and every page answers as fast as the first one.

Terminal
curl "https://api.api-cinema.com/v1/showtimes?from=2026-09-16&to=2026-09-30&limit=1000" -H "Authorization: Bearer ac_live_…"
# meta.nextCursor = "WyIyMDI2LTA5LTE2VDE0OjAwOjAwIiwiLi4uIl0"
curl "https://api.api-cinema.com/v1/showtimes?from=2026-09-16&to=2026-09-30&limit=1000&cursor=WyIyMDI2LTA5LTE2VDE0OjAwOjAwIiwiLi4uIl0" -H "Authorization: Bearer ac_live_…"

Repeat with the same filters until meta.nextCursor is null. meta.total is only computed on the first page (without a cursor). The cursor combines with neither offset nor near.

MCP server

The API is also available as an MCP server (Streamable HTTP), to query showtimes from Claude, Cursor or any compatible client. The server takes the same API key as the REST API; each tool call counts as one request and follows the key's rate limit.

Address: https://api.api-cinema.com/mcp

Claude Code

Terminal
claude mcp add --transport http api-cinema https://api.api-cinema.com/mcp --header "Authorization: Bearer ac_live_…"

Claude Desktop, Cursor and clients configured in JSON

JSON
{
  "mcpServers": {
    "api-cinema": {
      "type": "http",
      "url": "https://api.api-cinema.com/mcp",
      "headers": { "Authorization": "Bearer ac_live_…" }
    }
  }
}

Available tools (read-only, 20 results by default)

  • search_showtimes: Upcoming cinema showtimes in France and the United States, filtered by country, by film (movie_id, TMDB or Allociné id), by city, by distance around a point, by movie, by day or time range and by language version. Each result includes the movie and the cinema.
  • search_cinemas: Cinemas in France and the United States by country, city, name, postal / ZIP code, or around a point (sorted by distance, with distanceKm).
  • get_cinema: Details of one cinema (address, coordinates, screens, website, ticketing) by id or slug.
  • cinema_showtimes: Programme of one cinema, by id or slug. Defaults to today.
  • search_movies: Movies by title (accent and case insensitive). Set playing to true to keep only movies with upcoming showtimes, and country to restrict to one country.
  • movie_showtimes: Upcoming showtimes of one movie, optionally in a country, a city or around a point. Get the movie_id from search_movies.

Endpoints

Cinemas

GET /v1/cinemas

List cinemas

ParameterTypeDescription
cityquerystringOptional. Exact city name; Paris also matches its arrondissements. Example: Paris.
qquerystringOptional. Name contains. Example: champo.
zip_codequerystringOptional. Postal code (FR) or ZIP code (US) starts with: 75005 for one code, 75 for a whole French department, 100 for a range of US ZIP codes. 2 to 5 digits. Example: 75005.
activequery"true" | "false"Optional. Default true.
countryquery"FR" | "US"Optional. Only cinemas of this country (ISO 3166-1 alpha-2). Default: every country. Example: FR.
nearquerystringOptional. "lat,lng" centre point. Example: 48.8566,2.3522.
radius_kmquerynumberOptional. Radius around near, default 10. Example: 5.
limitqueryintegerOptional. Example: 50.
offsetqueryinteger | nullOptional. Example: 0.

Response: CinemaList

POST /v1/cinemas/search

Search cinemas with a JSON body

Same filters and results as GET /v1/cinemas, sent as a JSON body (typed values, camelCase names). Read-only.

JSON body: CinemaSearch · Response: CinemaList

GET /v1/cinemas/{id}

Get a cinema by id or slug

ParameterTypeDescription
id*pathstringCinema id or slug, as returned by GET /v1/cinemas (or cinemaId / cinema.id of a showtime)

Response: Cinema

GET /v1/cinemas/{id}/showtimes

Showtimes of a cinema (defaults to today)

ParameterTypeDescription
id*pathstringCinema id or slug, as returned by GET /v1/cinemas (or cinemaId / cinema.id of a showtime)
datequerystringOptional. Whole day, YYYY-MM-DD, in each cinema's local time. Example: 2026-09-15.
fromquerystringOptional. YYYY-MM-DD or YYYY-MM-DDTHH:MM, in each cinema's local time. Defaults to now in each cinema's time zone. Example: 2026-09-15T18:00.
toquerystringOptional. YYYY-MM-DD or YYYY-MM-DDTHH:MM, in each cinema's local time. Example: 2026-09-16.
versionquery"VF" | "VO" | "VOST" | "VFST" | "UNKNOWN"Optional. Example: VOST.
includequerystringOptional. Nested objects to embed, comma-separated: movie, cinema. Default movie,cinema; include= (empty) returns only movieId / cinemaId, for much lighter pages on full imports. Example: movie.
limitqueryintegerOptional. Page size, up to 1000. Example: 1000.
offsetqueryinteger | nullOptional. Rows to skip. For deep pages, walk with cursor instead. Example: 0.
cursorquerystringOptional. meta.nextCursor of the previous page. Walks the whole result set in a stable order (startsAt, id); not combinable with offset or near.

Response: ShowtimeList

POST /v1/cinemas/{id}/showtimes/search

Showtimes of a cinema with a JSON body (defaults to today)

Same filters and results as GET /v1/cinemas/{id}/showtimes, sent as a JSON body (typed values, camelCase names). Read-only.

ParameterTypeDescription
id*pathstringCinema id or slug, as returned by GET /v1/cinemas (or cinemaId / cinema.id of a showtime)

JSON body: CinemaShowtimeSearch · Response: ShowtimeList

Showtimes

GET /v1/showtimes

Search showtimes (defaults to upcoming from now)

ParameterTypeDescription
cityquerystringOptional. Exact city name; Paris also matches its arrondissements. Example: Lyon.
movie_idquerystringOptional.
tmdb_idqueryintegerOptional. The Movie Database id: every showtime of this film, whatever the title published by each cinema or the country. Example: 1368337.
allocine_idquerystringOptional. Allociné film id, as in allocine.fr/film/fichefilm_gen_cfilm=.html: every showtime of this film (also those read from other sources, once the film is matched on TMDB). Example: 1000013045.
countryquery"FR" | "US"Optional. Only cinemas of this country (ISO 3166-1 alpha-2). Default: every country. Example: FR.
nearquerystringOptional. "lat,lng" centre point. Example: 48.8566,2.3522.
radius_kmquerynumberOptional. Radius around near, default 10. Example: 5.
datequerystringOptional. Whole day, YYYY-MM-DD, in each cinema's local time. Example: 2026-09-15.
fromquerystringOptional. YYYY-MM-DD or YYYY-MM-DDTHH:MM, in each cinema's local time. Defaults to now in each cinema's time zone. Example: 2026-09-15T18:00.
toquerystringOptional. YYYY-MM-DD or YYYY-MM-DDTHH:MM, in each cinema's local time. Example: 2026-09-16.
versionquery"VF" | "VO" | "VOST" | "VFST" | "UNKNOWN"Optional. Example: VOST.
updated_sincequerystringOptional. Incremental sync: only showtimes inserted, changed or removed since this ISO 8601 instant, removed ones included (removedAt set), ordered by (updatedAt, id). Pass meta.syncedAt of the first page of your previous walk. Tombstones are kept 30 days: sync at least that often, or do a full walk. Example: 2026-09-16T03:00:00Z.
includequerystringOptional. Nested objects to embed, comma-separated: movie, cinema. Default movie,cinema; include= (empty) returns only movieId / cinemaId, for much lighter pages on full imports. Example: movie.
limitqueryintegerOptional. Page size, up to 1000. Example: 1000.
offsetqueryinteger | nullOptional. Rows to skip. For deep pages, walk with cursor instead. Example: 0.
cursorquerystringOptional. meta.nextCursor of the previous page. Walks the whole result set in a stable order (startsAt, id); not combinable with offset or near.

Response: ShowtimeList

POST /v1/showtimes/search

Search showtimes with a JSON body

Same filters and results as GET /v1/showtimes, sent as a JSON body with typed values and camelCase names instead of a long query string. Read-only: nothing is created.

JSON body: ShowtimeSearch · Response: ShowtimeList

Movies

GET /v1/movies

List movies

ParameterTypeDescription
qquerystringOptional. Title search (accent/case-insensitive). Example: dune.
playingquery"true" | "false"Optional. Only movies with upcoming showtimes (in country when given).
updated_sincequerystringOptional. Only movies changed since this ISO 8601 instant (TMDB match, alias, metadata). Example: 2026-09-16T03:00:00Z.
tmdb_idqueryintegerOptional. The Movie Database id: every showtime of this film, whatever the title published by each cinema or the country. Example: 1368337.
allocine_idquerystringOptional. Allociné film id, as in allocine.fr/film/fichefilm_gen_cfilm=.html: every showtime of this film (also those read from other sources, once the film is matched on TMDB). Example: 1000013045.
countryquery"FR" | "US"Optional. Only cinemas of this country (ISO 3166-1 alpha-2). Default: every country. Example: FR.
limitqueryintegerOptional. Example: 50.
offsetqueryinteger | nullOptional. Example: 0.

Response: MovieList

POST /v1/movies/search

Search movies with a JSON body

Same filters and results as GET /v1/movies, sent as a JSON body (typed values, camelCase names). Read-only.

JSON body: MovieSearch · Response: MovieList

GET /v1/movies/unmatched

Movies showing without a TMDB match, most programmed first

Upcoming movies whose tmdbId is still null, ordered by number of upcoming showtimes: lets you watch the TMDB matching over time.

ParameterTypeDescription
limitqueryintegerOptional. Example: 50.
offsetqueryinteger | nullOptional. Example: 0.

Response: UnmatchedMovieList

GET /v1/movies/{id}

Get a movie

ParameterTypeDescription
id*pathstringMovie id (ours), as returned by GET /v1/movies?q=…, GET /v1/movies?tmdb_id=… / ?allocine_id=…, or movieId of a showtime. A film can have several ids (one per country, or per published title until it is matched on TMDB): to get every showtime of a film from its TMDB or Allociné id, prefer GET /v1/showtimes?tmdb_id=… / ?allocine_id=…

Response: Movie

GET /v1/movies/{id}/showtimes

Showtimes of a movie (defaults to upcoming from now)

ParameterTypeDescription
id*pathstringMovie id (ours), as returned by GET /v1/movies?q=…, GET /v1/movies?tmdb_id=… / ?allocine_id=…, or movieId of a showtime. A film can have several ids (one per country, or per published title until it is matched on TMDB): to get every showtime of a film from its TMDB or Allociné id, prefer GET /v1/showtimes?tmdb_id=… / ?allocine_id=…
cityquerystringOptional. Exact city name; Paris also matches its arrondissements. Example: Paris.
countryquery"FR" | "US"Optional. Only cinemas of this country (ISO 3166-1 alpha-2). Default: every country. Example: FR.
nearquerystringOptional. "lat,lng" centre point. Example: 48.8566,2.3522.
radius_kmquerynumberOptional. Radius around near, default 10. Example: 5.
datequerystringOptional. Whole day, YYYY-MM-DD, in each cinema's local time. Example: 2026-09-15.
fromquerystringOptional. YYYY-MM-DD or YYYY-MM-DDTHH:MM, in each cinema's local time. Defaults to now in each cinema's time zone. Example: 2026-09-15T18:00.
toquerystringOptional. YYYY-MM-DD or YYYY-MM-DDTHH:MM, in each cinema's local time. Example: 2026-09-16.
versionquery"VF" | "VO" | "VOST" | "VFST" | "UNKNOWN"Optional. Example: VOST.
includequerystringOptional. Nested objects to embed, comma-separated: movie, cinema. Default movie,cinema; include= (empty) returns only movieId / cinemaId, for much lighter pages on full imports. Example: movie.
limitqueryintegerOptional. Page size, up to 1000. Example: 1000.
offsetqueryinteger | nullOptional. Rows to skip. For deep pages, walk with cursor instead. Example: 0.
cursorquerystringOptional. meta.nextCursor of the previous page. Walks the whole result set in a stable order (startsAt, id); not combinable with offset or near.

Response: ShowtimeList

POST /v1/movies/{id}/showtimes/search

Showtimes of a movie with a JSON body (defaults to upcoming from now)

Same filters and results as GET /v1/movies/{id}/showtimes, sent as a JSON body (typed values, camelCase names). Read-only.

ParameterTypeDescription
id*pathstringMovie id (ours), as returned by GET /v1/movies?q=…, GET /v1/movies?tmdb_id=… / ?allocine_id=…, or movieId of a showtime. A film can have several ids (one per country, or per published title until it is matched on TMDB): to get every showtime of a film from its TMDB or Allociné id, prefer GET /v1/showtimes?tmdb_id=… / ?allocine_id=…

JSON body: MovieShowtimeSearch · Response: ShowtimeList

Meta

GET /health

Liveness check

Response: Health

Schemas

CinemaList

FieldTypeDescription
data*Cinema[]
meta*Meta

Cinema

FieldTypeDescription
id*string
slug*string
name*string
address*string | null
city*string
country*"FR" | "US"ISO 3166-1 alpha-2
timezone*stringIANA time zone of the cinema: its showtimes startsAt are wall-clock times in this zone
postalCode*string | nullPostal code (FR) or ZIP code (US)
inseeCode*string | nullFrance only: INSEE code of the municipality (CNC); set even when postalCode is missing
department*string | nullFrance only: département code (CNC)
region*string | nullRégion (FR) or state code, e.g. "NY" (US)
lat*number | null
lng*number | null
website*string | null
cncId*integer | nullFrance only: CNC id of the establishment
screens*integer | null
seats*integer | null
artEtEssai*boolean | nullFrance only: rated "Art et Essai" (arthouse label)
ticketingUrl*string | null
phone*string | null
email*string | null
active*boolean
programmeCheckedAt*string | nullLast successful read of the cinema's programme (ISO 8601, UTC); null when it was never read. A programme read more than 2 days ago may be stale
distanceKmnumberOnly present when near is given

Meta

FieldTypeDescription
limit*integer
offset*integer
totalinteger

Error

FieldTypeDescription
error*object

CinemaSearch

FieldTypeDescription
country"FR" | "US"Optional. Only cinemas of this country. Default: every country.
citystringOptional. Exact city name; Paris also matches its arrondissements.
qstringOptional. Name contains.
zipCodestringOptional. Postal code (FR) or ZIP code (US) starts with: 75005 for one code, 75 for a whole French department, 100 for a range of US ZIP codes. 2 to 5 digits.
activebooleanOptional. Open cinemas (default) or closed ones.
nearobjectOptional. Centre point and radius (default 10 km); results carry distanceKm.
limitintegerOptional.
offsetintegerOptional.

ShowtimeList

FieldTypeDescription
data*Showtime[]
meta*ShowtimeMeta

Showtime

FieldTypeDescription
id*string
cinemaId*stringAlways present, also when cinema is left out with include
movieId*stringAlways present, also when movie is left out with include
startsAt*stringWall-clock datetime in the cinema's time zone (cinema.timezone), no offset
version*"VF" | "VO" | "VOST" | "VFST" | "UNKNOWN"
format*"2D" | "3D" | "IMAX" | "4DX" | "DOLBY" | "UNKNOWN"
room*string | null
bookingUrl*string | null
updatedAt*stringLast insert, change or removal of this showtime (ISO 8601, UTC)
removedAt*string | nullSet when the cinema no longer lists this showtime (cancelled or withdrawn). Only returned with updated_since; normal lists hide removed showtimes
movieMovie
cinemaobject

Movie

FieldTypeDescription
id*string
title*stringClean title from TMDB when the movie is matched (tmdbId set): French for French cinemas, English for US ones; otherwise the title as published by the first cinema
rawTitle*string | nullTitle as first published by a cinema, before cleanup
originalTitle*string | null
year*integer | null
durationMin*integer | null
director*string | null
synopsis*string | nullSynopsis (TMDB), French or English like title
genres*string[]Genre names (TMDB), French or English like title; empty when unknown
posterUrl*string | null
allocineId*string | nullAllociné film id, when the movie was read from Allociné (France); filter showtimes with allocine_id
tmdbId*integer | nullThe Movie Database id, set when the movie was matched. Group showtimes of one film by tmdbId: cinemas publishing different titles ("SPIDERMAN", "Spider-Man : Brand New Day") give distinct ids with the same tmdbId, and a film shown in France and in the US has one id per country
updatedAt*stringLast change of the movie (TMDB match, alias, metadata), ISO 8601 UTC
titleSource*"tmdb" | "raw"tmdb: title, synopsis and genres come from TMDB (tmdbId set); raw: title as published by the cinema, not matched yet

ShowtimeMeta

CinemaShowtimeSearch

FieldTypeDescription
datestringOptional. Whole day, in each cinema's local time.
fromstringOptional. YYYY-MM-DD or YYYY-MM-DDTHH:MM, in each cinema's local time. Defaults to now in each cinema's time zone.
tostringOptional. YYYY-MM-DD or YYYY-MM-DDTHH:MM, in each cinema's local time.
version"VF" | "VO" | "VOST" | "VFST" | "UNKNOWN"Optional.
include("movie" | "cinema")[]Optional. Nested objects to embed. Default both; [] returns only movieId / cinemaId.
limitintegerOptional.
offsetintegerOptional.
cursorstringOptional. meta.nextCursor of the previous page.

ShowtimeSearch

FieldTypeDescription
country"FR" | "US"Optional. Only cinemas of this country. Default: every country.
citystringOptional. Exact city name; Paris also matches its arrondissements.
cinemaIdstringOptional. One cinema (id).
movieIdstringOptional. One movie row (id).
tmdbIdintegerOptional. Every showtime of this TMDB film, whatever the title or country.
allocineIdstringOptional. Every showtime of this Allociné film (allocine.fr/film/fichefilm_gen_cfilm=.html).
nearobjectOptional. Centre point and radius (default 10 km); results carry distanceKm.
datestringOptional. Whole day, in each cinema's local time.
fromstringOptional. YYYY-MM-DD or YYYY-MM-DDTHH:MM, in each cinema's local time. Defaults to now in each cinema's time zone.
tostringOptional. YYYY-MM-DD or YYYY-MM-DDTHH:MM, in each cinema's local time.
version"VF" | "VO" | "VOST" | "VFST" | "UNKNOWN"Optional.
updatedSincestringOptional. Incremental sync, as updated_since of GET /v1/showtimes.
include("movie" | "cinema")[]Optional. Nested objects to embed. Default both; [] returns only movieId / cinemaId.
limitintegerOptional.
offsetintegerOptional.
cursorstringOptional. meta.nextCursor of the previous page.

MovieList

FieldTypeDescription
data*Movie[]
meta*Meta

MovieSearch

FieldTypeDescription
qstringOptional. Title search (accent/case-insensitive).
playingbooleanOptional. Only movies with upcoming showtimes (in country when given).
country"FR" | "US"Optional. Only movies shown in this country.
tmdbIdintegerOptional. Every row of this TMDB film.
allocineIdstringOptional. Every row of this Allociné film.
updatedSincestringOptional. Only movies changed since this ISO 8601 instant.
limitintegerOptional.
offsetintegerOptional.

UnmatchedMovieList

FieldTypeDescription
data*UnmatchedMovie[]
meta*Meta

UnmatchedMovie

FieldTypeDescription
movie*Movie
upcomingShowtimes*integer
cinemas*integerActive cinemas showing it

MovieShowtimeSearch

FieldTypeDescription
country"FR" | "US"Optional. Only cinemas of this country. Default: every country.
citystringOptional. Exact city name; Paris also matches its arrondissements.
nearobjectOptional. Centre point and radius (default 10 km); results carry distanceKm.
datestringOptional. Whole day, in each cinema's local time.
fromstringOptional. YYYY-MM-DD or YYYY-MM-DDTHH:MM, in each cinema's local time. Defaults to now in each cinema's time zone.
tostringOptional. YYYY-MM-DD or YYYY-MM-DDTHH:MM, in each cinema's local time.
version"VF" | "VO" | "VOST" | "VFST" | "UNKNOWN"Optional.
include("movie" | "cinema")[]Optional. Nested objects to embed. Default both; [] returns only movieId / cinemaId.
limitintegerOptional.
offsetintegerOptional.
cursorstringOptional. meta.nextCursor of the previous page.

Health

FieldTypeDescription
ok*true
version*string