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",
  
  
  
"possibleDuplicateOf": "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",
  
  
  
"possibleDuplicateOf": "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",
  
"possibleDuplicateOf": "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",
  
"possibleDuplicateOf": "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.

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",
  
"possibleDuplicateOf": "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",
  
  
  
"possibleDuplicateOf": "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",
  
"possibleDuplicateOf": "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

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",
  
"possibleDuplicateOf": "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 waitingisPaused 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.

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
}

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 and delayed jobs from a queue. Active jobs are not affected.

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.

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.

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 attempts by the username in this body, 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.

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