Skip to content

API Reference ​

Interactive API documentation generated from the OpenAPI spec.

API Version: 0.1.0

auth​


Whether this install still needs setting up​

GET
/api/setup

Lets the sign-in page decide between offering sign-in and offering first-run setup. Public, because there is no account to authenticate with when the answer is yes. Returns a bare boolean on purpose — anything richer would be an unauthenticated window into who exists on this server. True both for a fresh install and for an upgraded one whose users were created by the auth cutover migration and therefore have no password yet.

Responses​

Setup status

application/json
JSON
{
  
"required": true
}

Samples​


Create or recover the first admin​

POST
/api/setup

First-run bootstrap. Available only while nobody on this install can sign in with a password — every later account is created by an admin, and self-registration is disabled. On a fresh install it creates the first user with role admin. On an install upgraded from pre-Better-Auth Libris, where the cutover migration created users with no credential, it attaches the submitted email and password to an EXISTING user (the one already holding that email, else the oldest admin, else the oldest user promoted to admin) rather than creating a duplicate person. Returns 409 once any credential exists, so this is safe to leave mounted.

Request Body​

application/json
JSON
{
  
"email": "string",
  
"password": "string",
  
"name": "string"
}

Responses​

The first admin credential was created

application/json
JSON
{
  
"id": "string",
  
"email": "string",
  
"name": "string",
  
"role": "string",
  
"adopted": true
}

Samples​


health​


Liveness probe​

GET
/api/health/live

Answers 200 as soon as the process is serving HTTP. Performs no database, Redis or event-bus I/O, so it stays cheap at the frequency an orchestrator probes at and never fails because a dependency is down. Use this for container liveness probes; use GET /api/health for readiness and dependency status.

Responses​

The process is up and serving requests

application/json
JSON
{
  
"status": "string",
  
"service": "string"
}

Samples​


Health check (readiness)​

GET
/api/health

Deep readiness check: verifies the database, Redis and the event bus, and answers 503 when any of them is degraded. Returns minimal status for unauthenticated requests; provide a valid API key for per-dependency detail. Costs one database round-trip and one Redis PING per call — probe GET /api/health/live instead for container liveness.

Responses​

All systems healthy

application/json
JSON
{
  
"status": "string",
  
"service": "string",
  
"checks": {
  
  
"database": {
  
  
  
"status": "string",
  
  
  
"latencyMs": 0,
  
  
  
"error": "string"
  
  
},
  
  
"redis": {
  
  
  
"status": "string",
  
  
  
"latencyMs": 0,
  
  
  
"error": "string"
  
  
},
  
  
"eventBus": {
  
  
  
"status": "string",
  
  
  
"latencyMs": 0,
  
  
  
"error": "string"
  
  
}
  
}
}

Samples​


Get full settings page status​

GET
/api/settings/status

Aggregate endpoint that returns health checks, job queue status, failed jobs, app settings, and all credential statuses in a single request. Non-admin users receive only their credential connection status; admin users receive the full diagnostics payload.

Responses​

Aggregated settings status

application/json
JSON
{
  
"health": {
  
  
"status": "string",
  
  
"checks": {
  
  
  
"database": {
  
  
  
  
"status": "string",
  
  
  
  
"latencyMs": 0,
  
  
  
  
"error": "string"
  
  
  
},
  
  
  
"redis": {
  
  
  
  
"status": "string",
  
  
  
  
"latencyMs": 0,
  
  
  
  
"error": "string"
  
  
  
},
  
  
  
"eventBus": {
  
  
  
  
"status": "string",
  
  
  
  
"latencyMs": 0,
  
  
  
  
"error": "string"
  
  
  
}
  
  
}
  
},
  
"queues": {
  
  
"additionalProperties": {
  
  
  
"waiting": 0,
  
  
  
"active": 0,
  
  
  
"completed": 0,
  
  
  
"failed": 0,
  
  
  
"delayed": 0,
  
  
  
"isPaused": true
  
  
}
  
},
  
"failedJobs": {
  
  
"jobs": [
  
  
  
{
  
  
  
  
"id": "string",
  
  
  
  
"queueName": "string",
  
  
  
  
"name": "string",
  
  
  
  
"data": {
  
  
  
  
  
"additionalProperties": "string"
  
  
  
  
},
  
  
  
  
"error": "string",
  
  
  
  
"failedAt": 0,
  
  
  
  
"attemptsMade": 0,
  
  
  
  
"maxAttempts": 0
  
  
  
}
  
  
],
  
  
"total": 0
  
},
  
"settings": {
  
  
"libraryPath": "string",
  
  
"inboxPath": "string",
  
  
"hardcoverMetadataEnabled": true,
  
  
"hardcoverSyncEnabled": true
  
},
  
"credentials": {
  
  
"opds": {
  
  
  
"configured": true,
  
  
  
"service": "string",
  
  
  
"username": "string",
  
  
  
"createdAt": "string",
  
  
  
"updatedAt": "string"
  
  
},
  
  
"kosync": {
  
  
  
"configured": true,
  
  
  
"service": "string",
  
  
  
"username": "string",
  
  
  
"createdAt": "string",
  
  
  
"updatedAt": "string"
  
  
},
  
  
"hardcover": {
  
  
  
"configured": true,
  
  
  
"service": "string",
  
  
  
"username": "string",
  
  
  
"createdAt": "string",
  
  
  
"updatedAt": "string"
  
  
}
  
}
}

Samples​


Get settings​

GET
/api/settings

Return application settings. The response varies by the caller's role: libraryPath and inboxPath are host filesystem paths and are present only for administrators, absent for everyone else. The remaining fields are returned to every authenticated caller.

Responses​

Current settings. Admin callers additionally receive libraryPath and inboxPath.

application/json
JSON
{
  
"kosyncConfigured": true,
  
"hardcoverMetadataEnabled": true,
  
"hardcoverSyncEnabled": true,
  
"libraryPath": "string",
  
"inboxPath": "string"
}

Samples​


Update settings​

PATCH
/api/settings

Update persistent application settings (Hardcover integration toggles). Library and inbox paths are configured via the LIBRIS_LIBRARY_PATH and LIBRIS_INBOX_PATH environment variables and cannot be changed at runtime.

Request Body​

application/json
JSON
{
  
"hardcoverMetadataEnabled": true,
  
"hardcoverSyncEnabled": true
}

Responses​

Settings updated

application/json
JSON
{
  
"updated": [
  
  
"string"
  
]
}

Samples​


List library books​

GET
/api/library

Paginated list of organized books with optional search and filtering. The organized library is shared, so every caller sees every book together with its uploader's display label. uploader.id is an opaque per-install reference, never the uploader's user id; pass a value from GET /api/library/facets as uploaderId to filter. An unrecognised uploaderId returns an empty page.

Parameters​

Query Parameters

page

Page number

Type
integer
Minimum
1
Default
1
limit

Items per page

Type
integer
Minimum
1
Maximum
100
Default
20
author

Filter by author (partial match)

Type
string
Max Length
500
Default
""
genre

Filter by genre (exact, case-insensitive)

Type
string
Max Length
500
Default
""
language

Filter by language code (exact, case-insensitive)

Type
string
Max Length
500
Default
""
series

Filter by series name (exact match)

Type
string
Max Length
500
Default
""
uploaderId

Filter by uploader. Takes the opaque uploaders[].id reference from GET /api/library/facets, not a user id; an unrecognised value returns an empty page.

Type
string
Default
""
q

Full-text search across title, author, and description with typo tolerance

Type
string
Max Length
500
Default
""
sort

Sort order for results

Type
string
Default
"title_asc"

Responses​

Paginated list of books with files

application/json
JSON
{
  
"data": [
  
  
{
  
  
  
"id": "string",
  
  
  
"status": "string",
  
  
  
"title": "string",
  
  
  
"author": "string",
  
  
  
"isbn10": "string",
  
  
  
"isbn13": "string",
  
  
  
"publisher": "string",
  
  
  
"publishedYear": 0,
  
  
  
"language": "string",
  
  
  
"description": "string",
  
  
  
"coverUrl": "string",
  
  
  
"coverPath": "string",
  
  
  
"pageCount": 0,
  
  
  
"series": "string",
  
  
  
"seriesIndex": 0,
  
  
  
"genres": [
  
  
  
  
"string"
  
  
  
],
  
  
  
"tags": [
  
  
  
  
"string"
  
  
  
],
  
  
  
"hardcoverBookId": 0,
  
  
  
"hardcoverEditionId": 0,
  
  
  
"createdBy": "string",
  
  
  
"approvedAt": "string",
  
  
  
"createdAt": "string",
  
  
  
"updatedAt": "string",
  
  
  
"files": [
  
  
  
  
{
  
  
  
  
  
"id": "string",
  
  
  
  
  
"format": "string",
  
  
  
  
  
"originalName": "string",
  
  
  
  
  
"fileSize": "string"
  
  
  
  
}
  
  
  
],
  
  
  
"uploader": {
  
  
  
  
"id": "string",
  
  
  
  
"label": "string"
  
  
  
}
  
  
}
  
],
  
"pagination": {
  
  
"page": 0,
  
  
"limit": 0,
  
  
"total": 0,
  
  
"totalPages": 0
  
}
}

Samples​


Bulk library sync feed​

GET
/api/library/sync

Single paginated endpoint optimised for full-vault mirror clients and CLIs. Returns BookSyncRecord[] bundling each organised book's metadata + a per-book progress aggregate (max % across devices + derived reading status). Optional ?since= filters to books whose metadata or progress changed after that time. uploader.id is an opaque per-install reference, never the uploader's user id.

Parameters​

Query Parameters

page

Page number

Type
integer
Minimum
1
Default
1
limit

Items per page

Type
integer
Minimum
1
Maximum
100
Default
20
since

ISO 8601 timestamp. When set, only return books whose metadata or progress changed after this time. Pass serverTime from the previous successful response.

Type
string
Format
"date-time"

Responses​

Paginated sync records

application/json
JSON
{
  
"data": [
  
  
{
  
  
  
"id": "string",
  
  
  
"status": "string",
  
  
  
"title": "string",
  
  
  
"author": "string",
  
  
  
"isbn10": "string",
  
  
  
"isbn13": "string",
  
  
  
"publisher": "string",
  
  
  
"publishedYear": 0,
  
  
  
"language": "string",
  
  
  
"description": "string",
  
  
  
"coverUrl": "string",
  
  
  
"coverPath": "string",
  
  
  
"pageCount": 0,
  
  
  
"series": "string",
  
  
  
"seriesIndex": 0,
  
  
  
"genres": [
  
  
  
  
"string"
  
  
  
],
  
  
  
"tags": [
  
  
  
  
"string"
  
  
  
],
  
  
  
"hardcoverBookId": 0,
  
  
  
"hardcoverEditionId": 0,
  
  
  
"createdBy": "string",
  
  
  
"approvedAt": "string",
  
  
  
"createdAt": "string",
  
  
  
"updatedAt": "string",
  
  
  
"files": [
  
  
  
  
{
  
  
  
  
  
"id": "string",
  
  
  
  
  
"format": "string",
  
  
  
  
  
"originalName": "string",
  
  
  
  
  
"fileSize": "string"
  
  
  
  
}
  
  
  
],
  
  
  
"uploader": {
  
  
  
  
"id": "string",
  
  
  
  
"label": "string"
  
  
  
},
  
  
  
"progress": {
  
  
  
  
"percentage": 0,
  
  
  
  
"status": "string",
  
  
  
  
"lastDevice": "string",
  
  
  
  
"lastTimestamp": 0,
  
  
  
  
"startedAt": "string",
  
  
  
  
"finishedAt": "string",
  
  
  
  
"pausedAt": "string",
  
  
  
  
"manuallySet": true,
  
  
  
  
"externallySet": true
  
  
  
}
  
  
}
  
],
  
"pagination": {
  
  
"page": 0,
  
  
"limit": 0,
  
  
"total": 0,
  
  
"totalPages": 0
  
},
  
"serverTime": "string"
}

Samples​


Get library filter facets​

GET
/api/library/facets

Returns library filter values. The organized library is shared, so every caller receives every uploader who owns an organized book. Each uploader is identified by an opaque per-install reference plus a display label — never by user id. Pass the reference back as uploaderId on GET /api/library.

Responses​

Distinct authors, genres, languages, series, and uploader values

application/json
JSON
{
  
"authors": [
  
  
"string"
  
],
  
"genres": [
  
  
"string"
  
],
  
"languages": [
  
  
"string"
  
],
  
"series": [
  
  
"string"
  
],
  
"uploaders": [
  
  
{
  
  
  
"id": "string",
  
  
  
"label": "string"
  
  
}
  
]
}

Samples​


Get library book​

GET
/api/library/{id}

Retrieve a single organized book with its files. uploader.id is an opaque per-install reference, never the uploader's user id.

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"

Responses​

Book with files

application/json
JSON
{
  
"id": "string",
  
"status": "string",
  
"title": "string",
  
"author": "string",
  
"isbn10": "string",
  
"isbn13": "string",
  
"publisher": "string",
  
"publishedYear": 0,
  
"language": "string",
  
"description": "string",
  
"coverUrl": "string",
  
"coverPath": "string",
  
"pageCount": 0,
  
"series": "string",
  
"seriesIndex": 0,
  
"genres": [
  
  
"string"
  
],
  
"tags": [
  
  
"string"
  
],
  
"hardcoverBookId": 0,
  
"hardcoverEditionId": 0,
  
"createdBy": "string",
  
"approvedAt": "string",
  
"createdAt": "string",
  
"updatedAt": "string",
  
"files": [
  
  
{
  
  
  
"id": "string",
  
  
  
"format": "string",
  
  
  
"originalName": "string",
  
  
  
"fileSize": "string",
  
  
  
"storagePath": "string",
  
  
  
"checksum": "string"
  
  
}
  
],
  
"uploader": {
  
  
"id": "string",
  
  
"label": "string"
  
},
  
"progress": {
  
  
"percentage": 0,
  
  
"status": "string",
  
  
"lastDevice": "string",
  
  
"lastTimestamp": 0,
  
  
"startedAt": "string",
  
  
"finishedAt": "string",
  
  
"pausedAt": "string",
  
  
"manuallySet": true,
  
  
"externallySet": true
  
}
}

Samples​


Update library book​

PATCH
/api/library/{id}

Edit metadata fields on an organized book

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"

Request Body​

application/json
JSON
{
  
"title": "string",
  
"author": "string",
  
"isbn10": "string",
  
"isbn13": "string",
  
"publisher": "string",
  
"publishedYear": 0,
  
"language": "string",
  
"description": "string",
  
"pageCount": 0,
  
"series": "string",
  
"seriesIndex": 0,
  
"genres": [
  
  
"string"
  
],
  
"tags": [
  
  
"string"
  
],
  
"coverUrl": "string"
}

Responses​

Updated book

application/json
JSON
{
  
"id": "string",
  
"status": "string",
  
"title": "string",
  
"author": "string",
  
"isbn10": "string",
  
"isbn13": "string",
  
"publisher": "string",
  
"publishedYear": 0,
  
"language": "string",
  
"description": "string",
  
"coverUrl": "string",
  
"coverPath": "string",
  
"pageCount": 0,
  
"series": "string",
  
"seriesIndex": 0,
  
"genres": [
  
  
"string"
  
],
  
"tags": [
  
  
"string"
  
],
  
"hardcoverBookId": 0,
  
"hardcoverEditionId": 0,
  
"createdBy": "string",
  
"approvedAt": "string",
  
"createdAt": "string",
  
"updatedAt": "string"
}

Samples​


Get reading progress for a book​

GET
/api/library/{id}/progress

Returns reading progress across all devices by matching book file content hashes to KoReader document identifiers

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"

Responses​

Reading progress entries for the book

application/json
JSON
{
  
"bookId": "string",
  
"progress": [
  
  
{
  
  
  
"document": "string",
  
  
  
"device": "string",
  
  
  
"deviceId": "string",
  
  
  
"progress": "string",
  
  
  
"percentage": 0,
  
  
  
"timestamp": 0
  
  
}
  
]
}

Samples​


Refetch metadata from external sources​

POST
/api/library/{id}/refetch

Delete existing non-file metadata candidates and re-fetch from Hardcover for an organized book. The book stays organized throughout. Idempotent while a refetch for the book is in flight (the repeat is accepted but not enqueued again), and capped at 10 in-flight refetches per user.

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"

Responses​

Refetch enqueued

application/json
JSON
{
  
"status": "string",
  
"bookId": "string",
  
"searchQuery": "string"
}

Samples​


Re-organize a library book​

POST
/api/library/{id}/reorganize

Enqueue a BOOK_ORGANIZE job for an already-organized book so its files are moved to match updated metadata (author/title)

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"

Responses​

Reorganize job enqueued

application/json
JSON
{
  
"message": "string",
  
"bookId": "string"
}

Samples​


Apply refetched metadata to a library book​

POST
/api/library/{id}/apply-metadata

Select metadata fields from refetched candidates and apply them to an organized book. Automatically enqueues a re-organize job to update file paths and re-embed EPUB metadata.

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"

Request Body​

application/json
JSON
{
  
"fields": {
  
  
"additionalProperties": {
  
  
  
"source": "string",
  
  
  
"value": "string"
  
  
}
  
}
}

Responses​

Metadata applied and re-organize job enqueued

application/json
JSON
{
  
"id": "string",
  
"status": "string",
  
"title": "string",
  
"author": "string",
  
"isbn10": "string",
  
"isbn13": "string",
  
"publisher": "string",
  
"publishedYear": 0,
  
"language": "string",
  
"description": "string",
  
"coverUrl": "string",
  
"coverPath": "string",
  
"pageCount": 0,
  
"series": "string",
  
"seriesIndex": 0,
  
"genres": [
  
  
"string"
  
],
  
"tags": [
  
  
"string"
  
],
  
"hardcoverBookId": 0,
  
"hardcoverEditionId": 0,
  
"createdBy": "string",
  
"approvedAt": "string",
  
"createdAt": "string",
  
"updatedAt": "string"
}

Samples​


Clear the manual reading status override​

DELETE
/api/library/{id}/reading-status

Remove any manual override and revert to the computed reading status from KoReader sync data.

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"

Responses​

Override cleared; returns the updated effective progress aggregate

application/json
JSON
{
  
"percentage": 0,
  
"status": "string",
  
"lastDevice": "string",
  
"lastTimestamp": 0,
  
"startedAt": "string",
  
"finishedAt": "string",
  
"pausedAt": "string",
  
"manuallySet": true,
  
"externallySet": true
}

Samples​


Manually set reading status for a book​

PATCH
/api/library/{id}/reading-status

Override the computed reading status with user-supplied values. Sticky against KoReader sync until the user clears the override via DELETE.

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"

Request Body​

application/json
JSON
{
  
"status": "string",
  
"startedAt": "string",
  
"finishedAt": "string",
  
"pausedAt": "string"
}

Responses​

Override applied; returns the updated effective progress aggregate

application/json
JSON
{
  
"percentage": 0,
  
"status": "string",
  
"lastDevice": "string",
  
"lastTimestamp": 0,
  
"startedAt": "string",
  
"finishedAt": "string",
  
"pausedAt": "string",
  
"manuallySet": true,
  
"externallySet": true
}

Samples​


Get library book cover​

GET
/api/library/{id}/cover

Returns the cover image for an organized book, served from the library storage path. Supports ETag-based cache revalidation.

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"

Responses​

Cover image (JPEG, PNG, WebP, or GIF)

Samples​


Download a book file​

GET
/api/library/{id}/download/{fileId}

Streams the ebook file for download, identified by book ID and file ID. Sets Content-Disposition for browser download with the original filename.

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"
fileId*

File UUID

Type
string
Required
Format
"uuid"

Responses​

Ebook file binary stream

Samples​


List inbox books​

GET
/api/inbox

Paginated list of books in inbox or review status. Non-admin users see only books they own.

Parameters​

Query Parameters

page

Page number

Type
integer
Minimum
1
Default
1
limit

Items per page

Type
integer
Minimum
1
Maximum
100
Default
20
q

Full-text search query

Type
string
Max Length
500
Default
""
sort

Sort order for results

Type
string
Default
"detected_newest"

Responses​

Paginated list of inbox books with files

application/json
JSON
{
  
"data": [
  
  
{
  
  
  
"id": "string",
  
  
  
"status": "string",
  
  
  
"title": "string",
  
  
  
"author": "string",
  
  
  
"isbn10": "string",
  
  
  
"isbn13": "string",
  
  
  
"publisher": "string",
  
  
  
"publishedYear": 0,
  
  
  
"language": "string",
  
  
  
"description": "string",
  
  
  
"coverUrl": "string",
  
  
  
"coverPath": "string",
  
  
  
"pageCount": 0,
  
  
  
"series": "string",
  
  
  
"seriesIndex": 0,
  
  
  
"genres": [
  
  
  
  
"string"
  
  
  
],
  
  
  
"tags": [
  
  
  
  
"string"
  
  
  
],
  
  
  
"hardcoverBookId": 0,
  
  
  
"hardcoverEditionId": 0,
  
  
  
"createdBy": "string",
  
  
  
"approvedAt": "string",
  
  
  
"createdAt": "string",
  
  
  
"updatedAt": "string",
  
  
  
"files": [
  
  
  
  
{
  
  
  
  
  
"id": "string",
  
  
  
  
  
"format": "string",
  
  
  
  
  
"originalName": "string",
  
  
  
  
  
"fileSize": "string"
  
  
  
  
}
  
  
  
],
  
  
  
"uploader": {
  
  
  
  
"id": "string",
  
  
  
  
"label": "string"
  
  
  
}
  
  
}
  
],
  
"pagination": {
  
  
"page": 0,
  
  
"limit": 0,
  
  
"total": 0,
  
  
"totalPages": 0
  
}
}

Samples​


Get inbox count​

GET
/api/inbox/count

Returns the number of visible books in inbox or review status. Non-admin counts are owner-scoped.

Responses​

Inbox count

application/json
JSON
{
  
"count": 0
}

Samples​


Inbox processing status​

GET
/api/inbox/processing

Returns the current pipeline stage for visible books being processed. Non-admin results are owner-scoped.

Responses​

Map of bookId to processing stage

application/json
JSON
{
  
"processing": {
  
  
"additionalProperties": {
  
  
  
"stage": "string",
  
  
  
"label": "string"
  
  
}
  
}
}

Samples​


Get inbox book​

GET
/api/inbox/{id}

Retrieve an owned inbox/review book with its files and metadata candidates. Admins may retrieve any book.

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"

Responses​

Book with files and candidates

application/json
JSON
{
  
"id": "string",
  
"status": "string",
  
"title": "string",
  
"author": "string",
  
"isbn10": "string",
  
"isbn13": "string",
  
"publisher": "string",
  
"publishedYear": 0,
  
"language": "string",
  
"description": "string",
  
"coverUrl": "string",
  
"coverPath": "string",
  
"pageCount": 0,
  
"series": "string",
  
"seriesIndex": 0,
  
"genres": [
  
  
"string"
  
],
  
"tags": [
  
  
"string"
  
],
  
"hardcoverBookId": 0,
  
"hardcoverEditionId": 0,
  
"createdBy": "string",
  
"approvedAt": "string",
  
"createdAt": "string",
  
"updatedAt": "string",
  
"possibleDuplicate": {
  
  
"id": "string",
  
  
"title": "string",
  
  
"author": "string",
  
  
"status": "string"
  
},
  
"files": [
  
  
{
  
  
  
"id": "string",
  
  
  
"format": "string",
  
  
  
"originalName": "string",
  
  
  
"fileSize": "string",
  
  
  
"checksum": "string"
  
  
}
  
],
  
"candidates": [
  
  
{
  
  
  
"id": "string",
  
  
  
"source": "string",
  
  
  
"normalized": "string",
  
  
  
"confidence": "string",
  
  
  
"selectedFields": [
  
  
  
  
"string"
  
  
  
]
  
  
}
  
],
  
"uploader": {
  
  
"id": "string",
  
  
"label": "string"
  
}
}

Samples​


Rescan inbox book metadata​

PATCH
/api/inbox/{id}/rescan

Delete existing metadata candidates and re-fetch from external sources. Idempotent while a rescan for the book is in flight, and capped at 10 in-flight metadata jobs per user.

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"

Responses​

Rescan enqueued

application/json
JSON
{
  
"status": "string",
  
"bookId": "string",
  
"searchQuery": "string"
}

Samples​


Get inbox book cover​

GET
/api/inbox/{id}/cover

Returns the cover image for an owned inbox/review book. Admins may retrieve any cover. Tries EPUB extraction first, then falls back to proxying the coverUrl from metadata sources.

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"

Responses​

Cover image (JPEG, PNG, WebP, or GIF)

Samples​


Upload ebook files​

POST
/api/inbox/upload

Upload one or more ebook files (EPUB) to the inbox directory. Files are saved to disk; the file watcher picks them up for processing.

The response splits the batch three ways. uploaded[] is what was written. skipped[] is files whose contents are already on the server — already ingested, or uploaded by anyone and still awaiting the watcher; ingestion deduplicates by checksum, so writing them would drop them silently, and they are not written. A skip is not a failure: the library already holds that book, which is what the caller wanted. errors[] is genuine rejections — unsupported format, over the size limit, not a readable EPUB, or an unsafe filename.

The status is 400 only when every file landed in errors[]. A batch that was entirely skipped is 200: nothing was wrong with the request, there was simply nothing left to do.

Request Body​

multipart/form-data

One or more ebook files

Responses​

Per-file outcome for the batch: uploaded[], skipped[] (already in the library), errors[]. Returned whenever at least one file was written or skipped, even if others errored.

application/json
JSON
{
  
"uploaded": [
  
  
{
  
  
  
"filename": "string",
  
  
  
"size": 0
  
  
}
  
],
  
"skipped": [
  
  
{
  
  
  
"filename": "string",
  
  
  
"reason": "string"
  
  
}
  
],
  
"errors": [
  
  
{
  
  
  
"filename": "string",
  
  
  
"error": "string"
  
  
}
  
]
}

Samples​


Delete book​

DELETE
/api/books/{id}

Delete a book and its associated files from the database and disk

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"

Responses​

Book deleted

Samples​


Approve book metadata​

POST
/api/books/{id}/approve

Select metadata fields from candidates, mark book as organized, and enqueue file organization

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"

Request Body​

application/json
JSON
{
  
"fields": {
  
  
"additionalProperties": {
  
  
  
"source": "string",
  
  
  
"value": "string"
  
  
}
  
}
}

Responses​

Book approved and organize job enqueued

application/json
JSON
{
  
"id": "string",
  
"status": "string",
  
"title": "string",
  
"author": "string",
  
"isbn10": "string",
  
"isbn13": "string",
  
"publisher": "string",
  
"publishedYear": 0,
  
"language": "string",
  
"description": "string",
  
"coverUrl": "string",
  
"coverPath": "string",
  
"pageCount": 0,
  
"series": "string",
  
"seriesIndex": 0,
  
"genres": [
  
  
"string"
  
],
  
"tags": [
  
  
"string"
  
],
  
"hardcoverBookId": 0,
  
"hardcoverEditionId": 0,
  
"createdBy": "string",
  
"approvedAt": "string",
  
"createdAt": "string",
  
"updatedAt": "string"
}

Samples​


Get metadata candidates​

GET
/api/books/{id}/candidates

List metadata candidates fetched from external sources for a book

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Format
"uuid"

Responses​

Book info with metadata candidates

application/json
JSON
{
  
"book": {
  
  
"id": "string",
  
  
"status": "string",
  
  
"title": "string",
  
  
"author": "string"
  
},
  
"candidates": [
  
  
{
  
  
  
"id": "string",
  
  
  
"source": "string",
  
  
  
"normalized": "string",
  
  
  
"confidence": "string",
  
  
  
"selectedFields": [
  
  
  
  
"string"
  
  
  
]
  
  
}
  
]
}

Samples​


series​


List all series​

GET
/api/series

Returns distinct series names with book counts and cover art. Supports search filtering.

Parameters​

Query Parameters

q

Filter series names (partial match)

Type
string
Max Length
500
Default
""

Responses​

Series list

application/json
JSON
{
  
"data": [
  
  
{
  
  
  
"name": "string",
  
  
  
"bookCount": 0,
  
  
  
"coverUrl": "string",
  
  
  
"coverPath": "string",
  
  
  
"coverBookId": "string"
  
  
}
  
],
  
"total": 0
}

Samples​


Get books in a series​

GET
/api/series/{name}

Returns all books in the given series ordered by series_index (nulls last).

Parameters​

Path Parameters

name*

Series name

Type
string
Required

Responses​

Series detail with books

application/json
JSON
{
  
"series": "string",
  
"books": [
  
  
{
  
  
  
"id": "string",
  
  
  
"title": "string",
  
  
  
"author": "string",
  
  
  
"series": "string",
  
  
  
"seriesIndex": 0,
  
  
  
"coverUrl": "string",
  
  
  
"coverPath": "string",
  
  
  
"genres": [
  
  
  
  
"string"
  
  
  
],
  
  
  
"tags": [
  
  
  
  
"string"
  
  
  
],
  
  
  
"pageCount": 0,
  
  
  
"publishedYear": 0,
  
  
  
"files": [
  
  
  
  
{
  
  
  
  
  
"id": "string",
  
  
  
  
  
"format": "string",
  
  
  
  
  
"originalName": "string",
  
  
  
  
  
"fileSize": "string"
  
  
  
  
}
  
  
  
]
  
  
}
  
],
  
"total": 0
}

Samples​


search​


Search suggestions for command palette​

GET
/api/search/suggest

Lightweight prefix search returning up to 8 results for autocomplete. Matches every organized book (the library is shared) plus the caller's own review books, so you can find an upload of yours that is still awaiting metadata approval. Other users' review books are never returned; admins see all of them.

Parameters​

Query Parameters

q*

Search prefix

Type
string
Required
Min Length
1
Max Length
500

Responses​

Search suggestions

application/json
JSON
{
  
"data": [
  
  
{
  
  
  
"id": "string",
  
  
  
"title": "string",
  
  
  
"author": "string",
  
  
  
"status": "string",
  
  
  
"coverUrl": "string"
  
  
}
  
]
}

Samples​


dashboard​


Get dashboard data​

GET
/api/dashboard

Returns currently reading books, recently added, inbox count, library stats, and pipeline status. currentlyReading, inboxCount and stats.processingCount are per-user (reading progress is private, and inbox/review books are pre-approval uploads); recentlyAdded and the rest of stats describe the shared organized library, so stats.totalFileSize counts only organized books' files. pipeline holds install-wide queue counts and is therefore admin-only: it is an empty object for everyone else. Admins receive the install-wide inbox count and processing count.

Responses​

Dashboard data

application/json
JSON
{
  
"currentlyReading": [
  
  
{
  
  
  
"id": "string",
  
  
  
"title": "string",
  
  
  
"author": "string",
  
  
  
"coverPath": "string",
  
  
  
"percentage": 0,
  
  
  
"device": "string",
  
  
  
"lastRead": 0
  
  
}
  
],
  
"recentlyAdded": [
  
  
{
  
  
  
"id": "string",
  
  
  
"title": "string",
  
  
  
"author": "string",
  
  
  
"coverPath": "string",
  
  
  
"createdAt": "string"
  
  
}
  
],
  
"inboxCount": 0,
  
"stats": {
  
  
"totalBooks": 0,
  
  
"totalAuthors": 0,
  
  
"topGenre": "string",
  
  
"totalFileSize": 0,
  
  
"processingCount": 0
  
},
  
"pipeline": {
  
  
"additionalProperties": {
  
  
  
"waiting": 0,
  
  
  
"active": 0,
  
  
  
"completed": 0,
  
  
  
"failed": 0,
  
  
  
"delayed": 0
  
  
}
  
}
}

Samples​


stats​


Get reading statistics​

GET
/api/stats

Returns reading analytics for the stats page: finished-book counts, genre distribution, reading streak, average finish time, yearly pages-read heatmap, books finished per month, reading velocity (7-day moving avg), top authors, days-to-finish histogram, and library growth.

Parameters​

Query Parameters

year

Calendar year for the daily-pages heatmap (YYYY). Defaults to the current year.

Type
integer
Example2026
Minimum
1970
Maximum
2100

Responses​

Reading statistics

application/json
JSON
{
  
"booksFinished": {
  
  
"allTime": 0,
  
  
"thisYear": 0,
  
  
"thisMonth": 0
  
},
  
"genreDistribution": [
  
  
{
  
  
  
"genre": "string",
  
  
  
"count": 0
  
  
}
  
],
  
"streak": {
  
  
"current": 0,
  
  
"longest": 0
  
},
  
"avgDaysToFinish": 0,
  
"pagesHeatmap": {
  
  
"year": 0,
  
  
"days": [
  
  
  
{
  
  
  
  
"day": "string",
  
  
  
  
"pages": 0
  
  
  
}
  
  
]
  
},
  
"finishedPerMonth": [
  
  
{
  
  
  
"month": "string",
  
  
  
"count": 0
  
  
}
  
],
  
"readingVelocity": [
  
  
{
  
  
  
"day": "string",
  
  
  
"avgPages": 0
  
  
}
  
],
  
"topAuthors": [
  
  
{
  
  
  
"author": "string",
  
  
  
"count": 0
  
  
}
  
],
  
"daysToFinishBuckets": [
  
  
{
  
  
  
"bucket": "string",
  
  
  
"count": 0
  
  
}
  
],
  
"libraryGrowth": [
  
  
{
  
  
  
"month": "string",
  
  
  
"cumulative": 0
  
  
}
  
]
}

Samples​


Get reading status counts​

GET
/api/reading-status/counts

Returns the count of organized books in each reading status (unread, reading, finished, paused).

Responses​

Status counts

application/json
JSON
{
  
"unread": 0,
  
"reading": 0,
  
"finished": 0,
  
"paused": 0
}

Samples​


List books by reading status​

GET
/api/reading-status/{status}

Returns a paginated list of organized books filtered by the given reading status, with optional search and sorting.

Parameters​

Path Parameters

status*

Reading status to filter by

Type
string
Required
Valid values
"unread""reading""finished""paused"

Query Parameters

page

Page number (1-based)

Type
integer
Minimum
1
Default
1
limit

Number of items per page

Type
integer
Minimum
1
Maximum
100
Default
20
sort

Sort field

Type
string
Default
"title"
order

Sort direction

Type
string
Default
"asc"
search

Full-text search query

Type
string
Max Length
500
Default
""

Responses​

Paginated list of books with reading progress

application/json
JSON
{
  
"data": [
  
  
{
  
  
  
"id": "string",
  
  
  
"title": "string",
  
  
  
"author": "string",
  
  
  
"coverPath": "string",
  
  
  
"isbn13": "string",
  
  
  
"isbn10": "string",
  
  
  
"genres": [
  
  
  
  
"string"
  
  
  
],
  
  
  
"pageCount": 0,
  
  
  
"percentage": 0,
  
  
  
"device": "string",
  
  
  
"lastReadAt": "string",
  
  
  
"readingStatus": "string"
  
  
}
  
],
  
"pagination": {
  
  
"page": 0,
  
  
"limit": 0,
  
  
"total": 0,
  
  
"totalPages": 0
  
}
}

Samples​


Check service credentials​

GET
/api/credentials/{service}

Check whether credentials are configured for a service (opds, kosync, or hardcover). Returns the username and timestamps if configured.

Parameters​

Path Parameters

service*

Service name

Type
string
Required
Valid values
"kosync""hardcover"

Responses​

Credential status

application/json
JSON
{
  
"configured": true,
  
"service": "string",
  
"username": "string",
  
"createdAt": "string",
  
"updatedAt": "string"
}

Samples​


Set service credentials​

PUT
/api/credentials/{service}

Set or update credentials for a service. Passwords for opds/kosync are bcrypt-hashed. Hardcover tokens are sealed with reversible encryption.

Parameters​

Path Parameters

service*

Service name

Type
string
Required
Valid values
"kosync""hardcover"

Request Body​

application/json
JSON
{
  
"username": "string",
  
"password": "string"
}

Responses​

Credentials updated

application/json
JSON
{
  
"service": "string",
  
"username": "string",
  
"updated": true
}

Samples​


Delete service credentials​

DELETE
/api/credentials/{service}

Remove stored credentials for a service (opds, kosync, or hardcover).

Parameters​

Path Parameters

service*

Service name

Type
string
Required
Valid values
"kosync""hardcover"

Responses​

Credentials deleted

application/json
JSON
{
  
"service": "string",
  
"deleted": true
}

Samples​


List your app passwords​

GET
/api/app-passwords

Every credential issued to the signed-in user, for the Connected Devices list. The credentials themselves are hashed and never returned — only their labels, prefixes and last-used timestamps.

Responses​

The caller's app passwords

application/json
JSON
{
  
"keys": [
  
  
{
  
  
  
"id": "string",
  
  
  
"name": "string",
  
  
  
"start": "string",
  
  
  
"enabled": true,
  
  
  
"createdAt": "string",
  
  
  
"lastRequest": "string"
  
  
}
  
]
}

Samples​


Issue an app password​

POST
/api/app-passwords

Create a credential for an e-reader, OPDS client or script. The plaintext is in the response and is never retrievable again — show it to the user immediately.

Request Body​

application/json
JSON
{
  
"name": "string"
}

Responses​

The new app password, including its plaintext

application/json
JSON
{
  
"id": "string",
  
"name": "string",
  
"start": "string",
  
"enabled": true,
  
"createdAt": "string",
  
"lastRequest": "string",
  
"key": "string"
}

Samples​


Revoke an app password​

DELETE
/api/app-passwords/{id}

Revoke a credential immediately — there is no session cache, so the next request using it fails. Revoking someone else's credential returns 404 rather than 403, so ids cannot be probed for existence.

Parameters​

Path Parameters

id*

Credential id

Type
string
Required

Responses​

Revoked

Samples​


Job queue status​

GET
/api/jobs/status

Return job counts per queue (waiting, active, completed, failed, delayed) plus whether the queue itself is paused. A paused queue keeps its jobs in waiting — isPaused is a queue-level flag, not a job count.

Responses​

Queue status counts

application/json
JSON
{
  
"queues": {
  
  
"additionalProperties": {
  
  
  
"waiting": 0,
  
  
  
"active": 0,
  
  
  
"completed": 0,
  
  
  
"failed": 0,
  
  
  
"delayed": 0,
  
  
  
"isPaused": true
  
  
}
  
}
}

Samples​


List failed jobs​

GET
/api/jobs/failed

Return failed jobs across all queues with job ID, queue name, error message, timestamps, and attempt count

Responses​

List of failed jobs

application/json
JSON
{
  
"jobs": [
  
  
{
  
  
  
"id": "string",
  
  
  
"queueName": "string",
  
  
  
"name": "string",
  
  
  
"data": {
  
  
  
  
"additionalProperties": "string"
  
  
  
},
  
  
  
"error": "string",
  
  
  
"failedAt": 0,
  
  
  
"attemptsMade": 0,
  
  
  
"maxAttempts": 0
  
  
}
  
],
  
"total": 0
}

Samples​


List jobs across all queues​

GET
/api/jobs

Browse recent jobs across all queues with filtering by queue name and status. Supports pagination via page/pageSize query params. total is the exact number of matching jobs. Browsing is bounded: every selected queue/status board is read in BullMQ's native order up to a share of a 10000-job window (fewer selected boards means a deeper per-board window), and the merged result is ordered by creation time. truncated is true when any board holds more matching jobs than the window reaches; those jobs cannot be paged to.

Parameters​

Query Parameters

queue

Filter by queue name (e.g. book-detected)

Type
string
status

Filter by job status

Type
string
Valid values
"completed""active""waiting""failed""delayed"
page

Page number

Type
integer
Minimum
1
Default
1
pageSize

Items per page (max 100)

Type
integer
Minimum
1
Maximum
100
Default
20

Responses​

Paginated list of jobs

application/json
JSON
{
  
"jobs": [
  
  
{
  
  
  
"id": "string",
  
  
  
"queueName": "string",
  
  
  
"name": "string",
  
  
  
"data": {
  
  
  
  
"additionalProperties": "string"
  
  
  
},
  
  
  
"status": "string",
  
  
  
"progress": 0,
  
  
  
"returnValue": "string",
  
  
  
"failedReason": "string",
  
  
  
"stacktrace": [
  
  
  
  
"string"
  
  
  
],
  
  
  
"attemptsMade": 0,
  
  
  
"maxAttempts": 0,
  
  
  
"timestamp": 0,
  
  
  
"processedOn": 0,
  
  
  
"finishedOn": 0,
  
  
  
"duration": 0
  
  
}
  
],
  
"total": 0,
  
"page": 0,
  
"pageSize": 0,
  
"totalPages": 0,
  
"truncated": true
}

Samples​


Get job details​

GET
/api/jobs/{id}

Return full details for a specific job including stack trace, duration, progress, timestamps, return value, and payload data. Requires queueName since BullMQ job IDs are auto-incremented per queue and not unique across queues.

Parameters​

Path Parameters

id*

Job ID

Type
string
Required
Min Length
1

Query Parameters

queueName*

Queue this job belongs to (e.g. book-fetch-metadata)

Type
string
Required
Min Length
1

Responses​

Job details

application/json
JSON
{
  
"id": "string",
  
"queueName": "string",
  
"name": "string",
  
"data": {
  
  
"additionalProperties": "string"
  
},
  
"status": "string",
  
"progress": 0,
  
"returnValue": "string",
  
"failedReason": "string",
  
"stacktrace": [
  
  
"string"
  
],
  
"attemptsMade": 0,
  
"maxAttempts": 0,
  
"timestamp": 0,
  
"processedOn": 0,
  
"finishedOn": 0,
  
"duration": 0
}

Samples​


Get job logs​

GET
/api/jobs/{id}/logs

Return log lines stored via BullMQ job.log() for a specific job. Logs are stored in Redis per job and provide a timeline of job execution. Requires queueName since BullMQ job IDs are auto-incremented per queue and not unique across queues.

Parameters​

Path Parameters

id*

Job ID

Type
string
Required
Min Length
1

Query Parameters

queueName*

Queue this job belongs to (e.g. book-fetch-metadata)

Type
string
Required
Min Length
1

Responses​

Job logs

application/json
JSON
{
  
"jobId": "string",
  
"logs": [
  
  
"string"
  
],
  
"count": 0
}

Samples​


Retry a failed job​

POST
/api/jobs/{id}/retry

Retry a specific failed job by ID. Requires queueName since BullMQ job IDs are auto-incremented per queue and not unique across queues.

Parameters​

Path Parameters

id*

Job ID to retry

Type
string
Required
Min Length
1

Query Parameters

queueName*

Queue this job belongs to (e.g. book-fetch-metadata)

Type
string
Required
Min Length
1

Responses​

Job retried successfully

application/json
JSON
{
  
"success": true,
  
"jobId": "string",
  
"queueName": "string"
}

Samples​


Pause a queue​

POST
/api/jobs/queues/{name}/pause

Pause a specific queue by name. New jobs will not be processed until resumed.

Parameters​

Path Parameters

name*

Queue name (e.g. book-detected)

Type
string
Required
Min Length
1

Responses​

Queue paused

application/json
JSON
{
  
"success": true,
  
"queue": "string",
  
"paused": true
}

Samples​


Resume a queue​

POST
/api/jobs/queues/{name}/resume

Resume a paused queue. Jobs will begin processing again.

Parameters​

Path Parameters

name*

Queue name

Type
string
Required
Min Length
1

Responses​

Queue resumed

application/json
JSON
{
  
"success": true,
  
"queue": "string",
  
"paused": true
}

Samples​


Clean failed jobs from a queue​

POST
/api/jobs/queues/{name}/clean

Remove all failed jobs from a specific queue.

Parameters​

Path Parameters

name*

Queue name

Type
string
Required
Min Length
1

Responses​

Failed jobs cleaned

application/json
JSON
{
  
"success": true,
  
"queue": "string",
  
"removed": 0
}

Samples​


Drain a queue​

POST
/api/jobs/queues/{name}/drain

Remove all waiting, prioritized, and delayed jobs from a queue. Active jobs keep running, and delayed jobs owned by a Job Scheduler are kept — draining a scheduler queue does not unschedule its recurring work.

Parameters​

Path Parameters

name*

Queue name

Type
string
Required
Min Length
1

Responses​

Queue drained

application/json
JSON
{
  
"success": true,
  
"queue": "string"
}

Samples​


Get Hardcover connection status​

GET
/api/hardcover/status

Check whether a Hardcover credential is configured, verify the token with the Hardcover API, and return the connected username and last sync timestamp. The live token check is cached per user for 30 seconds.

Responses​

Connection status

application/json
JSON
{
  
"connected": true,
  
"username": "string",
  
"lastSyncAt": "string",
  
"error": "string"
}

Samples​


Trigger Hardcover sync​

POST
/api/hardcover/sync

Enqueue a user-scoped job to synchronize reading progress and ratings with the Hardcover service. Global metadata maintenance runs only on scheduled jobs. Requires a configured Hardcover credential. Idempotent while a sync for the user is already queued or running.

Responses​

Sync job enqueued

application/json
JSON
{
  
"message": "string"
}

Samples​


List Hardcover sync log entries​

GET
/api/hardcover/sync/log

Return recent Hardcover sync log entries joined with book titles, sorted by last synced timestamp descending.

Parameters​

Query Parameters

limit

Maximum entries to return

Type
integer
Minimum
1
Maximum
100
Default
20

Responses​

Array of sync log entries

application/json
JSON
[
  
{
  
  
"bookId": "string",
  
  
"bookTitle": "string",
  
  
"status": "string",
  
  
"progress": "string",
  
  
"rating": "string",
  
  
"syncedAt": "string"
  
}
]

Samples​


Search Hardcover for metadata​

GET
/api/hardcover/search

Run a free-text search against Hardcover and return up to 5 normalized metadata candidates. Used by the UI when auto-fetched metadata is wrong or missing — the user picks a result to autofill the edit form. The search always spends the caller's own Hardcover token; a caller with no Hardcover credential of their own gets 503 and no request is made to Hardcover, matching what GET /api/hardcover/status reports for them.

Parameters​

Query Parameters

q*

Search query — title, author, ISBN, or any combination

Type
string
Required
Min Length
2
Max Length
200

Responses​

Search results (may be empty)

application/json
JSON
{
  
"results": [
  
  
{
  
  
  
"source": "string",
  
  
  
"normalized": "string",
  
  
  
"confidence": 0
  
  
}
  
]
}

Samples​


events​


Realtime event stream (WebSocket)​

GET
/api/events

Upgrades to a WebSocket carrying job, pipeline and Hardcover sync events for the caller. Events are scoped to the authenticated principal; an admin additionally receives install-wide job events. The server closes the socket with application code 4401 when the session behind it is revoked (ban, sign-out, removal) and 4409 when the caller's identity or role changed and the client should re-dial to be re-scoped. Connections are capped per principal and process-wide.

Parameters​

Query Parameters

bookId

Only deliver events concerning this book.

Type
string

Responses​

Switching Protocols - the WebSocket is established.

Samples​


Authenticate via KOReader headers​

GET
/kosync/users/auth

KOReader sends credentials via x-auth-user (username) and x-auth-key (md5-hashed password) headers. Returns the userkey for subsequent sync requests. These non-standard headers are validated in the handler.

Responses​

Authentication successful

application/json
JSON
{
  
"authorized": "string",
  
"userkey": "string"
}

Samples​


Authenticate via JSON body​

POST
/kosync/users/auth

Validate KoSync credentials provided as a JSON body. Returns the md5-hashed password as the userkey for subsequent sync requests. The rate limiter buckets POST attempts by the username in this body — never by x-auth-user — so a body over 8 KB, which no KOReader login sends, is refused with 413 rather than let through unbucketed.

Request Body​

application/json
JSON
{
  
"username": "string",
  
"password": "string"
}

Responses​

Authentication successful

application/json
JSON
{
  
"authorized": "string",
  
"userkey": "string"
}

Samples​


Register a KoSync user (disabled)​

POST
/kosync/users/create

KOReader calls this endpoint to register a new user. Registration is disabled in Libris — credentials must be set via the Libris dashboard. Always returns 409.

Request Body​

application/json
JSON
{
  
"username": "string",
  
"password": "string"
}

Responses​

Registration is disabled; set credentials in the Libris dashboard

Samples​


Get reading progress​

GET
/kosync/syncs/progress/{document}

Retrieve the most recent reading progress entry for a document identified by its hash. Returns 404 if no progress has been recorded for this document.

Parameters​

Path Parameters

document*

Document hash (content or original)

Type
string
Required
Min Length
1

Responses​

Reading progress

application/json
JSON
{
  
"document": "string",
  
"progress": "string",
  
"percentage": 0,
  
"device": "string",
  
"device_id": "string",
  
"timestamp": 0
}

Samples​


Upsert reading progress​

PUT
/kosync/syncs/progress

Create or update reading progress for a document/device pair. Also appends to the progress history table (fire-and-forget). Returns the persisted progress entry. Credentials are verified on every request, but only failed checks count against the per-user brute-force budget, so a device that keeps syncing never throttles itself.

Request Body​

application/json
JSON
{
  
"document": "string",
  
"progress": "string",
  
"device": "string",
  
"percentage": 0,
  
"device_id": "string"
}

Responses​

Persisted reading progress

application/json
JSON
{
  
"document": "string",
  
"progress": "string",
  
"percentage": 0,
  
"device": "string",
  
"device_id": "string",
  
"timestamp": 0
}

Samples​


OPDS root catalog​

GET
/opds

Returns the top-level OPDS navigation feed with links to New Arrivals, All Books, Genres, Series, and Languages sub-catalogs, plus an OpenSearch descriptor link.

Responses​

OPDS navigation feed (Atom XML)

application/atom+xml;profile=opds-catalog;kind=navigation
XML

Samples​


List all books (OPDS)​

GET
/opds/books

Returns a paginated OPDS acquisition feed of all organized books, sorted alphabetically by title. Supports page-based pagination via query parameter.

Parameters​

Query Parameters

page

Page number (1-based)

Type
integer
Example1
Minimum
1

Responses​

OPDS acquisition feed with book entries (Atom XML)

application/atom+xml;profile=opds-catalog;kind=acquisition
XML

Samples​


Get a single book entry (OPDS)​

GET
/opds/books/{id}

Returns an OPDS entry document for a single organized book, including metadata and acquisition links for available file formats.

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Example"550e8400-e29b-41d4-a716-446655440000"
Format
"uuid"

Responses​

OPDS entry document for the book (Atom XML)

application/atom+xml;type=entry;profile=opds-catalog
XML

Samples​


Books by author (OPDS)​

GET
/opds/authors/{slug}

Returns a paginated OPDS acquisition feed of books by a specific author, identified by a URL-friendly slug derived from the author name.

Parameters​

Path Parameters

slug*

URL-friendly author slug

Type
string
Required
Min Length
1
Max Length
500

Query Parameters

page

Page number (1-based)

Type
integer
Example1
Minimum
1

Responses​

OPDS acquisition feed of books by the author (Atom XML)

application/atom+xml;profile=opds-catalog;kind=acquisition
XML

Samples​


List genres (OPDS)​

GET
/opds/genres

Returns an OPDS navigation feed listing all genres found in organized books, each linking to a genre-specific acquisition feed.

Responses​

OPDS navigation feed of genres (Atom XML)

application/atom+xml;profile=opds-catalog;kind=navigation
XML

Samples​


Books by genre (OPDS)​

GET
/opds/genres/{slug}

Returns a paginated OPDS acquisition feed of books in a specific genre, identified by a URL-friendly slug.

Parameters​

Path Parameters

slug*

URL-friendly genre slug

Type
string
Required
Min Length
1
Max Length
500

Query Parameters

page

Page number (1-based)

Type
integer
Example1
Minimum
1

Responses​

OPDS acquisition feed of books in the genre (Atom XML)

application/atom+xml;profile=opds-catalog;kind=acquisition
XML

Samples​


List series (OPDS)​

GET
/opds/series

Returns an OPDS navigation feed listing all book series found in organized books, each linking to a series-specific acquisition feed.

Responses​

OPDS navigation feed of series (Atom XML)

application/atom+xml;profile=opds-catalog;kind=navigation
XML

Samples​


Books in a series (OPDS)​

GET
/opds/series/{name}

Returns a paginated OPDS acquisition feed of books in a specific series, ordered by series index.

Parameters​

Path Parameters

name*

Series name

Type
string
Required
Min Length
1
Max Length
500

Query Parameters

page

Page number (1-based)

Type
integer
Example1
Minimum
1

Responses​

OPDS acquisition feed of books in the series (Atom XML)

application/atom+xml;profile=opds-catalog;kind=acquisition
XML

Samples​


List languages (OPDS)​

GET
/opds/languages

Returns an OPDS navigation feed listing only the languages present in organized books (canonical ISO 639-1 codes shown as full names), each linking to a language-specific acquisition feed.

Responses​

OPDS navigation feed of languages (Atom XML)

application/atom+xml;profile=opds-catalog;kind=navigation
XML

Samples​


Books by language (OPDS)​

GET
/opds/languages/{code}

Returns a paginated OPDS acquisition feed of books in a specific language, identified by its ISO 639-1 code (case-insensitive).

Parameters​

Path Parameters

code*

Language code, e.g. 'en'

Type
string
Required
Min Length
1
Max Length
35

Query Parameters

page

Page number (1-based)

Type
integer
Example1
Minimum
1

Responses​

OPDS acquisition feed of books in the language (Atom XML)

application/atom+xml;profile=opds-catalog;kind=acquisition
XML

Samples​


New arrivals (OPDS)​

GET
/opds/new

Returns a paginated OPDS acquisition feed of recently added books, sorted by creation date (newest first).

Parameters​

Query Parameters

page

Page number (1-based)

Type
integer
Example1
Minimum
1

Responses​

OPDS acquisition feed of new arrivals (Atom XML)

application/atom+xml;profile=opds-catalog;kind=acquisition
XML

Samples​


Search books or get OpenSearch descriptor (OPDS)​

GET
/opds/search

When called with a q query parameter, returns a paginated OPDS acquisition feed of matching books using full-text search. Without q, returns an OpenSearch description document that OPDS clients use for search discovery.

Parameters​

Query Parameters

q

Search query. Omit to get the OpenSearch description document.

Type
string
Max Length
500
page

Page number (1-based, only used with q)

Type
integer
Example1
Minimum
1

Responses​

OPDS acquisition feed of search results (Atom XML) or OpenSearch description (XML)

XML

Samples​


Get book cover image (OPDS)​

GET
/opds/covers/{id}

Returns the cover image for an organized book. Used by OPDS clients to display book thumbnails. Supports ETag-based cache revalidation.

Parameters​

Path Parameters

id*

Book UUID

Type
string
Required
Example"550e8400-e29b-41d4-a716-446655440000"
Format
"uuid"

Responses​

Cover image (JPEG, PNG, WebP, or GIF)

Samples​


Download a book file (OPDS)​

GET
/opds/download/{fileId}

Streams an ebook file for download, identified by its file ID. The file must belong to an organized book. Sets Content-Disposition for browser/e-reader download with the original filename.

Parameters​

Path Parameters

fileId*

Book file UUID

Type
string
Required
Example"550e8400-e29b-41d4-a716-446655440000"
Format
"uuid"

Responses​

Ebook file binary stream

Samples​


Powered by VitePress OpenAPI