426 lines
6.3 KiB
Markdown
426 lines
6.3 KiB
Markdown
# API Documentation
|
|
|
|
## Base URL
|
|
|
|
```
|
|
http://localhost:8080/api
|
|
```
|
|
|
|
All responses are in JSON format.
|
|
|
|
## Authentication
|
|
|
|
Protected endpoints require a JWT token in the Authorization header:
|
|
|
|
```
|
|
Authorization: Bearer <token>
|
|
```
|
|
|
|
## Error Responses
|
|
|
|
All error responses follow this format:
|
|
|
|
```json
|
|
{
|
|
"error": "Error message here",
|
|
"code": "ERROR_CODE"
|
|
}
|
|
```
|
|
|
|
## Public Endpoints
|
|
|
|
### Get All Mangas
|
|
|
|
```http
|
|
GET /mangas?page=1&limit=20
|
|
```
|
|
|
|
**Query Parameters:**
|
|
- `page` (int) - Page number (default: 1)
|
|
- `limit` (int) - Items per page (default: 20)
|
|
- `sort` (string) - Sort by: latest, popular, rating, views
|
|
- `status` (string) - Filter by status: ongoing, completed, hiatus
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": "uuid",
|
|
"title": "Manga Title",
|
|
"description": "Description",
|
|
"author": "Author Name",
|
|
"artist": "Artist Name",
|
|
"cover_image": "url",
|
|
"rating": 4.5,
|
|
"views": 1000,
|
|
"status": "ongoing",
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
],
|
|
"total": 100,
|
|
"page": 1,
|
|
"limit": 20
|
|
}
|
|
```
|
|
|
|
### Get Manga Details
|
|
|
|
```http
|
|
GET /mangas/:id
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"id": "uuid",
|
|
"title": "Manga Title",
|
|
"description": "Description",
|
|
"author": "Author Name",
|
|
"artist": "Artist Name",
|
|
"cover_image": "url",
|
|
"rating": 4.5,
|
|
"views": 1000,
|
|
"status": "ongoing",
|
|
"chapters": [
|
|
{
|
|
"id": "uuid",
|
|
"number": 1,
|
|
"title": "Chapter 1",
|
|
"page_count": 25,
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
],
|
|
"tags": ["action", "adventure"],
|
|
"reviews": [
|
|
{
|
|
"id": "uuid",
|
|
"user": {"id": "uuid", "username": "user"},
|
|
"rating": 5,
|
|
"comment": "Great manga!",
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Get Chapter Pages
|
|
|
|
```http
|
|
GET /mangas/:id/chapters/:chapterNum/pages
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"id": "uuid",
|
|
"number": 1,
|
|
"title": "Chapter 1",
|
|
"pages": [
|
|
{
|
|
"id": "uuid",
|
|
"page_num": 1,
|
|
"image_url": "https://s3.example.com/..."
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Search Mangas
|
|
|
|
```http
|
|
GET /search?q=query&limit=10
|
|
```
|
|
|
|
**Query Parameters:**
|
|
- `q` (string) - Search query (required)
|
|
- `limit` (int) - Result limit (default: 10)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"results": [
|
|
{
|
|
"id": "uuid",
|
|
"title": "Manga Title",
|
|
"cover_image": "url",
|
|
"rating": 4.5
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Authentication Endpoints
|
|
|
|
### Sign Up
|
|
|
|
```http
|
|
POST /auth/signup
|
|
```
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"username": "username",
|
|
"email": "user@example.com",
|
|
"password": "password"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"token": "jwt_token",
|
|
"user": {
|
|
"id": "uuid",
|
|
"username": "username",
|
|
"email": "user@example.com"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Sign In
|
|
|
|
```http
|
|
POST /auth/signin
|
|
```
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"email": "user@example.com",
|
|
"password": "password"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"token": "jwt_token",
|
|
"user": {
|
|
"id": "uuid",
|
|
"username": "username",
|
|
"email": "user@example.com"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Protected Endpoints
|
|
|
|
### Get User Library
|
|
|
|
```http
|
|
GET /library
|
|
Authorization: Bearer <token>
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": "uuid",
|
|
"title": "Manga Title",
|
|
"cover_image": "url",
|
|
"rating": 4.5
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Add to Library
|
|
|
|
```http
|
|
POST /library/:id
|
|
Authorization: Bearer <token>
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"message": "Added to library"
|
|
}
|
|
```
|
|
|
|
### Remove from Library
|
|
|
|
```http
|
|
DELETE /library/:id
|
|
Authorization: Bearer <token>
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"message": "Removed from library"
|
|
}
|
|
```
|
|
|
|
### Upload Manga (Admin Only)
|
|
|
|
```http
|
|
POST /upload/manga
|
|
Authorization: Bearer <token>
|
|
Content-Type: multipart/form-data
|
|
```
|
|
|
|
**Form Fields:**
|
|
- `title` (string) - Manga title
|
|
- `author` (string) - Author name
|
|
- `artist` (string) - Artist name
|
|
- `description` (string) - Description
|
|
- `status` (string) - Status: ongoing, completed, hiatus
|
|
- `cover` (file) - Cover image
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"id": "uuid",
|
|
"title": "Manga Title",
|
|
"cover_image": "url"
|
|
}
|
|
```
|
|
|
|
### Upload Chapter (Admin Only)
|
|
|
|
```http
|
|
POST /upload/chapter/:id
|
|
Authorization: Bearer <token>
|
|
Content-Type: multipart/form-data
|
|
```
|
|
|
|
**Form Fields:**
|
|
- `number` (float) - Chapter number
|
|
- `title` (string) - Chapter title
|
|
- `pages` (file[]) - Chapter page images
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"id": "uuid",
|
|
"number": 1,
|
|
"title": "Chapter 1",
|
|
"page_count": 25,
|
|
"pages": [
|
|
{
|
|
"page_num": 1,
|
|
"image_url": "url"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Create Review
|
|
|
|
```http
|
|
POST /reviews/:mangaId
|
|
Authorization: Bearer <token>
|
|
```
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"rating": 5,
|
|
"comment": "Great manga!"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"id": "uuid",
|
|
"rating": 5,
|
|
"comment": "Great manga!",
|
|
"created_at": "2025-01-01T00:00:00Z"
|
|
}
|
|
```
|
|
|
|
## Status Codes
|
|
|
|
- `200` - Success
|
|
- `201` - Created
|
|
- `204` - No Content
|
|
- `400` - Bad Request
|
|
- `401` - Unauthorized
|
|
- `403` - Forbidden
|
|
- `404` - Not Found
|
|
- `409` - Conflict
|
|
- `429` - Too Many Requests
|
|
- `500` - Internal Server Error
|
|
|
|
## Rate Limiting
|
|
|
|
Rate limits are applied per IP address:
|
|
- 100 requests per minute for public endpoints
|
|
- 1000 requests per minute for authenticated endpoints
|
|
|
|
Rate limit headers:
|
|
```
|
|
X-RateLimit-Limit: 100
|
|
X-RateLimit-Remaining: 99
|
|
X-RateLimit-Reset: 1234567890
|
|
```
|
|
|
|
## Pagination
|
|
|
|
List endpoints support pagination:
|
|
|
|
```json
|
|
{
|
|
"data": [...],
|
|
"total": 100,
|
|
"page": 1,
|
|
"limit": 20,
|
|
"pages": 5
|
|
}
|
|
```
|
|
|
|
## Example Requests
|
|
|
|
### Using cURL
|
|
|
|
```bash
|
|
# Get all mangas
|
|
curl http://localhost:8080/api/mangas
|
|
|
|
# Search
|
|
curl "http://localhost:8080/api/search?q=action"
|
|
|
|
# Sign up
|
|
curl -X POST http://localhost:8080/api/auth/signup \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"username":"user","email":"user@example.com","password":"pass"}'
|
|
|
|
# Protected endpoint
|
|
curl -H "Authorization: Bearer TOKEN" http://localhost:8080/api/library
|
|
```
|
|
|
|
### Using JavaScript
|
|
|
|
```javascript
|
|
// Fetch mangas
|
|
const response = await fetch('/api/mangas');
|
|
const data = await response.json();
|
|
|
|
// With auth
|
|
const authResponse = await fetch('/api/library', {
|
|
headers: {
|
|
'Authorization': `Bearer ${token}`
|
|
}
|
|
});
|
|
```
|
|
|
|
### Using Python
|
|
|
|
```python
|
|
import requests
|
|
|
|
# Get mangas
|
|
response = requests.get('http://localhost:8080/api/mangas')
|
|
data = response.json()
|
|
|
|
# With auth
|
|
headers = {'Authorization': f'Bearer {token}'}
|
|
response = requests.get('http://localhost:8080/api/library', headers=headers)
|
|
```
|