Jellyfin API Client
@get-coral/jellyfin
Section titled “@get-coral/jellyfin”A modern, fetch-based Jellyfin API client with full TypeScript types and zero dependencies. Works in Node.js, browsers, and edge runtimes. It powers Aurora and the other Coral modules.
Installation
Section titled “Installation”pnpm add @get-coral/jellyfin# ornpm install @get-coral/jellyfinQuick Start
Section titled “Quick Start”import { createClient, getLibraryItems, fromJellyfin } from '@get-coral/jellyfin'
const client = createClient({ url: 'http://192.168.1.10:8096', apiKey: 'your-api-key', userId: 'your-user-id',})
const { Items } = await getLibraryItems(client, 'Movie', { limit: 24, sortBy: 'SortName', watchStatus: 'unwatched',})
const movies = Items.map(item => fromJellyfin(client, item))Client Configuration
Section titled “Client Configuration”const client = createClient({ url: string // Jellyfin server URL (trailing slash stripped automatically) apiKey: string // Jellyfin API key userId: string // User ID (UUID)
// Optional — for playback progress sync username?: string password?: string
// Optional — a ready Jellyfin access token (e.g. from authenticateUserByName). // When set, playback auth uses it directly instead of re-authenticating. accessToken?: string
// Optional — how this client identifies itself in Jellyfin's active sessions clientName?: string // default: 'Coral' deviceName?: string // default: 'Coral Web' deviceId?: string // default: 'coral-web' version?: string // default: '1.0.0'})API Overview
Section titled “API Overview”The client is passed as the first argument to standalone functions, grouped roughly by area:
- Items:
getLibraryItems,getItem,getLatestMedia,getContinueWatching,getFavoriteItems,getWatchHistory,getMostPlayed,getSimilarItems,getFeaturedItem,searchItems,setFavorite,setPlayed,deleteItem,updateItem, remote image helpers - Shows:
getEpisodesForSeries,getNextUpForSeries - Collections:
getCollections,getCollectionItems,createCollection,addItemsToCollection,removeItemsFromCollection,searchCollectionItems - Playback:
createPlaybackSession,syncPlaybackState - Authentication & sessions:
authenticateUserByName,logoutUserSession - URL builders:
imageUrl,personImageUrl,streamUrl,transcodeUrl,subtitleUrl - Mapper:
fromJellyfin,fromJellyfinDetailed— normalise rawJellyfinItems into a UI-friendlyMediaItemshape - Admin:
getSystemInfo,getItemCounts,getActiveSessions,getUsers,getUserById,createUser,deleteUser,updateUserPolicy,getVirtualFolders,scanAllLibraries,scanLibrary
See the repository README for the full reference with options and return types.
Authentication & Sessions
Section titled “Authentication & Sessions”Build sign-in flows on top of Jellyfin’s own accounts:
import { authenticateUserByName, logoutUserSession, createClient } from '@get-coral/jellyfin'
// Sign a user in with their Jellyfin username/password.// Returns their identity and a real Jellyfin access token.const { user, accessToken, sessionId } = await authenticateUserByName(client, 'alice', 'secret')
// Act as that user: playback and progress sync run under their tokenconst userClient = createClient({ url, apiKey, userId: user.Id, accessToken, deviceId: 'my-app-session-1234',})
// End the session again (revokes the token)await logoutUserSession(client, accessToken)Give every session a unique deviceId — Jellyfin revokes the previous token when the same user re-authenticates with the same device id, so a shared id makes concurrent sign-ins invalidate each other. authenticateUserByName throws a JellyfinError with status 401 for invalid credentials or disabled users.
Playback Sync
Section titled “Playback Sync”import { createPlaybackSession, syncPlaybackState } from '@get-coral/jellyfin'
const session = await createPlaybackSession(client, itemId)
await syncPlaybackState(client, { itemId, playSessionId: session.playSessionId, positionTicks: 12_345, isPaused: false,})Playback endpoints authenticate as a real Jellyfin session, using either the configured username/password or a ready accessToken.
Error Handling
Section titled “Error Handling”All functions throw a JellyfinError on non-OK responses:
import { JellyfinError } from '@get-coral/jellyfin'
try { const item = await getItem(client, 'bad-id')} catch (err) { if (err instanceof JellyfinError) { console.error(err.message) // 'Jellyfin API error on ...: 404 Not Found' console.error(err.status) // 404 }}Contributing
Section titled “Contributing”Community contributions are welcome! See the Contributing guide.