Type-safe TypeScript companion SDK for the Trakt API.
Trakt is the user activity layer for movie and TV apps. It gives your product a portable watchlist, viewing history, ratings, playback scrobbling, calendars, collections, and sync state that can follow a user across devices and services.
@api-wrappers/trakt-wrapper is built for watchlist apps, media trackers,
personal media dashboards, second-screen experiences, and sync jobs that need
Trakt data without hand-rolling request paths, headers, OAuth helpers, pagination,
or response types.
It also pairs cleanly with @api-wrappers/tmdb-wrapper:
- TMDB gives you rich metadata, artwork, posters, backdrops, discovery, and localized media details.
- Trakt gives you user activity: watchlists, history, ratings, calendars, scrobbling, collections, playback progress, and account sync.
Use TMDB IDs in Trakt sync bodies to connect the two systems: TMDB powers the catalog surface, while Trakt records what the user did with that catalog.
bun add @api-wrappers/trakt-wrappernpm install @api-wrappers/trakt-wrapperimport { Trakt } from "@api-wrappers/trakt-wrapper";
const trakt = new Trakt({
clientId: process.env.TRAKT_CLIENT_ID,
accessToken: process.env.TRAKT_ACCESS_TOKEN,
});
const trending = await trakt.movies.trending({ limit: 10, extended: "full" });
for (const item of trending.data) {
console.log(item.watchers, item.movie.title);
}
console.log(trending.pagination.itemCount);- Endpoint groups match the Trakt product areas you build with:
auth,movies,shows,users,sync,calendars,scrobble,checkin,lists, andsearch. - OAuth URL, authorization-code exchange, refresh, revoke, and device-code flow helpers keep auth code out of your request plumbing.
- Paginated endpoints return parsed pagination metadata from Trakt headers.
- The shared
@api-wrappers/api-coreruntime gives you customfetch, retries, timeouts, transports, and plugins. - Request and response types cover common media, user, sync, watchlist, rating, and scrobble shapes while preserving a low-level escape hatch for new Trakt endpoints.
const trakt = new Trakt({
clientId: process.env.TRAKT_CLIENT_ID,
clientSecret: process.env.TRAKT_CLIENT_SECRET,
redirectUri: "urn:ietf:wg:oauth:2.0:oob",
});
const authorizeUrl = trakt.auth.getAuthorizationUrl({
state: "csrf-or-session-state",
});
console.log(authorizeUrl);
const token = await trakt.auth.exchangeCode("authorization-code");
trakt.setAccessToken(token.access_token);const code = await trakt.auth.deviceCode();
console.log(`Open ${code.verification_url} and enter ${code.user_code}`);
const token = await trakt.auth.deviceToken(code.device_code);
trakt.setAccessToken(token.access_token);const trending = await trakt.movies.trending({
limit: 10,
extended: "full",
});
for (const item of trending.data) {
console.log(item.watchers, item.movie.title, item.movie.ids.tmdb);
}const history = await trakt.users.history("me", "movies", undefined, {
limit: 25,
extended: "full",
});
console.log(history.pagination.pageCount);const watchlist = await trakt.sync.watchlist({
type: "movies",
sort: "rank",
extended: "full",
});
await trakt.sync.addWatchlist({
movies: [{ ids: { tmdb: 438631 } }],
});const tenStarMovies = await trakt.sync.ratings("movies", 10);
await trakt.sync.addRatings({
movies: [
{
rating: 9,
ids: { tmdb: 438631 },
},
],
});
console.log(tenStarMovies.length);await trakt.scrobble.start({
progress: 1,
movie: { ids: { tmdb: 438631 } },
});
await trakt.scrobble.stop({
progress: 95,
movie: { ids: { tmdb: 438631 } },
});const [result] = await trakt.search.id("tmdb", 438631, { type: "movie" });
console.log(result.movie?.title);Use trakt.api when Trakt adds an endpoint before this wrapper exposes a typed
method for it.
const data = await trakt.api.get<unknown>("/movies/trending", {
query: { limit: 5, extended: "full" },
});
const page = await trakt.api.paginated<unknown>("/movies/trending", {
query: { page: 1, limit: 10 },
});More copy-ready examples live in docs/examples.md.
const url = trakt.auth.getAuthorizationUrl({ state: "session-state" });
// Redirect the user to `url`, then exchange the returned code.
const token = await trakt.auth.exchangeCode("returned-code");
trakt.setAccessToken(token.access_token);const watchlist = await trakt.sync.watchlist({
type: "movies",
extended: "full",
});
const tmdbIds = watchlist
.map((item) => item.movie?.ids.tmdb)
.filter((id): id is number => typeof id === "number");await trakt.sync.addHistory({
movies: [{ ids: { tmdb: 438631 } }],
});const importedTmdbIds = [438631, 693134, 872585];
await trakt.sync.addHistory({
movies: importedTmdbIds.map((tmdb) => ({ ids: { tmdb } })),
});await trakt.scrobble.start({
progress: 5,
movie: { ids: { tmdb: 438631 } },
});
await trakt.scrobble.stop({
progress: 90,
movie: { ids: { tmdb: 438631 } },
});auth: OAuth authorization, token exchange, refresh, device flow, revokesearch: text search and ID lookupmovies: trending, popular, played, watched, collected, anticipated, details, comments, lists, people, ratings, related, stats, watchingshows: trending, popular, played, watched, collected, anticipated, details, seasons, comments, lists, people, ratings, related, stats, watchingseasonsandepisodes: summaries, comments, lists, people, ratings, stats, watchingcalendars: all and authenticated show/movie calendarsusers: profile, watching, watched, history, ratings, watchlist, collection, listssync: last activities, playback, watched, history, collection, watchlist, ratingsscrobble: start, pause, stopcheckin: create and remove check-inslists: trending, popular, summary, items, create, update, delete, add/remove items
This package uses the shared @api-wrappers/api-core HTTP runtime, so custom
fetch, retry configuration, timeouts, transports, and plugins are supported.
const trakt = new Trakt({
clientId: "client-id",
fetch: customFetch,
retry: { maxAttempts: 3, delayMs: 250 },
timeoutMs: 10_000,
});Contributions are welcome. Start with CONTRIBUTING.md for
local setup, validation, endpoint guidelines, and pull request expectations.
Maintainers use Changesets. Run bun run changeset for user-facing changes,
merge the generated version PR, and let the release workflow publish from main
after bun run verify passes. The workflow expects an NPM_TOKEN repository
secret and requests npm provenance during publish.
bun run verifyverify runs source typechecking, test typechecking, the unit test suite, and
the production build. bun run validate is kept as a compatibility alias.