MCUAPI/v1 mcuapi.up.railway.app
MCUAPI · v1 · read-only REST No API key

Every MCU movie, TV show and character — in one API that knows the order.

A free REST API for the Marvel Cinematic Universe: every movie and TV show, the characters and the actors who played them, and the chronology that orders it all — including the X-Men and Sony continuities the MCU keeps pulling in. No key, no signup, CORS open to any origin.

GET https://mcuapi.up.railway.app/api/v1/movies — no Authorization header

GET /api/v1/timeline

Release order is not watch order.

The catalogue isn't one universe either. Every title carries a continuity and an Earth designation, and /timeline returns them grouped and ordered by in-story chronology, so you can build a watch order without maintaining one by hand. Hover a mark to read it; pick a branch to load it in the console.

Hover any mark to read the title and its chronology position.
Marks are positioned by chronology_order within each branch, not by release date. Snapshot embedded · refreshing from live API…

Live request console

Try it against production, right here.

These calls hit mcuapi.up.railway.app from your browser — same URL your app will use. Every href in the response is clickable, because the API is hypermedia-driven: you can crawl the whole graph without hardcoding a single path.

Endpoint
https://mcuapi.up.railway.app/api/v1/movies?limit=5&page=1
READY Showing a cached example response. Press Send for a live one.

        
HATEOAS · click any href above to follow it

Three resources, one graph

Everything a record carries.

No partial payloads and no second call to hydrate a title. Every field below is on the resource by default — trim it with ?columns= when you want less. Fields marked with a dot are nullable.

Movie

57 records

GET /api/v1/movies · /movies/{id}

  • id
  • title
  • release_date
  • box_office
  • duration
  • overview
  • cover_url
  • trailer_url
  • directed_by
  • phase
  • saga
  • chronology
  • post_credit_scenes
  • imdb_id
  • studio
  • continuity
  • multiverse_designation
  • is_mcu
  • type
  • timeline_chronology_order
  • updated_at
_links selfcharactersrelated_movies[]related_tvshows[]

TV show

56 records

GET /api/v1/tvshows · /tvshows/{id}

  • id
  • title
  • release_date
  • last_aired_date
  • season
  • number_episodes
  • overview
  • cover_url
  • trailer_url
  • directed_by
  • phase
  • saga
  • chronology
  • imdb_id
  • studio
  • continuity
  • multiverse_designation
  • is_mcu
  • type
  • timeline_chronology_order
  • updated_at
_links selfcharactersrelated_movies[]related_tvshows[]

Character

302 records

GET /api/v1/characters · /characters/{id}

  • id
  • name
  • alias
  • description
  • image_url
  • played_by
  • continuity
  • multiverse_designation
  • variant_of
  • first_appearance_movie_id
  • first_appearance_tvshow_id
  • created_at
  • updated_at
_links selfmoviestvshowsvariant_offirst_appearance_moviefirst_appearance_tvshow
Recasts and variants

played_by is per character record, and variant_of points a character at the version they are a variant of — so a recast or a multiverse double is a real edge in the graph, not a duplicate row you have to reconcile.

Collections

List endpoints wrap results as { data, total, page, limit, _links } with first, prev, next and last that preserve every filter you passed in.

Filtering

?filter=column=value for a case-insensitive match, ?order=column,DESC to sort, and ?continuity= or ?is_mcu=false to scope to one branch of the multiverse.


GET /api/v1/characters/{id}/movies

One name, several people, several earths.

Civilian names live on name and hero names on alias, so the search hits both — Captain America returns two different people. Every record carrying the term comes back, including the variants each continuity casts separately, which is why played_by sits on the character and not on the title. Pick one and the page follows that record's own _links.movies and _links.tvshows to the titles it appears in. No join table to maintain on your side.

Loading characters from the live API…
Variants are joined by variant_of; each one carries its own played_by. Querying /characters…

Three lines to first data

No key. No setup. Client optional.

# Every Phase 4 movie, newest first, three fields only
curl "https://mcuapi.up.railway.app/api/v1/movies?filter=phase=4&order=release_date,DESC&columns=id,title,release_date"

# The full chronological timeline for one branch
curl "https://mcuapi.up.railway.app/api/v1/timeline?multiverse=Earth-10005"
Auth None. No key, no hash, no referrer allow-list.
Methods Read-only — every route is a GET.
Pagination limit defaults to 10, capped at 100. Collections carry first, prev, next, last.
Rate limit 100 requests per minute per IP, with RateLimit-* headers and a 429 past it.
Caching Cache-Control: public, max-age=3600 plus an ETag. Send If-None-Match for a 304.
CORS Access-Control-Allow-Origin: * — call it straight from the browser.
Open source · issues welcome

Built it because the data should stay reachable.

Express, TypeScript, TypeORM and Postgres, organised as clean-architecture modules. If a title is missing, a cover is broken, or you want a field that isn't there yet, open an issue — the dataset is maintained by hand and every correction lands for everyone.

Star the repo on GitHub