Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

mcuapi-client

Typed client for MCUAPI — Marvel Cinematic Universe movies, TV shows, characters, people, and the chronology that orders them.

No API key. No runtime dependencies. ESM and CJS. ~10 kB packed.

npm install mcuapi-client

Usage

import { MCUAPI } from 'mcuapi-client';

const mcu = new MCUAPI();

const ironMan = await mcu.movies.get(1);
//    ^? Movie

const { data, total } = await mcu.movies.list({
  filter: 'title=Spider',
  order: 'release_date,DESC',
  limit: 5,
});

Requires Node 18+ (for global fetch), or pass your own — see Options.

Reading a whole collection

limit is capped at 100 server-side. .all() walks the pages for you by following the API's own _links.next, yielding one record at a time:

for await (const character of mcu.characters.all()) {
  console.log(character.name, character.played_by);
}

Following hypermedia links

Every resource ships HAL-style _links, so you can traverse the graph without building paths yourself:

const movie = await mcu.movies.get(1);
const cast = await mcu.follow(movie._links!.characters!);

API

Call Returns
mcu.movies.list(params?) Paginated<Movie>
mcu.movies.get(id) Movie
mcu.movies.all(params?) AsyncGenerator<Movie>
mcu.movies.characters(id) WithRole<Character>[]
mcu.movies.postCreditScenes(id) PostCreditScene[]
mcu.tvshows.list(params?) Paginated<TVShow>
mcu.tvshows.get(id) TVShow
mcu.tvshows.all(params?) AsyncGenerator<TVShow>
mcu.tvshows.characters(id) WithRole<Character>[]
mcu.tvshows.postCreditScenes(id) PostCreditScene[]
mcu.characters.list(params?) Paginated<Character>
mcu.characters.get(id) Character
mcu.characters.all(params?) AsyncGenerator<Character>
mcu.characters.movies(id) WithRole<Movie>[]
mcu.characters.tvshows(id) WithRole<TVShow>[]
mcu.people.list(params?) Paginated<Person>
mcu.people.get(id) Person
mcu.people.all(params?) AsyncGenerator<Person>
mcu.people.characters(id) WithRecastOrder<Character>[]
mcu.people.titles(id) PersonTitle[]
mcu.postCreditScenes.list(params?) Paginated<PostCreditScene>
mcu.postCreditScenes.get(id) PostCreditScene
mcu.postCreditScenes.all(params?) AsyncGenerator<PostCreditScene>
mcu.timeline.get(params?) TimelineGroup[]
mcu.upcoming.list(params?) Paginated<UpcomingItem>
mcu.upcoming.all(params?) AsyncGenerator<UpcomingItem>
mcu.titles.list(params?) Paginated<TitleItem>
mcu.titles.all(params?) AsyncGenerator<TitleItem>
mcu.search.list(params) Paginated<SearchHit>
mcu.search.all(params) AsyncGenerator<SearchHit>
mcu.stats.get() Stats
mcu.health() Health
mcu.follow(link) whatever the link points at

List params: page, limit, order, filter, continuity, multiverse_designation — plus studio and is_mcu on movies and TV shows. people.list() and postCreditScenes.list() only honour page, limit, order, and filter; neither has continuity or multiverse_designation columns to filter by. timeline.get() takes multiverse. upcoming.list()/.all() take page, limit, type ('movie' | 'tvshow'), continuity, multiverse_designation, and is_mcu — movies and TV shows whose release_date is strictly in the future, merged and sorted ascending; titles with no announced release date are excluded. titles.list()/.all() take the same params as movies/tvshows (TitleListParams, now including type) — the same movies+tvshows merge as upcoming, but paged over the whole dataset instead of only future releases, so undated titles are included and sorted last. stats.get() takes no params.

WithRole<T> (the appearance-relation return types above) also carries appeared_in?: string — the reality the appearance actually happened in. It only differs from the title's own multiverse_designation for rare per-appearance exceptions (e.g. the Void sequences in Deadpool & Wolverine).

Two things worth knowing

box_office is a string, not a number. Postgres returns bigint as a string to avoid precision loss, so you get "585171547". Convert deliberately:

const gross = movie.box_office ? Number(movie.box_office) : null;

Most fields are nullable, including obvious ones. Recently announced titles often have no release_date, phase, saga, box_office, or runtime yet. The types reflect what the API really returns — verified against production, not copied from the server's entity definitions — so the compiler will make you handle it.

Errors

Non-2xx responses throw MCUAPIError:

import { MCUAPIError } from 'mcuapi-client';

try {
  await mcu.movies.get(99999);
} catch (err) {
  if (err instanceof MCUAPIError) {
    err.status;        // 404
    err.isNotFound;    // true
    err.isRateLimited; // true only on 429
    err.body;          // Problem Details JSON, or raw text
  }
}

The API allows 100 requests per minute per IP and sends RateLimit-* headers.

Options

const mcu = new MCUAPI({
  baseUrl: 'http://localhost:3333', // point at your own instance
  timeout: 10_000,                  // per-request, in ms
  headers: { 'User-Agent': 'my-app/1.0' },
  fetch: myFetch,                   // undici, a proxy agent, a test double
});

Every method takes an optional { signal } for cancellation:

const controller = new AbortController();
const page = await mcu.movies.list({}, { signal: controller.signal });

Caching

Successful cacheable responses carry Cache-Control: public, max-age=3600 and an ETag; API JSON responses are also cached server-side in Redis and invalidated after MCP data writes. Error responses use Cache-Control: no-store.

Licence

MIT. Source and issues: https://github.com/AugustoMarcelo/mcuapi

Not affiliated with Marvel, Marvel Studios, or The Walt Disney Company.