A RESTful API serving structured data on the Marvel Cinematic Universe — movies, TV shows, characters, and the timeline connecting them.
baseURL https://mcuapi.up.railway.app/api/v1
docs https://mcuapi.up.railway.app/docs
health https://mcuapi.up.railway.app/health
Free, open, and no API key required.
- Movies & TV shows — release info, box office, cast, saga/phase, and where each title sits in the MCU timeline.
- Characters — bios, actors (including recasts), and every movie/show they appear in.
- Timeline — chronological ordering of the whole catalog, independent of release date.
- Hypermedia (HATEOAS) — every resource ships a HAL-style
_linksobject so clients can navigate the API without hardcoding URLs.
GET /api/v1/movies/1{
"id": 1,
"title": "Iron Man",
"_links": {
"self": { "href": "https://mcuapi.up.railway.app/api/v1/movies/1" },
"characters": { "href": "https://mcuapi.up.railway.app/api/v1/characters/movie/1" }
}
}List endpoints (/movies, /tvshows, /characters) return page, limit, and collection _links (self, first, last, plus prev/next), preserving all other query params. Characters are fully navigable via GET /characters/{id}/movies and GET /characters/{id}/tvshows.
Tip
Full request/response schemas live in the Swagger docs.
Note
Links are built from the request host by default. Set APP_URL (e.g. APP_URL=https://mcuapi.up.railway.app) to force the base URL behind a proxy.
A typed client is published as mcuapi-client — zero dependencies, ESM and CJS. Source lives in mcuapi-client/.
npm install mcuapi-clientimport { MCUAPI } from 'mcuapi-client';
const mcu = new MCUAPI();
const ironMan = await mcu.movies.get(1);
// walks every page for you by following _links.next
for await (const character of mcu.characters.all()) {
console.log(character.name, character.played_by);
}It's entirely optional — the API needs no client — but the types are derived from real production responses, so they catch things the entity definitions don't. box_office is a string (Postgres returns bigint as a string), and most fields are genuinely nullable.
The whole dataset is also committed to data/ and served over jsDelivr, so it stays reachable even if the API is down — and it doesn't count against the rate limit.
https://cdn.jsdelivr.net/gh/AugustoMarcelo/mcuapi@master/data/movies.json
https://cdn.jsdelivr.net/gh/AugustoMarcelo/mcuapi@master/data/tvshows.json
https://cdn.jsdelivr.net/gh/AugustoMarcelo/mcuapi@master/data/characters.json
https://cdn.jsdelivr.net/gh/AugustoMarcelo/mcuapi@master/data/timeline.json
https://cdn.jsdelivr.net/gh/AugustoMarcelo/mcuapi@master/data/index.json
Each file is a plain array of the same records the API returns, _links included. index.json carries the record counts, a generated_at timestamp and a content_hash.
Pin a tag instead of @master if you want a fixed dataset — @3.0.0/data/movies.json will never change. @master is refreshed weekly and cached by the CDN for up to 12 hours.
Regenerate it with npm run snapshot. The output is byte-stable when the data hasn't moved, so a no-op run leaves the tree clean.
- Read-only. Every endpoint is a
GET; the API never accepts writes. - Rate limit. 100 requests per minute per IP. Responses carry
RateLimit-*headers, and exceeding it returns429. - Caching. Responses are
Cache-Control: public, max-age=3600and carry anETag. SendIf-None-Matchto get a304and save the transfer — the dataset only changes a few times a month. - Pagination.
limitdefaults to10and is capped at100.
Express · TypeScript · TypeORM · PostgreSQL — organized as Clean Architecture modules (movies, tvshows, characters, timeline) with tsyringe for dependency injection.
git clone https://github.com/AugustoMarcelo/mcuapi
cd mcuapi
npm installCreate a .env from .env.example with your database credentials.
Development
# NODE_ENV=development in .env
npm run typeorm:dev migration:run # create tables
npm run seed:run:dev # seed data
npm run dev:server # start on port 3333 (hot-reload)Production
# NODE_ENV=production in .env
npm run typeorm migration:run # create tables
npm run seed:run # seed data
npm run build # compile to ./dist
npm run start # start on port 3333Note
NODE_ENV also tells ormconfig where to find migrations — src/ in development, dist/ in production.
Have a suggestion? Open an issue.