Skip to content

Books

Upload, list, edit, delete, and send books to an e-reader.

Updated View as Markdown

See Library & Reading for what these operations do in the UI. A book’s id is a slug derived from its title (deduplicated with a hash suffix on collision), not a UUID.

GET /api/books

GETAny session

Lists every book in the library — this endpoint is not scoped to the active profile; ratings, read, and progress on each record reflect whichever profile last had them applied server-side. Use PATCH /api/books/:id to read/write the active profile’s own state, via its returned book object.

Response: { "books": BookRecord[] }

POST /api/books

POSTAny session

Uploads an EPUB. multipart/form-data, one field:

Field Type Required Notes
file file Yes Must end in .epub

Deduplicated by SHA-256 content hash — re-uploading identical bytes returns the existing book instead of creating a new one.

Response: 201 with { "book": BookRecord, "duplicate": false }, or 200 with { "book": BookRecord, "duplicate": true } if the file already exists. 400 if the file isn’t .epub or its metadata can’t be parsed.

PATCH /api/books/:id

PATCHAny session

Updates the active profile’s reading state for one book — rating, read status, and reading position all live per-profile, not on the shared book record.

Request body — all fields optional:

Field Type Notes
rating integer 0–5 0 clears the rating
read boolean
cfi string EPUB CFI (reading position); also stamps lastReadAt
progress number Clamped to 0–100, rounded

Response: { "book": Book } — the book merged with the active profile’s state.

DELETE /api/books/:id

DELETEAdmin only

Deletes the book’s files from storage, removes it from the index, and clears every profile’s reading state for it.

Response: { "ok": true }

GET /api/books/:id/readers

GETAny session

Lists other profiles (excluding the active one) that have read, rated, or made progress on this book — powers the “Readers” panel on a shared install.

Response: { "readers": [{ "profileId": string, "name": string, "color": string, "read": boolean, "progress"?: number, "rating"?: number }] }

POST /api/books/:id/send-to-ereader

POSTAny session

Emails the book’s .epub to the active profile’s e-reader address. See Send to E-Reader for the SMTP and destination-address setup this depends on.

Response: { "ok": true, "sentTo": string }, or 400 if SMTP or the profile’s e-reader email isn’t configured yet, 502 if sending fails.

GET /api/books/:id/metadata/candidates

GETAny session

Looks up metadata candidates on Open Library by the book’s ISBN, title, and author. How many candidates come back is set admin-side — see Settings.

Response: { "candidates": [...] }, or 404 if Open Library has no match.

POST /api/books/:id/metadata

POSTAny session

Applies edited or looked-up metadata. Accepts either JSON or multipart/form-data (use form data to upload a cover file directly).

Request body (JSON)

Field Type Notes
title string
author string
description string
coverUrl string Fetched server-side and stored as the new cover

Request body (form data) — same title/author/description fields, plus a cover file field (must be an image) instead of coverUrl.

Response: { "book": BookRecord }

Navigation

Type to search…

↑↓ navigate↵ selectEsc close