Browse docs

API Reference

HTTP routes exposed by the current Alex application

Alex's web UI uses route handlers under /api. They are application-internal APIs rather than a versioned public SDK, so clients should expect them to evolve with Alex releases.

Authentication

Protected routes accept either:

  • A valid NextAuth session cookie for browser traffic
  • The private x-alex-desktop-auth header injected by the Electron shell for requests to its local server

Do not configure or forward the desktop header yourself. Remote traffic to a desktop Alex instance uses normal email/password authentication.

Roles:

  • admin — User administration and destructive library operations, plus normal reader features
  • user — Library access, personal collections, sharing, and per-user reading progress

Routes under /api/shared/[token] do not require login. Each handler validates the token and, for book resources, verifies membership in that shared collection.

Books

MethodEndpointDescription
GET/api/booksPaginated books. Query: q, type, status, sort, page, limit (maximum 100).
GET/api/books/now-readingCurrent user's in-progress books, most recently read first.
GET/api/books/[id]Book metadata and current user's progress.
GET/api/books/[id]/coverCover image.
GET/api/books/[id]/filePDF or EPUB byte stream with Range support.
GET/api/books/[id]/book.epubEPUB stream at a URL ending in .epub. Returns 400 for non-EPUB books.
GET/api/books/[id]/progressCurrent user's progress row, or null when the book has not been started.
PUT/api/books/[id]/progressUpsert current user's reading progress.

GET /api/books query values:

  • type: all (default), pdf, or epub
  • status: all (default), not_started, reading, or completed
  • sort: added (default), title, author, or read
  • page: defaults to 1
  • limit: defaults to 24 and is capped at 100

Progress request bodies:

// PDF
{ "currentPage": 42, "totalPages": 300 }
// EPUB
{ "epubLocation": "epubcfi(...)", "percentComplete": 37.5 }

There are currently no PATCH or DELETE handlers for /api/books/[id].

Collections

MethodEndpointDescription
GET/api/collectionsCurrent user's collections and book counts. Optional bookId adds containsBook to each result.
POST/api/collectionsCreate with { name, description? }; names are limited to 100 characters.
GET/api/collections/[id]Collection metadata and paginated books. Query: page, limit (maximum 100).
PUT/api/collections/[id]Update { name?, description? }.
DELETE/api/collections/[id]Delete the collection and its memberships, not its books.
POST/api/collections/[id]/booksAdd { bookId }; adding an existing membership is idempotent.
DELETE/api/collections/[id]/books/[bookId]Remove a membership.
GET/api/collections/[id]/now-readingCurrent user's in-progress books within the collection.
GET/api/collections/[id]/shareReturn sharing state and the current token.
POST/api/collections/[id]/shareEnable sharing or return the existing token and URL.
DELETE/api/collections/[id]/shareRevoke sharing and clear the token.

Collection ownership is enforced on every protected collection route.

Users and administration

MethodEndpointDescription
GET/api/usersAdmin-only user list.
POST/api/usersAdmin-only creation with { email, displayName, password, role }. Passwords require at least 6 characters.
DELETE/api/users/[id]Admin-only deletion; an admin cannot delete their own account.
POST/api/admin/library/clearAdmin-only removal of indexed books and covers. The watcher can re-index source files.
POST/api/electron/clear-booksElectron-only reset helper, restricted to an authorized loopback request.

Admin edits to a user's display name, role, or password use authenticated Next.js server actions, not PATCH /api/users/[id].

Real-time updates

MethodEndpointDescription
GET/api/library/eventsAuthenticated Server-Sent Events stream. Emits library-update when the ingestion version changes.

The server checks the version every two seconds and writes a keepalive every 15 seconds.

Public shared collections

MethodEndpointDescription
GET/api/shared/[token]Collection metadata and paginated books. Query: page, limit.
GET/api/shared/[token]/covers/[bookId]Cover for a book in the collection.
GET/api/shared/[token]/books/[bookId]/filePDF or EPUB bytes for a book in the collection.
GET/api/shared/[token]/books/[bookId]/book.epubEPUB bytes for a book in the collection.

There is no separate /api/shared/[token]/books list route; pagination is part of GET /api/shared/[token].

Source-aware streaming

The four private/public /file and /book.epub handlers use one pipeline:

  • source=local — Stream from disk with single-range HTTP support.
  • source=s3 — Spawn watcher-rs s3-stream, forward the Range header, and stream from the configured bucket.

Normal browser reading does not require direct bucket access or bucket CORS.