Skip to main content
The libraries router manages library configurations and triggers filesystem scans to index ebooks.

Create library

Create a new library with optional filesystem paths.
const library = await client.libraries.createLibrary({
  name: "My Books",
  isCronWatch: true,
  isPublic: false,
  paths: ["/mnt/books/fiction", "/mnt/books/non-fiction"],
});

Input

name
string
required
Library name (minimum 1 character)
isCronWatch
boolean
default:false
Whether to automatically scan this library on a schedule
isPublic
boolean
default:false
Whether this library is visible to all organization members
paths
string[]
Array of filesystem paths to scan for ebooks

Response

id
number
Library ID
name
string | null
Library name
isCronWatch
boolean | null
Whether automatic scanning is enabled
isPublic
boolean
Whether library is public
createdAt
string
ISO timestamp when library was created
paths
array
Array of library path objects
id
number
Path ID
libraryId
number
Parent library ID
path
string
Filesystem path
isEnabled
boolean | null
Whether this path is enabled for scanning
createdAt
string
ISO timestamp

Get libraries

List all libraries for the user’s active organization.
const libraries = await client.libraries.getLibraries();

Response

Array of library objects with paths included.

Get library by ID

Retrieve a single library with its paths.
const library = await client.libraries.getLibraryById({
  id: 1,
});

Input

id
number
required
Library ID

Response

Library object with paths array.

Add path

Add a filesystem path to an existing library.
const path = await client.libraries.addPath({
  libraryId: 1,
  path: "/mnt/books/manga",
});

Input

libraryId
number
required
Library ID
path
string
required
Filesystem path (minimum 1 character)

Response

Library path object.

Remove path

Remove a filesystem path from a library.
await client.libraries.removePath({
  pathId: 5,
});

Input

pathId
number
required
Library path ID

Update library

Update library settings.
const updated = await client.libraries.updateLibrary({
  id: 1,
  name: "Updated Name",
  isCronWatch: true,
  isPublic: true,
});

Input

id
number
required
Library ID
name
string
New library name (minimum 1 character)
isCronWatch
boolean
Enable/disable automatic scanning
isPublic
boolean
Update public visibility

Response

Updated library object.

Delete library

Delete a library and all its associated data.
await client.libraries.deleteLibrary({
  id: 1,
});

Input

id
number
required
Library ID

Scan library

Trigger a filesystem scan to discover and index ebooks.
const result = await client.libraries.scanLibrary({
  libraryId: 1,
});
console.log(result.jobId); // BullMQ job ID

Input

libraryId
number
required
Library ID to scan

Response

jobId
string
BullMQ job ID for tracking the scan operation

Library scanning process

When you trigger a library scan:
  1. Discovery phase - The scanner recursively walks all library paths, discovering ebook files (EPUB, PDF, etc.)
  2. File events - For each discovered file, a file-event job is queued to BullMQ
  3. Book creation - The file.event.worker processes each file:
    • Extracts basic metadata from the file
    • Creates a book record in the database
    • Creates a scanned_file record to prevent duplicate processing
    • Queues a book-index job for Elasticsearch indexing
  4. Indexing - The book.index.worker indexes books into Elasticsearch with full metadata

Supported formats

  • EPUB
  • PDF
  • Additional formats may be supported depending on metadata extractors

Example: Create and scan library

// 1. Create library
const library = await client.libraries.createLibrary({
  name: "Japanese Literature",
  isCronWatch: true,
  isPublic: false,
  paths: ["/data/books/japanese"],
});

// 2. Trigger initial scan
const scanResult = await client.libraries.scanLibrary({
  libraryId: library.id,
});

console.log(`Scan started: ${scanResult.jobId}`);

// 3. Poll for books
setInterval(async () => {
  const books = await client.books.listRecent({ limit: 10 });
  console.log(`Found ${books.length} books`);
}, 5000);

Library types

The library model is defined in packages/api/src/routers/libraries/library.model.ts:
const LibrarySchema = z.object({
  id: z.number().int().nonnegative(),
  name: z.string().nullable().optional(),
  isCronWatch: z.boolean().nullable().optional(),
  isPublic: z.boolean(),
  createdAt: z.string(),
});

const LibraryPathSchema = z.object({
  id: z.number().int().nonnegative(),
  libraryId: z.number().int().nonnegative(),
  path: z.string(),
  isEnabled: z.boolean().nullable().optional(),
  createdAt: z.string(),
});

export const LibraryWithPathsSchema = LibrarySchema.extend({
  paths: z.array(LibraryPathSchema).optional(),
});

Build docs developers (and LLMs) love