Skip to main content
This guide covers administrative operations for managing your Komga server, including server settings, task management, duplicate page detection, and initial server setup.
All operations in this guide require ADMIN role unless otherwise noted.

Server claim (initial setup)

When Komga is first installed, it needs to be “claimed” by creating the initial admin user.

Check claim status

import { getClaimStatus } from 'komga-sdk';

const result = await getClaimStatus({ client });

if (result.data) {
  if (result.data.isClaimed) {
    console.log('Server is already configured');
  } else {
    console.log('Server needs initial setup');
  }
}
This endpoint does not require authentication - it’s designed for initial setup.

Claim the server

Create the initial admin user:
import { claimServer } from 'komga-sdk';

const result = await claimServer({
  client,
  body: {
    email: 'admin@example.com',
    password: 'secure-admin-password',
  },
});

if (result.data) {
  console.log('Server claimed successfully');
  // The response includes the created user
  console.log(`Admin user ID: ${result.data.id}`);
}
The claim endpoint can only be called once. After claiming, you must authenticate with the admin credentials.

Server settings

Get server settings

import { getServerSettings } from 'komga-sdk';

const result = await getServerSettings({ client });

if (result.data) {
  console.log('Server settings:');
  console.log(`- Delete empty collections: ${result.data.deleteEmptyCollections}`);
  console.log(`- Delete empty read lists: ${result.data.deleteEmptyReadLists}`);
  console.log(`- Remember me duration: ${result.data.rememberMeDurationDays} days`);
  console.log(`- Thumbnail size: ${result.data.thumbnailSize}`);
}

Update server settings

You can update individual settings without affecting others:
import { updateServerSettings } from 'komga-sdk';

await updateServerSettings({
  client,
  body: {
    deleteEmptyCollections: true,
    deleteEmptyReadLists: true,
    rememberMeDurationDays: 30,
    thumbnailSize: 'DEFAULT',
    taskPoolSize: 4,
  },
});

Available settings

SettingTypeDescription
deleteEmptyCollectionsbooleanAuto-delete collections when empty
deleteEmptyReadListsbooleanAuto-delete read lists when empty
rememberMeDurationDaysnumber”Remember me” cookie duration
thumbnailSizestringThumbnail quality: DEFAULT, MEDIUM, LARGE, XLARGE
taskPoolSizenumberNumber of concurrent background tasks
serverPortnumberServer port (requires restart)
serverContextPathstringURL context path

Server information

Get server info

Retrieve version and runtime information:
import { getActuatorInfo } from 'komga-sdk';

const result = await getActuatorInfo({ client });

if (result.data) {
  console.log('Server information:');
  // Response contains build and runtime details
  console.log(JSON.stringify(result.data, null, 2));
}

Releases

Check available Komga releases:
import { getReleases } from 'komga-sdk';

const result = await getReleases({ client });

if (result.data) {
  result.data.forEach(release => {
    console.log(`${release.version} - ${release.releaseDate}`);
  });
}

Announcements

Komga displays announcements for important updates and information.

Get announcements

import { getAnnouncements } from 'komga-sdk';

const result = await getAnnouncements({ client });

if (result.data) {
  for (const announcement of result.data) {
    console.log(`[${announcement.id}] ${announcement.title}`);
    console.log(`  ${announcement.body}`);
  }
}

Mark announcements as read

import { markAnnouncementsRead } from 'komga-sdk';

await markAnnouncementsRead({
  client,
  body: {
    ids: ['announcement-1', 'announcement-2'],
  },
});

Task management

Clear the task queue

Cancel all pending background tasks:
import { emptyTaskQueue } from 'komga-sdk';

await emptyTaskQueue({ client });
console.log('Task queue cleared');
This cancels all pending tasks including library scans, metadata refreshes, and thumbnail generation. Use with caution.

Historical events

View a log of important events on the server:
import { getHistoricalEvents } from 'komga-sdk';

const result = await getHistoricalEvents({
  client,
  query: {
    page: 0,
    size: 50,
  },
});

if (result.data) {
  for (const event of result.data.content) {
    console.log(`${event.timestamp}: ${event.type}`);
  }
}

Directory browsing

Browse the server’s filesystem (for library setup):
import { getDirectoryListing } from 'komga-sdk';

const result = await getDirectoryListing({
  client,
  body: {
    path: '/media/comics',
  },
});

if (result.data) {
  console.log(`Parent: ${result.data.parent}`);
  for (const dir of result.data.directories) {
    console.log(`📁 ${dir.name}`);
  }
}
This endpoint is typically used in admin UIs when setting up new libraries.

Duplicate page detection

Komga can detect duplicate pages across your library (useful for finding credit pages, ads, etc.).

List unknown duplicates

Get pages that appear multiple times but haven’t been categorized:
import { getUnknownPageHashes } from 'komga-sdk';

const result = await getUnknownPageHashes({
  client,
  query: {
    page: 0,
    size: 20,
  },
});

if (result.data) {
  for (const hash of result.data.content) {
    console.log(`Hash: ${hash.hash}`);
    console.log(`  Matches: ${hash.matchCount}`);
    console.log(`  Size: ${hash.size} bytes`);
  }
}

Get duplicate thumbnail

Preview a duplicate page:
import { getUnknownPageHashThumbnail } from 'komga-sdk';

const result = await getUnknownPageHashThumbnail({
  client,
  path: { pageHash: 'abc123def456' },
});

if (result.data) {
  // result.data is the image blob
  const url = URL.createObjectURL(result.data);
  // Display in UI
}

View duplicate matches

See which books contain a specific duplicate page:
import { getPageHashMatches } from 'komga-sdk';

const result = await getPageHashMatches({
  client,
  path: { pageHash: 'abc123def456' },
});

if (result.data) {
  for (const match of result.data) {
    console.log(`Book: ${match.bookId}, Page: ${match.pageNumber}`);
  }
}

Mark duplicate as known

Categorize a duplicate page:
import { createOrUpdateKnownPageHash } from 'komga-sdk';

await createOrUpdateKnownPageHash({
  client,
  body: {
    hash: 'abc123def456',
    action: 'DELETE_AUTO',
    size: 12345,
  },
});

Duplicate actions

ActionDescription
DELETE_AUTOAutomatically delete this page when found
DELETE_MANUALFlag for manual review
IGNOREIgnore this duplicate

Delete duplicate pages

Remove duplicate pages by hash:
import { deleteDuplicatePagesByPageHash } from 'komga-sdk';

await deleteDuplicatePagesByPageHash({
  client,
  path: { pageHash: 'abc123def456' },
});

List known duplicates

View pages you’ve already categorized:
import { getKnownPageHashes } from 'komga-sdk';

const result = await getKnownPageHashes({
  client,
  query: {
    page: 0,
    size: 50,
  },
});

if (result.data) {
  for (const known of result.data.content) {
    console.log(`${known.hash}: ${known.action}`);
  }
}

Get known duplicate thumbnail

Preview a known duplicate page:
import { getKnownPageHashThumbnail } from 'komga-sdk';

const result = await getKnownPageHashThumbnail({
  client,
  path: { pageHash: 'abc123def456' },
});

if (result.data) {
  const url = URL.createObjectURL(result.data);
}

Delete a single duplicate match

Remove one specific match instead of all occurrences:
import { deleteSingleMatchByPageHash } from 'komga-sdk';

await deleteSingleMatchByPageHash({
  client,
  path: { pageHash: 'abc123def456' },
  body: {
    bookId: 'book-123',
    pageNumber: 5,
  },
});

Transient books (import)

Scan and import books from a folder without adding them to a library.

Scan a folder

import { scanTransientBooks } from 'komga-sdk';

const result = await scanTransientBooks({
  client,
  body: {
    path: '/downloads/comics',
  },
});

if (result.data) {
  console.log(`Found ${result.data.length} books`);
  for (const book of result.data) {
    console.log(`- ${book.name}`);
  }
}

Analyze a transient book

Get details about a book before importing:
import { analyzeTransientBook } from 'komga-sdk';

const result = await analyzeTransientBook({
  client,
  path: { transientBookId: 'transient-123' },
});

if (result.data) {
  console.log(`Pages: ${result.data.media?.pagesCount}`);
  console.log(`Format: ${result.data.media?.mediaType}`);
}

Preview a transient book page

Retrieve a page image from a transient book:
import { getPageByTransientBookId } from 'komga-sdk';

const result = await getPageByTransientBookId({
  client,
  path: { 
    transientBookId: 'transient-123',
    pageNumber: 1,
  },
});

if (result.data) {
  const url = URL.createObjectURL(result.data);
}

Import books

Import books into a series:
import { importBooks } from 'komga-sdk';

await importBooks({
  client,
  body: {
    books: [
      {
        sourceFile: '/downloads/comics/book1.cbz',
        seriesId: 'series-123',
        upgradeBookId: null, // or book ID to replace
        destinationName: 'Chapter 1.cbz',
      },
    ],
    copyMode: 'COPY', // 'COPY', 'MOVE', or 'HARDLINK'
  },
});

Copy modes

ModeDescription
COPYCopy file to library (original remains)
MOVEMove file to library (original deleted)
HARDLINKCreate hard link (saves space, same filesystem only)

Client settings

Store application settings for clients (web UI, mobile apps).

Save global settings

import { saveGlobalSetting } from 'komga-sdk';

await saveGlobalSetting({
  client,
  body: {
    key: 'webui.theme.mode',
    value: 'dark',
  },
});

Delete global settings

import { deleteGlobalSettings } from 'komga-sdk';

await deleteGlobalSettings({
  client,
  body: {
    keys: ['webui.theme.mode'],
  },
});

Common workflows

Initial server setup

Complete setup flow for a new Komga installation:
import {
  getClaimStatus,
  claimServer,
  updateServerSettings,
  addLibrary,
} from 'komga-sdk';

async function setupServer(
  adminEmail: string,
  adminPassword: string,
  libraryPath: string
) {
  // Check if server needs setup
  const claimStatus = await getClaimStatus({ client });
  
  if (claimStatus.data?.isClaimed) {
    throw new Error('Server is already configured');
  }

  // Claim the server
  await claimServer({
    client,
    body: {
      email: adminEmail,
      password: adminPassword,
    },
  });

  // Now authenticate as admin
  const adminClient = createClient({
    baseUrl: 'http://localhost:25600',
    auth: { username: adminEmail, password: adminPassword },
  });

  // Configure server settings
  await updateServerSettings({
    client: adminClient,
    body: {
      deleteEmptyCollections: true,
      deleteEmptyReadLists: true,
      thumbnailSize: 'LARGE',
    },
  });

  // Add initial library
  await addLibrary({
    client: adminClient,
    body: {
      name: 'Comics',
      root: libraryPath,
      scanOnStartup: true,
      scanInterval: 'EVERY_6H',
    },
  });

  return adminClient;
}

Duplicate cleanup workflow

Review and clean up duplicate pages:
import {
  getUnknownPageHashes,
  getUnknownPageHashThumbnail,
  createOrUpdateKnownPageHash,
  deleteDuplicatePagesByPageHash,
} from 'komga-sdk';

interface DuplicateReview {
  hash: string;
  matchCount: number;
  thumbnailUrl: string;
}

async function getDuplicatesForReview(limit = 10): Promise<DuplicateReview[]> {
  const result = await getUnknownPageHashes({
    client,
    query: { page: 0, size: limit },
  });

  if (!result.data) return [];

  const reviews: DuplicateReview[] = [];
  
  for (const hash of result.data.content) {
    const thumbnail = await getUnknownPageHashThumbnail({
      client,
      path: { pageHash: hash.hash },
    });

    reviews.push({
      hash: hash.hash,
      matchCount: hash.matchCount,
      thumbnailUrl: thumbnail.data 
        ? URL.createObjectURL(thumbnail.data) 
        : '',
    });
  }

  return reviews;
}

async function handleDuplicateDecision(
  hash: string,
  action: 'delete' | 'ignore',
  size: number
) {
  if (action === 'delete') {
    // Mark for auto-deletion
    await createOrUpdateKnownPageHash({
      client,
      body: { hash, action: 'DELETE_AUTO', size },
    });
    
    // Delete existing matches
    await deleteDuplicatePagesByPageHash({
      client,
      path: { pageHash: hash },
    });
  } else {
    // Ignore this duplicate
    await createOrUpdateKnownPageHash({
      client,
      body: { hash, action: 'IGNORE', size },
    });
  }
}

Error handling

import { getServerSettings } from 'komga-sdk';

const result = await getServerSettings({ client });

if (result.error) {
  switch (result.response?.status) {
    case 401:
      console.error('Not authenticated');
      break;
    case 403:
      console.error('Admin access required');
      break;
    default:
      console.error('Error:', result.error);
  }
}

Next steps

Users

Manage users and their permissions.

Libraries

Configure and manage libraries.

Configuration

Client configuration options.

Troubleshooting

Common issues and solutions.