# Backend API Specification — Cloud Reader ## Overview The Cloud Reader backend provides a RESTful API for managing a user's personal book library. Built with Django 5 + Django REST Framework. ## Models ### Book | Field | Type | Constraints | |------------------|--------------------|---------------------------------| | `title` | `CharField(500)` | Required | | `author` | `CharField(500)` | Required | | `genre` | `CharField(200)` | Optional, blank allowed | | `description` | `TextField` | Optional, blank allowed | | `cover_image_url`| `URLField` | Optional, blank allowed | | `isbn` | `CharField(20)` | Optional, blank allowed | | `total_pages` | `PositiveIntegerField` | Default 0 | | `current_page` | `PositiveIntegerField` | Default 0, validated ≤ total | | `reading_status` | `CharField(20)` | Choices: `not_started`, `reading`, `finished`, `dnf` | | `owner` | `ForeignKey(User)` | Set automatically on create | | `created_at` | `DateTimeField` | Auto-set on create | | `updated_at` | `DateTimeField` | Auto-set on update | **Properties:** - `reading_progress` — computed `(current_page / total_pages) * 100`, returns `0.0` when `total_pages` is 0. **Indexes:** Composite indexes on `(owner, reading_status)`, `(owner, title)`, `(owner, author)`. ## API Endpoints Base URL: `/api/` Authentication: SessionAuthentication + BasicAuthentication (DRF defaults). Permissions: All book endpoints require `IsAuthenticated`. Users can only access their own books. ### Books | Method | URL | Action | Serializer | |----------|------------------------------------|---------------|--------------------| | `GET` | `/api/books/` | List books | `BookListSerializer` | | `POST` | `/api/books/` | Create book | `BookDetailSerializer` | | `GET` | `/api/books/{id}/` | Retrieve book | `BookDetailSerializer` | | `PUT` | `/api/books/{id}/` | Full update | `BookDetailSerializer` | | `PATCH` | `/api/books/{id}/` | Partial update| `BookDetailSerializer` | | `DELETE` | `/api/books/{id}/` | Delete book | — | | `POST` | `/api/books/{id}/mark_finished/` | Mark finished | `BookDetailSerializer` | | `GET` | `/api/books/stats/` | Library stats | — (custom) | ### Query Parameters (List) | Parameter | Type | Description | |------------------|----------|--------------------------------------------------| | `page` | int | Page number for pagination (20 items/page) | | `sort_by` | string | `title`, `-title`, `author`, `-author`, `-created_at`, `-updated_at`, `-reading_progress`, `reading_progress` | | `reading_status` | string | Filter by status value | | `search` | string | Search in title and author fields (icontains) | ### Stats Response ```json { "total_books": 10, "finished": 3, "reading": 4, "not_started": 3 } ``` ### Mark Finished `POST /api/books/{id}/mark_finished/` sets `reading_status` to `finished` and `current_page` to `total_pages`. ## Validation Rules - Title and author cannot be empty or whitespace-only - `current_page` cannot exceed `total_pages` (when `total_pages > 0`) - Setting `reading_status` to `finished` automatically sets `current_page = total_pages` ## Admin Books are registered in Django admin with list display, filters by `reading_status` and `genre`, and search by `title`/`author`.