API Endpoint Reference
Routing ownership map: see docs/d2/api-routing.svg (source: docs/d2/api-routing.d2) for a visual overview of which paths Caddy sends to the backend directly vs. through SvelteKit, with auth levels colour-coded.
All traffic enters through Caddy :443. Caddy routes a subset of paths directly to the Go backend (bypassing SvelteKit); everything else goes to SvelteKit, which enforces auth before proxying onward.
Health / Version
| Method |
Path |
Auth |
Description |
GET |
/health |
— |
Liveness probe. Returns {"ok":true}. |
GET |
/api/version |
— |
Build version + commit hash. |
Scrape Jobs (admin)
| Method |
Path |
Auth |
Description |
POST |
/scrape |
admin |
Enqueue full catalogue scrape. |
POST |
/scrape/book |
admin |
Enqueue single-book scrape {url}. |
POST |
/scrape/book/range |
admin |
Enqueue range scrape {url, from, to?}. |
GET |
/api/scrape/status |
admin |
Current job status. |
GET |
/api/scrape/tasks |
admin |
All scrape task records. |
POST |
/api/cancel-task/{id} |
admin |
Cancel a pending task. |
Browse / Catalogue
| Method |
Path |
Auth |
Description |
GET |
/api/browse |
— |
Live novelfire.net browse (MinIO page-1 cache). Legacy — used by save-browse subcommand. |
GET |
/api/catalogue |
— |
Primary browse endpoint. Meilisearch-backed, paginated. Params: q, page, limit, genre, status, sort (popular|new|update|rank|top-rated). Falls back to empty when Meilisearch is not configured. |
GET |
/api/search |
— |
Full-text search: Meilisearch local results merged with live novelfire.net remote results. Param: q (≥ 2 chars). Used by iOS app. |
GET |
/api/ranking |
— |
Top-ranked novels from PocketBase. |
GET |
/api/cover/{domain}/{slug} |
— |
Proxy cover image from MinIO (redirect to presigned URL). |
Book / Chapter Content
| Method |
Path |
Auth |
Description |
GET |
/api/book-preview/{slug} |
— |
Returns stored metadata + chapter list, or enqueues a scrape task (202) if unknown. |
GET |
/api/chapter-text/{slug}/{n} |
— |
Chapter content as plain text (markdown stripped). |
GET |
/api/chapter-markdown/{slug}/{n} |
— |
Chapter content as raw markdown from MinIO. |
POST |
/api/reindex/{slug} |
admin |
Rebuild chapters_idx from MinIO objects. |
Audio
| Method |
Path |
Auth |
Description |
POST |
/api/audio/{slug}/{n} |
— |
Trigger Kokoro TTS generation. Body: {voice?}. Returns 200 {status:"done"} if cached, 202 {task_id, status} if enqueued. |
GET |
/api/audio/status/{slug}/{n} |
— |
Poll audio generation status. Param: voice. Returns {status, task_id?, error?}. |
GET |
/api/audio-proxy/{slug}/{n} |
— |
Redirect to presigned MinIO audio URL. |
GET |
/api/voices |
— |
List available Kokoro voices. Returns {voices:[]} on error. |
Presigned URLs
All presign endpoints return a 302 redirect to a short-lived MinIO presigned
URL. The URL is cached in Valkey (TTL ~55 min) to avoid regenerating on every
request.
| Method |
Path |
Auth |
Description |
GET |
/api/presign/chapter/{slug}/{n} |
— |
Presigned URL for chapter markdown object. |
GET |
/api/presign/audio/{slug}/{n} |
— |
Presigned URL for audio MP3. Param: voice. |
GET |
/api/presign/voice-sample/{voice} |
— |
Presigned URL for voice sample MP3. |
GET |
/api/presign/avatar-upload/{userId} |
user |
Presigned PUT URL for avatar upload. |
GET |
/api/presign/avatar/{userId} |
— |
Presigned GET URL for avatar image. |
Reading Progress
Session-scoped (anonymous via cookie session ID, or tied to authenticated user).
| Method |
Path |
Auth |
Description |
GET |
/api/progress |
— |
Get all reading progress for the current session/user. |
POST |
/api/progress/{slug} |
— |
Set progress. Body: {chapter}. |
DELETE |
/api/progress/{slug} |
— |
Delete progress for a book. |
Notes
- Auth: The backend does not enforce auth itself — the SvelteKit UI layer enforces admin/user guards before proxying requests. The backend trusts all incoming requests.
/api/catalogue vs /api/browse: /api/catalogue is the primary UI endpoint (Meilisearch, always-local, fast). /api/browse hits or caches the live novelfire.net browse page and is only used internally by the save-browse subcommand.
- Meilisearch fallback: When
MEILI_URL is unset, /api/catalogue returns {books:[], has_next:false} and /api/search falls back to a PocketBase substring scan.
BACKEND_API_URL: The SvelteKit UI reads this env var (default http://localhost:8080) to reach the backend server-side. In docker-compose it is set to http://backend:8080.