> ## Documentation Index
> Fetch the complete documentation index at: https://komga-sdk.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Users

> Manage users, API keys, passwords, and authentication activity

This guide covers user administration, API keys, passwords, and authentication activity. Generated operations return `{ data, error, request, response }`; pass flat parameters first and `{ client }` second.

> [!NOTE]
>
> Most user administration operations require the **ADMIN** role. A regular user can manage their own profile, password, settings, and API keys, but cannot create, update, delete, or audit another user.

## Roles and restrictions

Roles are server-defined strings. Common roles include:

| Role | Capability |
| - | - |
| `USER` | Normal authenticated library access |
| `ADMIN` | User, library, and server administration |
| `FILE_DOWNLOAD` | Download complete book files |
| `PAGE_STREAMING` | Stream individual book pages |

Library and content restrictions are separate from roles:

* `sharedLibraries: { all: false, libraryIds }` limits a user to selected libraries. Set `all: true` for every library.
* `labelsAllow` exposes only content carrying at least one allowed label.
* `labelsExclude` hides content carrying an excluded label.
* `ageRestriction` accepts `ALLOW_ONLY`, `EXCLUDE`, or `NONE` with an age value.

The response shape exposes these as `sharedAllLibraries`, `sharedLibrariesIds`, and the corresponding label/age fields.

## Get the current user

`getCurrentUser` has an optional query parameter, so pass `undefined` when only the client is needed:

```typescript theme={null}
import { getCurrentUser } from 'komga-sdk';

const result = await getCurrentUser(undefined, { client });
if (result.data) {
  console.log(`Logged in as ${result.data.email}`);
  console.log(`Roles: ${result.data.roles.join(', ')}`);
}
```

## List all users

> [!WARNING]
>
> Requires the **ADMIN** role.

```typescript theme={null}
import { getUsers } from 'komga-sdk';

const result = await getUsers({ client });
for (const user of result.data ?? []) {
  console.log(`${user.email} - ${user.roles.join(', ')}`);
}
```

## Create a user

> [!WARNING]
>
> Requires the **ADMIN** role.

The generated body parameter is `userCreationDto`. Apply library and content restrictions at creation time when possible:

```typescript theme={null}
import { addUser } from 'komga-sdk';

const result = await addUser(
  {
    userCreationDto: {
      email: 'newuser@example.com',
      password: 'secure-password-123',
      roles: ['USER', 'PAGE_STREAMING'],
      sharedLibraries: { all: false, libraryIds: ['library-1'] },
      labelsAllow: ['family-friendly'],
      labelsExclude: ['adult'],
      ageRestriction: { age: 13, restriction: 'ALLOW_ONLY' },
    },
  },
  { client },
);

if (result.data) console.log(`Created user: ${result.data.id}`);
```

## Update a user

> [!WARNING]
>
> Requires the **ADMIN** role.

`userUpdateDto` is partial. A partial update leaves omitted fields unchanged:

```typescript theme={null}
import { updateUserById } from 'komga-sdk';

await updateUserById(
  {
    id: 'user-123',
    userUpdateDto: {
      roles: ['USER', 'FILE_DOWNLOAD'],
      sharedLibraries: { all: false, libraryIds: ['library-1', 'library-2'] },
      labelsAllow: ['family-friendly'],
      labelsExclude: ['adult'],
      ageRestriction: { age: 13, restriction: 'ALLOW_ONLY' },
    },
  },
  { client },
);
```

To grant all libraries, send `sharedLibraries: { all: true, libraryIds: [] }`. To clear an age rule, send the required numeric `age` together with `restriction: 'NONE'`.

## Delete a user

> [!WARNING]
>
> Requires the **ADMIN** role. This action cannot be undone.

```typescript theme={null}
import { deleteUserById } from 'komga-sdk';

await deleteUserById({ id: 'user-123' }, { client });
```

## Password management

### Update your password

```typescript theme={null}
import { updatePasswordForCurrentUser } from 'komga-sdk';

await updatePasswordForCurrentUser(
  { passwordUpdateDto: { password: 'new-secure-password' } },
  { client },
);
```

### Update another user's password

> [!WARNING]
>
> Requires the **ADMIN** role.

```typescript theme={null}
import { updatePasswordByUserId } from 'komga-sdk';

await updatePasswordByUserId(
  {
    id: 'user-123',
    passwordUpdateDto: { password: 'new-password-for-user' },
  },
  { client },
);
```

## API key management

API keys provide programmatic access without exposing a password. The key value is returned only by the create call; store it in a secret manager immediately and do not log it.

### List your API keys

```typescript theme={null}
import { getApiKeysForCurrentUser } from 'komga-sdk';

const result = await getApiKeysForCurrentUser({ client });
for (const key of result.data ?? []) {
  console.log(`Key ID: ${key.id}, Comment: ${key.comment}, Created: ${key.createdDate}`);
}
```

### Create an API key

```typescript theme={null}
import { createApiKeyForCurrentUser } from 'komga-sdk';

const result = await createApiKeyForCurrentUser(
  { apiKeyRequestDto: { comment: 'Automation script' } },
  { client },
);

if (result.data) {
  // Save result.data.key now; it is not a password replacement or a retrievable secret.
  const apiKey = result.data.key;
  // Persist apiKey in your secret manager; never log or commit it.
}
```

### Delete an API key

```typescript theme={null}
import { deleteApiKeyByKeyId } from 'komga-sdk';

await deleteApiKeyByKeyId({ keyId: 'key-123' }, { client });
```

### Use an API key for authentication

```typescript theme={null}
import { createKomgaClient } from 'komga-sdk';

const client = createKomgaClient({
  baseUrl: 'https://komga.example.com',
  auth: { type: 'apiKey', key: process.env.KOMGA_API_KEY! },
});
```

## Authentication activity

Activity records include `dateTime`, `success`, and optional `ip`, `source`, `userAgent`, `email`, `apiKeyComment`, and `error` fields.

### Get your activity

```typescript theme={null}
import { getAuthenticationActivityForCurrentUser } from 'komga-sdk';

const result = await getAuthenticationActivityForCurrentUser(
  { page: 0, size: 20, sort: ['dateTime,desc'] },
  { client },
);

for (const activity of result.data?.content ?? []) {
  console.log(`${activity.dateTime}: ${activity.success ? 'Success' : 'Failed'} from ${activity.ip ?? 'unknown IP'}`);
}
```

### Get all activity

> [!WARNING]
>
> Requires the **ADMIN** role.

```typescript theme={null}
import { getAuthenticationActivity } from 'komga-sdk';

const result = await getAuthenticationActivity(
  { page: 0, size: 50, sort: ['dateTime,desc'] },
  { client },
);
const failures = (result.data?.content ?? []).filter((activity) => !activity.success);
console.log(`${failures.length} failed login attempts`);
```

### Get the latest activity for a user

> [!WARNING]
>
> Requires the **ADMIN** role.

```typescript theme={null}
import { getLatestAuthenticationActivityByUserId } from 'komga-sdk';

const result = await getLatestAuthenticationActivityByUserId({ id: 'user-123' }, { client });
if (result.data) {
  console.log(`Last login: ${result.data.dateTime}`);
  console.log(`IP: ${result.data.ip ?? 'unknown'}`);
}
```

## User settings

User settings are key-to-setting maps. See [Client Settings](/guides/client-settings) for precedence and global defaults; the same map operations are available to the current user:

```typescript theme={null}
import { deleteUserSettings, getUserSettings, saveUserSetting } from 'komga-sdk';

const current = await getUserSettings({ client });
for (const [key, setting] of Object.entries(current.data ?? {})) {
  console.log(`${key} = ${setting.value}`);
}

await saveUserSetting(
  { body: { 'reader.pageFit': { value: 'WIDTH' } } },
  { client },
);
await deleteUserSettings(
  { body: ['reader.pageFit', 'reader.background'] },
  { client },
);
```

## Sync points

Delete all sync points, or only those associated with selected API key IDs. Deleting them makes a Kobo or other sync client start from scratch on its next sync:

```typescript theme={null}
import { deleteSyncPointsForCurrentUser } from 'komga-sdk';

await deleteSyncPointsForCurrentUser({ key_id: ['key-123'] }, { client });
```

## Workflows

### Create a restricted user

Create the account, then use the returned ID for any follow-up restriction change:

```typescript theme={null}
import { addUser, updateUserById } from 'komga-sdk';

async function createRestrictedUser(email: string, password: string, libraryIds: string[]) {
  const created = await addUser(
    {
      userCreationDto: {
        email,
        password,
        roles: ['USER', 'PAGE_STREAMING'],
        sharedLibraries: { all: false, libraryIds },
        ageRestriction: { age: 13, restriction: 'ALLOW_ONLY' },
      },
    },
    { client },
  );
  if (!created.data) return;

  return updateUserById(
    {
      id: created.data.id,
      userUpdateDto: { labelsAllow: ['family-friendly'], labelsExclude: ['adult'] },
    },
    { client },
  );
}
```

### Audit failed logins

Group a recent admin activity page by email and flag repeated failures:

```typescript theme={null}
import { getAuthenticationActivity } from 'komga-sdk';

async function auditRecentLogins() {
  const result = await getAuthenticationActivity(
    { page: 0, size: 100, sort: ['dateTime,desc'] },
    { client },
  );
  const byEmail = new Map<string, number>();
  for (const activity of result.data?.content ?? []) {
    if (activity.success) continue;
    const email = activity.email ?? activity.userId ?? 'unknown';
    byEmail.set(email, (byEmail.get(email) ?? 0) + 1);
  }
  return [...byEmail.entries()].filter(([, failures]) => failures >= 3);
}
```

### Rotate an API key

Create the replacement before deleting the old key so a failed create does not interrupt automation:

```typescript theme={null}
import { createApiKeyForCurrentUser, deleteApiKeyByKeyId } from 'komga-sdk';

async function rotateApiKey(
  oldKeyId: string,
  comment: string,
  saveSecret: (key: string) => Promise<void>,
) {
  const created = await createApiKeyForCurrentUser(
    { apiKeyRequestDto: { comment: `${comment} (rotated)` } },
    { client },
  );
  if (!created.data) return;

  await saveSecret(created.data.key);
  await deleteApiKeyByKeyId({ keyId: oldKeyId }, { client });
  return created.data.key;
}
```

## Handle failures

Generated calls expose HTTP failures in `result.error` and `result.response` instead of throwing by default. A 401 indicates missing/invalid credentials; a 403 indicates a role or restriction denied the operation:

```typescript theme={null}
import { getCurrentUser } from 'komga-sdk';

const result = await getCurrentUser(undefined, { client });
if (result.error) {
  console.error('User request failed', result.response?.status, result.error);
}
```

Use `unwrap` and `KomgaApiError` when an exception boundary is a better fit; see [Quickstart](/quickstart).

## Next steps

> **[Authentication](/authentication)**
>
> Configure Basic Auth, API keys, custom headers, and browser credentials.

> **[Client settings](/guides/client-settings)**
>
> Manage global and user-specific reader settings.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.