--- method: GET path: /api/stats/books/:id auth: jwt area: stats --- # Get Book Stats Per-book reading card on the book detail page: lifetime totals plus recent sessions (newest first, capped). Scoped to the requesting user's own reading history. ## Example Request ```http GET /api/stats/books/550e8400-e29b-41d4-a716-446655440000 Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` ## Example response ```json example-response { "media_item_id": "550e8400-e29b-41d4-a716-446655440000", "total_minutes": 610, "total_seconds": 36612, "total_pages": 0, "session_count": 41, "max_progress": 0.62, "finished": false, "first_session": "2026-09-30T18:02:11Z", "last_session": "2026-10-23T21:44:05Z", "recent_sessions": [ { "started_at": "2026-10-23T21:44:05Z", "ended_at": "2026-10-23T22:19:40Z", "minutes": 35, "pages": 0, "device_id": "660e8400-e29b-41d4-a716-446655440001" } ] } ``` ## Response fields | Field | Type | Notes | | ------------- | ------- | ---------------------------------------------------------------- | | total_seconds | int | exact wall-clock (audio "Time listened"; minutes lose remainder) | | max_progress | float | highest progress fraction ever reached (0-1) | | recent_sessions | array | newest first, server-capped | ## Errors | Status | Body | When | | ------ | ------------------------ | ----------------------- | | 400 | `invalid media item id` | malformed id | | 401 | `invalid user` | no user in JWT context |