1387 lines
38 KiB
Markdown
1387 lines
38 KiB
Markdown
# IGNY8 API Endpoints - Complete Analysis
|
|
|
|
**Date:** 2025-01-XX
|
|
**Purpose:** Comprehensive analysis of all existing API endpoints in the Django deployment, including request/response formats, authentication, rate limiting, usage patterns, and third-party integrations.
|
|
|
|
---
|
|
|
|
## Executive Summary
|
|
|
|
**Base URL:** `/api/v1/`
|
|
|
|
**Total Endpoints:** 100+ endpoints across 5 main modules
|
|
|
|
**Authentication:** JWT Bearer tokens (primary), Session authentication (fallback), Basic authentication (fallback)
|
|
|
|
**Rate Limiting:** Not currently implemented (planned for future)
|
|
|
|
**Response Format:** Standardized JSON with `success`, `data`, `message`, `errors` fields
|
|
|
|
**Pagination:** Custom pagination with `page_size` parameter (default: 10, max: 100)
|
|
|
|
|
|
---
|
|
|
|
## Table of Contents
|
|
|
|
1. [API Architecture Overview](#api-architecture-overview)
|
|
2. [Authentication & Authorization](#authentication--authorization)
|
|
3. [Response Format Standards](#response-format-standards)
|
|
4. [Pagination Format](#pagination-format)
|
|
5. [Auth Module Endpoints](#auth-module-endpoints)
|
|
6. [Planner Module Endpoints](#planner-module-endpoints)
|
|
7. [Writer Module Endpoints](#writer-module-endpoints)
|
|
8. [System Module Endpoints](#system-module-endpoints)
|
|
9. [Billing Module Endpoints](#billing-module-endpoints)
|
|
10. [Frontend API Usage Patterns](#frontend-api-usage-patterns)
|
|
11. [Third-Party Integrations](#third-party-integrations)
|
|
12. [Dependencies](#dependencies)
|
|
13. [Standardization Recommendations](#standardization-recommendations)
|
|
|
|
---
|
|
|
|
## API Architecture Overview
|
|
|
|
### Base URL Structure
|
|
|
|
```
|
|
/api/v1/
|
|
├── auth/ # Authentication and user management
|
|
├── planner/ # Keywords, clusters, content ideas
|
|
├── writer/ # Tasks, content, images
|
|
├── system/ # Settings, integrations, prompts
|
|
└── billing/ # Credits, transactions, usage
|
|
```
|
|
|
|
### Technology Stack
|
|
|
|
- **Framework**: Django REST Framework (DRF)
|
|
- **Router**: DefaultRouter (RESTful ViewSets)
|
|
- **Authentication**: Custom JWT + Session + Basic
|
|
- **Pagination**: CustomPageNumberPagination
|
|
- **Filtering**: DjangoFilterBackend, SearchFilter, OrderingFilter
|
|
- **Serialization**: DRF Serializers
|
|
|
|
### Base Classes
|
|
|
|
**AccountModelViewSet:**
|
|
- Automatic account filtering
|
|
- Admin/Developer override (bypasses account filtering)
|
|
- System account users bypass account filtering
|
|
- Sets account on create operations
|
|
|
|
**SiteSectorModelViewSet:**
|
|
- Inherits from AccountModelViewSet
|
|
- Additional site/sector filtering
|
|
- Site access control (based on user role)
|
|
- Sector validation (must belong to site)
|
|
|
|
---
|
|
|
|
## Authentication & Authorization
|
|
|
|
### Authentication Methods
|
|
|
|
**1. JWT Authentication (Primary)**
|
|
- **Class**: `igny8_core.api.authentication.JWTAuthentication`
|
|
- **Header**: `Authorization: Bearer <token>`
|
|
- **Token Type**: Access token (type: 'access')
|
|
- **Expiry**: 15 minutes (configurable via `JWT_ACCESS_TOKEN_EXPIRY`)
|
|
- **Token Payload**: Contains `user_id`, `account_id`, `type: 'access'`
|
|
- **Account Context**: Sets `request.account` from token
|
|
|
|
**2. Session Authentication (Fallback)**
|
|
- **Class**: `igny8_core.api.authentication.CSRFExemptSessionAuthentication`
|
|
- **Method**: Session cookies (CSRF exempt for API)
|
|
- **Use Case**: Admin panel, fallback when JWT fails
|
|
|
|
**3. Basic Authentication (Fallback)**
|
|
- **Class**: `rest_framework.authentication.BasicAuthentication`
|
|
- **Method**: HTTP Basic Auth
|
|
- **Use Case**: Fallback authentication
|
|
|
|
### Authentication Configuration
|
|
|
|
**Location**: `backend/igny8_core/settings.py`
|
|
|
|
```python
|
|
REST_FRAMEWORK = {
|
|
'DEFAULT_AUTHENTICATION_CLASSES': [
|
|
'igny8_core.api.authentication.JWTAuthentication', # Primary
|
|
'igny8_core.api.authentication.CSRFExemptSessionAuthentication', # Fallback
|
|
'rest_framework.authentication.BasicAuthentication', # Fallback
|
|
],
|
|
'DEFAULT_PERMISSION_CLASSES': [
|
|
'rest_framework.permissions.AllowAny', # Default: AllowAny
|
|
],
|
|
}
|
|
```
|
|
|
|
### Permission Classes
|
|
|
|
**Default**: `AllowAny` (most endpoints)
|
|
|
|
**Custom Permission Classes:**
|
|
- `IsAuthenticated`: Requires authentication
|
|
- `IsOwnerOrAdmin`: Owner or Admin role required
|
|
- `IsEditorOrAbove`: Editor, Admin, or Owner role required
|
|
- ViewSet-level overrides: Many ViewSets set `permission_classes = []` (AllowAny)
|
|
|
|
### Account Context Middleware
|
|
|
|
**Class**: `igny8_core.auth.middleware.AccountContextMiddleware`
|
|
|
|
**Functionality:**
|
|
- Extracts account ID from JWT token
|
|
- Loads Account object
|
|
- Sets `request.account` for all requests
|
|
- Enables automatic account filtering in ViewSets
|
|
|
|
---
|
|
|
|
## Response Format Standards
|
|
|
|
### Success Response
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": { ... },
|
|
"message": "Optional success message"
|
|
}
|
|
```
|
|
|
|
### Error Response
|
|
|
|
```json
|
|
{
|
|
"success": false,
|
|
"error": "Error message",
|
|
"errors": {
|
|
"field_name": ["Error detail"]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Pagination Response
|
|
|
|
```json
|
|
{
|
|
"count": 100,
|
|
"next": "http://api.igny8.com/api/v1/endpoint/?page=2",
|
|
"previous": null,
|
|
"results": [ ... ]
|
|
}
|
|
```
|
|
|
|
### Standard Response Fields
|
|
|
|
- **success**: Boolean indicating success/failure
|
|
- **data**: Response data (object or array)
|
|
- **message**: Human-readable message (optional)
|
|
- **error**: Error message (on failure)
|
|
- **errors**: Validation errors object (on failure)
|
|
|
|
---
|
|
|
|
## Pagination Format
|
|
|
|
### CustomPageNumberPagination
|
|
|
|
**Class**: `igny8_core.api.pagination.CustomPageNumberPagination`
|
|
|
|
**Configuration:**
|
|
- Default page size: 10
|
|
- Max page size: 100
|
|
- Query parameter: `page_size` (optional)
|
|
- Page parameter: `page` (default: 1)
|
|
|
|
**Example Request:**
|
|
```
|
|
GET /api/v1/planner/keywords/?page=2&page_size=25
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"count": 150,
|
|
"next": "http://api.igny8.com/api/v1/planner/keywords/?page=3&page_size=25",
|
|
"previous": "http://api.igny8.com/api/v1/planner/keywords/?page=1&page_size=25",
|
|
"results": [ ... ]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Auth Module Endpoints
|
|
|
|
**Base Path**: `/api/v1/auth/`
|
|
|
|
### Authentication Endpoints
|
|
|
|
#### POST `/api/v1/auth/register/`
|
|
**Purpose**: User registration
|
|
|
|
**Authentication**: None (AllowAny)
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"email": "user@example.com",
|
|
"password": "password123",
|
|
"password_confirm": "password123"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Registration successful",
|
|
"user": {
|
|
"id": 1,
|
|
"email": "user@example.com",
|
|
"role": "owner",
|
|
"account": { ... }
|
|
}
|
|
}
|
|
```
|
|
|
|
**Status Codes**: 201 (Created), 400 (Bad Request)
|
|
|
|
#### POST `/api/v1/auth/login/`
|
|
**Purpose**: User login
|
|
|
|
**Authentication**: None (AllowAny)
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"email": "user@example.com",
|
|
"password": "password123"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Login successful",
|
|
"user": { ... },
|
|
"tokens": {
|
|
"access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
|
|
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc...",
|
|
"access_expires_at": "2025-01-15T12:30:00Z",
|
|
"refresh_expires_at": "2025-01-22T12:00:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Status Codes**: 200 (OK), 401 (Unauthorized), 400 (Bad Request)
|
|
|
|
#### POST `/api/v1/auth/change-password/`
|
|
**Purpose**: Change user password
|
|
|
|
**Authentication**: Required (IsAuthenticated)
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"old_password": "oldpass123",
|
|
"new_password": "newpass123",
|
|
"new_password_confirm": "newpass123"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Password changed successfully"
|
|
}
|
|
```
|
|
|
|
**Status Codes**: 200 (OK), 400 (Bad Request)
|
|
|
|
#### GET `/api/v1/auth/me/`
|
|
**Purpose**: Get current user information
|
|
|
|
**Authentication**: Required (IsAuthenticated)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"user": {
|
|
"id": 1,
|
|
"email": "user@example.com",
|
|
"role": "owner",
|
|
"account": { ... },
|
|
"accessible_sites": [ ... ]
|
|
}
|
|
}
|
|
```
|
|
|
|
**Status Codes**: 200 (OK), 401 (Unauthorized)
|
|
|
|
### User Management Endpoints
|
|
|
|
#### ViewSet: `UsersViewSet`
|
|
**Base Path**: `/api/v1/auth/users/`
|
|
|
|
**Permission**: IsOwnerOrAdmin
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/auth/users/` - List users
|
|
- `POST /api/v1/auth/users/` - Create user
|
|
- `GET /api/v1/auth/users/{id}/` - Get user
|
|
- `PUT /api/v1/auth/users/{id}/` - Update user
|
|
- `DELETE /api/v1/auth/users/{id}/` - Delete user
|
|
|
|
**Custom Actions:**
|
|
- `POST /api/v1/auth/users/invite/` - Invite user
|
|
- `POST /api/v1/auth/users/{id}/activate/` - Activate user
|
|
|
|
### Account Management Endpoints
|
|
|
|
#### ViewSet: `AccountsViewSet`
|
|
**Base Path**: `/api/v1/auth/accounts/`
|
|
|
|
**Permission**: IsOwnerOrAdmin
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/auth/accounts/` - List accounts
|
|
- `POST /api/v1/auth/accounts/` - Create account
|
|
- `GET /api/v1/auth/accounts/{id}/` - Get account
|
|
- `PUT /api/v1/auth/accounts/{id}/` - Update account
|
|
- `DELETE /api/v1/auth/accounts/{id}/` - Delete account
|
|
|
|
### Site Management Endpoints
|
|
|
|
#### ViewSet: `SiteViewSet`
|
|
**Base Path**: `/api/v1/auth/sites/`
|
|
|
|
**Permission**: IsEditorOrAbove
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/auth/sites/` - List sites
|
|
- `POST /api/v1/auth/sites/` - Create site
|
|
- `GET /api/v1/auth/sites/{id}/` - Get site
|
|
- `PUT /api/v1/auth/sites/{id}/` - Update site
|
|
- `DELETE /api/v1/auth/sites/{id}/` - Delete site
|
|
|
|
**Custom Actions:**
|
|
- `GET /api/v1/auth/sites/{id}/sectors/` - Get site sectors
|
|
- `POST /api/v1/auth/sites/{id}/set_active/` - Set active site
|
|
- `POST /api/v1/auth/sites/{id}/select_sectors/` - Select sectors
|
|
|
|
### Sector Management Endpoints
|
|
|
|
#### ViewSet: `SectorViewSet`
|
|
**Base Path**: `/api/v1/auth/sectors/`
|
|
|
|
**Permission**: IsEditorOrAbove
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/auth/sectors/` - List sectors
|
|
- `POST /api/v1/auth/sectors/` - Create sector
|
|
- `GET /api/v1/auth/sectors/{id}/` - Get sector
|
|
- `PUT /api/v1/auth/sectors/{id}/` - Update sector
|
|
- `DELETE /api/v1/auth/sectors/{id}/` - Delete sector
|
|
|
|
### Plan Management Endpoints
|
|
|
|
#### ViewSet: `PlanViewSet`
|
|
**Base Path**: `/api/v1/auth/plans/`
|
|
|
|
**Permission**: AllowAny (read-only)
|
|
|
|
**Endpoints:**
|
|
- `GET /api/v1/auth/plans/` - List plans
|
|
- `GET /api/v1/auth/plans/{id}/` - Get plan
|
|
|
|
### Industry Management Endpoints
|
|
|
|
#### ViewSet: `IndustryViewSet`
|
|
**Base Path**: `/api/v1/auth/industries/`
|
|
|
|
**Permission**: AllowAny (read-only)
|
|
|
|
**Endpoints:**
|
|
- `GET /api/v1/auth/industries/` - List industries
|
|
- `GET /api/v1/auth/industries/{id}/` - Get industry
|
|
|
|
### Seed Keyword Endpoints
|
|
|
|
#### ViewSet: `SeedKeywordViewSet`
|
|
**Base Path**: `/api/v1/auth/seed-keywords/`
|
|
|
|
**Permission**: AllowAny (read-only)
|
|
|
|
**Endpoints:**
|
|
- `GET /api/v1/auth/seed-keywords/` - List seed keywords
|
|
- `GET /api/v1/auth/seed-keywords/{id}/` - Get seed keyword
|
|
|
|
### Site Access Management Endpoints
|
|
|
|
#### ViewSet: `SiteUserAccessViewSet`
|
|
**Base Path**: `/api/v1/auth/site-access/`
|
|
|
|
**Permission**: IsOwnerOrAdmin
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/auth/site-access/` - List site access records
|
|
- `POST /api/v1/auth/site-access/` - Grant site access
|
|
- `GET /api/v1/auth/site-access/{id}/` - Get site access
|
|
- `PUT /api/v1/auth/site-access/{id}/` - Update site access
|
|
- `DELETE /api/v1/auth/site-access/{id}/` - Revoke site access
|
|
|
|
### Subscription Management Endpoints
|
|
|
|
#### ViewSet: `SubscriptionsViewSet`
|
|
**Base Path**: `/api/v1/auth/subscriptions/`
|
|
|
|
**Permission**: IsOwnerOrAdmin
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/auth/subscriptions/` - List subscriptions
|
|
- `POST /api/v1/auth/subscriptions/` - Create subscription
|
|
- `GET /api/v1/auth/subscriptions/{id}/` - Get subscription
|
|
- `PUT /api/v1/auth/subscriptions/{id}/` - Update subscription
|
|
- `DELETE /api/v1/auth/subscriptions/{id}/` - Delete subscription
|
|
|
|
**Custom Actions:**
|
|
- `GET /api/v1/auth/subscriptions/by-account/{account_id}/` - Get subscriptions by account
|
|
|
|
---
|
|
|
|
## Planner Module Endpoints
|
|
|
|
**Base Path**: `/api/v1/planner/`
|
|
|
|
### Keyword Management Endpoints
|
|
|
|
#### ViewSet: `KeywordViewSet`
|
|
**Base Path**: `/api/v1/planner/keywords/`
|
|
|
|
**Permission**: AllowAny (default)
|
|
|
|
**Inherits**: SiteSectorModelViewSet (automatic account/site/sector filtering)
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/planner/keywords/` - List keywords (paginated)
|
|
- `POST /api/v1/planner/keywords/` - Create keyword
|
|
- `GET /api/v1/planner/keywords/{id}/` - Get keyword
|
|
- `PUT /api/v1/planner/keywords/{id}/` - Update keyword
|
|
- `DELETE /api/v1/planner/keywords/{id}/` - Delete keyword
|
|
|
|
**Filtering:**
|
|
- `status`: Filter by status
|
|
- `cluster_id`: Filter by cluster
|
|
- `seed_keyword__intent`: Filter by intent
|
|
- `seed_keyword_id`: Filter by seed keyword ID
|
|
- `difficulty_min`: Minimum difficulty
|
|
- `difficulty_max`: Maximum difficulty
|
|
- `volume_min`: Minimum volume
|
|
- `volume_max`: Maximum volume
|
|
- `site_id`: Filter by site (query param)
|
|
- `sector_id`: Filter by sector (query param)
|
|
|
|
**Search:**
|
|
- `search`: Search by keyword text (searches `seed_keyword__keyword` field)
|
|
|
|
**Ordering:**
|
|
- `ordering`: Order by `created_at`, `seed_keyword__volume`, `seed_keyword__difficulty`
|
|
- Default: `-created_at` (newest first)
|
|
|
|
**Custom Actions:**
|
|
- `POST /api/v1/planner/keywords/bulk_delete/` - Bulk delete keywords
|
|
- **Request**: `{ "ids": [1, 2, 3] }`
|
|
- **Response**: `{ "deleted_count": 3 }`
|
|
|
|
- `POST /api/v1/planner/keywords/bulk_update_status/` - Bulk update status
|
|
- **Request**: `{ "ids": [1, 2, 3], "status": "active" }`
|
|
- **Response**: `{ "updated_count": 3 }`
|
|
|
|
- `POST /api/v1/planner/keywords/bulk_add_from_seed/` - Add keywords from seed library
|
|
- **Request**: `{ "seed_keyword_ids": [1, 2, 3], "site_id": 1, "sector_id": 1 }`
|
|
- **Response**: `{ "added_count": 3, "keywords": [ ... ] }`
|
|
|
|
- `GET /api/v1/planner/keywords/export/` - Export keywords to CSV
|
|
- **Query Params**: Same filtering as list endpoint
|
|
- **Response**: CSV file download
|
|
|
|
- `POST /api/v1/planner/keywords/import_keywords/` - Import keywords from CSV
|
|
- **Request**: Multipart form data with CSV file
|
|
- **Response**: `{ "imported_count": 10, "errors": [] }`
|
|
|
|
- `POST /api/v1/planner/keywords/auto_cluster/` - Auto-cluster keywords using AI
|
|
- **Request**: `{ "ids": [1, 2, 3, ...], "sector_id": 1 }`
|
|
- **Response**: `{ "success": true, "task_id": "abc123" }`
|
|
- **Max Keywords**: 20 per batch
|
|
- **Returns**: Celery task ID for progress tracking
|
|
|
|
### Cluster Management Endpoints
|
|
|
|
#### ViewSet: `ClusterViewSet`
|
|
**Base Path**: `/api/v1/planner/clusters/`
|
|
|
|
**Permission**: AllowAny (default)
|
|
|
|
**Inherits**: SiteSectorModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/planner/clusters/` - List clusters
|
|
- `POST /api/v1/planner/clusters/` - Create cluster
|
|
- `GET /api/v1/planner/clusters/{id}/` - Get cluster
|
|
- `PUT /api/v1/planner/clusters/{id}/` - Update cluster
|
|
- `DELETE /api/v1/planner/clusters/{id}/` - Delete cluster
|
|
|
|
**Filtering:**
|
|
- `status`: Filter by status
|
|
- `site_id`: Filter by site (query param)
|
|
- `sector_id`: Filter by sector (query param)
|
|
|
|
**Search:**
|
|
- `search`: Search by cluster name
|
|
|
|
**Ordering:**
|
|
- `ordering`: Order by `keywords_count`, `volume`, `created_at`
|
|
|
|
**Custom Actions:**
|
|
- `POST /api/v1/planner/clusters/bulk_delete/` - Bulk delete clusters
|
|
- **Request**: `{ "ids": [1, 2, 3] }`
|
|
- **Response**: `{ "deleted_count": 3 }`
|
|
|
|
- `POST /api/v1/planner/clusters/auto_generate_ideas/` - Auto-generate content ideas
|
|
- **Request**: `{ "ids": [1] }` (max 1 cluster per batch)
|
|
- **Response**: `{ "success": true, "task_id": "abc123" }`
|
|
- **Returns**: Celery task ID for progress tracking
|
|
|
|
### Content Ideas Endpoints
|
|
|
|
#### ViewSet: `ContentIdeasViewSet`
|
|
**Base Path**: `/api/v1/planner/ideas/`
|
|
|
|
**Permission**: AllowAny (default)
|
|
|
|
**Inherits**: SiteSectorModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/planner/ideas/` - List content ideas
|
|
- `POST /api/v1/planner/ideas/` - Create content idea
|
|
- `GET /api/v1/planner/ideas/{id}/` - Get content idea
|
|
- `PUT /api/v1/planner/ideas/{id}/` - Update content idea
|
|
- `DELETE /api/v1/planner/ideas/{id}/` - Delete content idea
|
|
|
|
**Filtering:**
|
|
- `status`: Filter by status
|
|
- `cluster_id`: Filter by cluster
|
|
- `content_type`: Filter by content type
|
|
- `site_id`: Filter by site (query param)
|
|
- `sector_id`: Filter by sector (query param)
|
|
|
|
**Search:**
|
|
- `search`: Search by idea title
|
|
|
|
**Custom Actions:**
|
|
- `POST /api/v1/planner/ideas/bulk_delete/` - Bulk delete ideas
|
|
- **Request**: `{ "ids": [1, 2, 3] }`
|
|
- **Response**: `{ "deleted_count": 3 }`
|
|
|
|
- `POST /api/v1/planner/ideas/bulk_queue_to_writer/` - Queue ideas to writer (create tasks)
|
|
- **Request**: `{ "ids": [1, 2, 3] }`
|
|
- **Response**: `{ "tasks_created": 3, "tasks": [ ... ] }`
|
|
|
|
---
|
|
|
|
## Writer Module Endpoints
|
|
|
|
**Base Path**: `/api/v1/writer/`
|
|
|
|
### Task Management Endpoints
|
|
|
|
#### ViewSet: `TasksViewSet`
|
|
**Base Path**: `/api/v1/writer/tasks/`
|
|
|
|
**Permission**: AllowAny (default)
|
|
|
|
**Inherits**: SiteSectorModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/writer/tasks/` - List tasks
|
|
- `POST /api/v1/writer/tasks/` - Create task
|
|
- `GET /api/v1/writer/tasks/{id}/` - Get task
|
|
- `PUT /api/v1/writer/tasks/{id}/` - Update task
|
|
- `DELETE /api/v1/writer/tasks/{id}/` - Delete task
|
|
|
|
**Filtering:**
|
|
- `status`: Filter by status (draft, in_progress, review, completed, archived)
|
|
- `cluster_id`: Filter by cluster
|
|
- `content_type`: Filter by content type
|
|
- `content_structure`: Filter by content structure
|
|
- `site_id`: Filter by site (query param)
|
|
- `sector_id`: Filter by sector (query param)
|
|
|
|
**Search:**
|
|
- `search`: Search by title or keywords
|
|
|
|
**Ordering:**
|
|
- `ordering`: Order by `title`, `created_at`, `word_count`, `status`
|
|
- Default: `-created_at`
|
|
|
|
**Custom Actions:**
|
|
- `POST /api/v1/writer/tasks/bulk_delete/` - Bulk delete tasks
|
|
- **Request**: `{ "ids": [1, 2, 3] }`
|
|
- **Response**: `{ "deleted_count": 3 }`
|
|
|
|
- `POST /api/v1/writer/tasks/bulk_update/` - Bulk update task status
|
|
- **Request**: `{ "ids": [1, 2, 3], "status": "review" }`
|
|
- **Response**: `{ "updated_count": 3 }`
|
|
|
|
- `POST /api/v1/writer/tasks/auto_generate_content/` - Auto-generate content using AI
|
|
- **Request**: `{ "ids": [1, 2, 3, ...] }` (max 50 tasks per batch)
|
|
- **Response**: `{ "success": true, "task_id": "abc123" }`
|
|
- **Returns**: Celery task ID for progress tracking
|
|
|
|
### Content Management Endpoints
|
|
|
|
#### ViewSet: `ContentViewSet`
|
|
**Base Path**: `/api/v1/writer/content/`
|
|
|
|
**Permission**: AllowAny (default)
|
|
|
|
**Inherits**: SiteSectorModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/writer/content/` - List content
|
|
- `POST /api/v1/writer/content/` - Create content
|
|
- `GET /api/v1/writer/content/{id}/` - Get content
|
|
- `PUT /api/v1/writer/content/{id}/` - Update content
|
|
- `DELETE /api/v1/writer/content/{id}/` - Delete content
|
|
|
|
**Filtering:**
|
|
- `status`: Filter by status
|
|
- `content_type`: Filter by content type
|
|
- `site_id`: Filter by site (query param)
|
|
- `sector_id`: Filter by sector (query param)
|
|
|
|
**Search:**
|
|
- `search`: Search by title or keywords
|
|
|
|
**Custom Actions:**
|
|
- `POST /api/v1/writer/content/generate_image_prompts/` - Generate image prompts from content
|
|
- **Request**: `{ "ids": [1, 2, 3] }`
|
|
- **Response**: `{ "success": true, "task_id": "abc123" }`
|
|
- **Returns**: Celery task ID for progress tracking
|
|
|
|
### Image Management Endpoints
|
|
|
|
#### ViewSet: `ImagesViewSet`
|
|
**Base Path**: `/api/v1/writer/images/`
|
|
|
|
**Permission**: AllowAny (default)
|
|
|
|
**Inherits**: SiteSectorModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/writer/images/` - List images
|
|
- `POST /api/v1/writer/images/` - Create image
|
|
- `GET /api/v1/writer/images/{id}/` - Get image
|
|
- `PUT /api/v1/writer/images/{id}/` - Update image
|
|
- `DELETE /api/v1/writer/images/{id}/` - Delete image
|
|
|
|
**Filtering:**
|
|
- `image_type`: Filter by type (featured, in_article, desktop, mobile)
|
|
- `status`: Filter by status
|
|
- `content_id`: Filter by content
|
|
- `task_id`: Filter by task
|
|
- `site_id`: Filter by site (query param)
|
|
- `sector_id`: Filter by sector (query param)
|
|
|
|
**Custom Actions:**
|
|
- `GET /api/v1/writer/images/{id}/file/` - Get image file URL
|
|
- **Response**: `{ "image_url": "https://..." }`
|
|
|
|
- `GET /api/v1/writer/images/content_images/` - Get images for content
|
|
- **Query Params**: `content_id` (required)
|
|
- **Response**: `{ "images": [ ... ] }`
|
|
|
|
- `POST /api/v1/writer/images/auto_generate/` - Auto-generate images (legacy)
|
|
- **Request**: `{ "ids": [1, 2, 3] }`
|
|
- **Response**: `{ "success": true, "images_created": 3 }`
|
|
|
|
- `POST /api/v1/writer/images/generate_images/` - Generate images using AI
|
|
- **Request**: `{ "ids": [1, 2, 3, ...] }`
|
|
- **Response**: `{ "success": true, "task_id": "abc123" }`
|
|
- **Returns**: Celery task ID for progress tracking
|
|
|
|
- `POST /api/v1/writer/images/bulk_update/` - Bulk update image status
|
|
- **Request**: `{ "ids": [1, 2, 3], "status": "completed" }` OR `{ "content_id": 1, "status": "completed" }`
|
|
- **Response**: `{ "updated_count": 3 }`
|
|
|
|
---
|
|
|
|
## System Module Endpoints
|
|
|
|
**Base Path**: `/api/v1/system/`
|
|
|
|
### AI Prompt Management Endpoints
|
|
|
|
#### ViewSet: `AIPromptViewSet`
|
|
**Base Path**: `/api/v1/system/prompts/`
|
|
|
|
**Permission**: AllowAny (default)
|
|
|
|
**Inherits**: AccountModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/system/prompts/` - List prompts
|
|
- `POST /api/v1/system/prompts/` - Create prompt
|
|
- `GET /api/v1/system/prompts/{id}/` - Get prompt
|
|
- `PUT /api/v1/system/prompts/{id}/` - Update prompt
|
|
- `DELETE /api/v1/system/prompts/{id}/` - Delete prompt
|
|
|
|
**Custom Actions:**
|
|
- `GET /api/v1/system/prompts/by_type/{prompt_type}/` - Get prompt by type
|
|
- **Response**: `{ "prompt_type": "auto_cluster", "prompt_value": "..." }`
|
|
|
|
- `POST /api/v1/system/prompts/save/` - Save prompt (custom action)
|
|
- **Request**: `{ "prompt_type": "auto_cluster", "prompt_value": "..." }`
|
|
- **Response**: `{ "success": true, "prompt": { ... } }`
|
|
|
|
- `POST /api/v1/system/prompts/reset/` - Reset prompt to default
|
|
- **Request**: `{ "prompt_type": "auto_cluster" }`
|
|
- **Response**: `{ "success": true, "prompt": { ... } }`
|
|
|
|
### Author Profile Management Endpoints
|
|
|
|
#### ViewSet: `AuthorProfileViewSet`
|
|
**Base Path**: `/api/v1/system/author-profiles/`
|
|
|
|
**Permission**: AllowAny (default)
|
|
|
|
**Inherits**: AccountModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/system/author-profiles/` - List author profiles
|
|
- `POST /api/v1/system/author-profiles/` - Create author profile
|
|
- `GET /api/v1/system/author-profiles/{id}/` - Get author profile
|
|
- `PUT /api/v1/system/author-profiles/{id}/` - Update author profile
|
|
- `DELETE /api/v1/system/author-profiles/{id}/` - Delete author profile
|
|
|
|
### Strategy Management Endpoints
|
|
|
|
#### ViewSet: `StrategyViewSet`
|
|
**Base Path**: `/api/v1/system/strategies/`
|
|
|
|
**Permission**: AllowAny (default)
|
|
|
|
**Inherits**: AccountModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/system/strategies/` - List strategies
|
|
- `POST /api/v1/system/strategies/` - Create strategy
|
|
- `GET /api/v1/system/strategies/{id}/` - Get strategy
|
|
- `PUT /api/v1/system/strategies/{id}/` - Update strategy
|
|
- `DELETE /api/v1/system/strategies/{id}/` - Delete strategy
|
|
|
|
### Integration Settings Endpoints
|
|
|
|
#### ViewSet: `IntegrationSettingsViewSet`
|
|
**Base Path**: `/api/v1/system/settings/integrations/`
|
|
|
|
**Permission**: AllowAny (default)
|
|
|
|
**Custom URL Patterns** (not standard ViewSet routes):
|
|
|
|
- `GET /api/v1/system/settings/integrations/{pk}/` - Get integration settings
|
|
- **Response**: `{ "integration_type": "openai", "config": { ... }, "is_active": true }`
|
|
|
|
- `POST /api/v1/system/settings/integrations/{pk}/save/` - Save integration settings
|
|
- **Request**: `{ "config": { "apiKey": "...", "model": "gpt-4" }, "is_active": true }`
|
|
- **Response**: `{ "success": true, "integration": { ... } }`
|
|
|
|
- `PUT /api/v1/system/settings/integrations/{pk}/` - Update integration settings
|
|
- **Request**: Same as save
|
|
- **Response**: Same as save
|
|
|
|
- `POST /api/v1/system/settings/integrations/{pk}/test/` - Test connection
|
|
- **Request**: `{ "provider": "openai" }` or `{ "provider": "runware" }`
|
|
- **Response**: `{ "success": true, "message": "Connection successful" }`
|
|
|
|
- `POST /api/v1/system/settings/integrations/{pk}/generate/` - Test image generation
|
|
- **Request**: `{ "prompt": "...", "provider": "openai", "model": "dall-e-3", ... }`
|
|
- **Response**: `{ "success": true, "image_url": "https://..." }`
|
|
|
|
- `GET /api/v1/system/settings/task_progress/{task_id}/` - Get Celery task progress
|
|
- **Response**: `{ "state": "PROGRESS", "meta": { "phase": "AI_CALL", "percentage": 50, ... } }`
|
|
|
|
- `GET /api/v1/system/integrations/image_generation/` - Get image generation settings
|
|
- **Response**: `{ "providers": ["openai", "runware"], "models": { ... }, ... }`
|
|
|
|
### Settings Management Endpoints
|
|
|
|
#### ViewSet: `SystemSettingsViewSet`
|
|
**Base Path**: `/api/v1/system/settings/system/`
|
|
|
|
**Permission**: IsAuthenticated
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/system/settings/system/` - List system settings
|
|
- `POST /api/v1/system/settings/system/` - Create system setting
|
|
- `GET /api/v1/system/settings/system/{id}/` - Get system setting
|
|
- `PUT /api/v1/system/settings/system/{id}/` - Update system setting
|
|
- `DELETE /api/v1/system/settings/system/{id}/` - Delete system setting
|
|
|
|
#### ViewSet: `AccountSettingsViewSet`
|
|
**Base Path**: `/api/v1/system/settings/account/`
|
|
|
|
**Permission**: IsAuthenticated
|
|
|
|
**Inherits**: AccountModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/system/settings/account/` - List account settings
|
|
- `POST /api/v1/system/settings/account/` - Create account setting
|
|
- `GET /api/v1/system/settings/account/{id}/` - Get account setting
|
|
- `PUT /api/v1/system/settings/account/{id}/` - Update account setting
|
|
- `DELETE /api/v1/system/settings/account/{id}/` - Delete account setting
|
|
|
|
#### ViewSet: `UserSettingsViewSet`
|
|
**Base Path**: `/api/v1/system/settings/user/`
|
|
|
|
**Permission**: IsAuthenticated
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/system/settings/user/` - List user settings
|
|
- `POST /api/v1/system/settings/user/` - Create user setting
|
|
- `GET /api/v1/system/settings/user/{id}/` - Get user setting
|
|
- `PUT /api/v1/system/settings/user/{id}/` - Update user setting
|
|
- `DELETE /api/v1/system/settings/user/{id}/` - Delete user setting
|
|
|
|
#### ViewSet: `ModuleSettingsViewSet`
|
|
**Base Path**: `/api/v1/system/settings/modules/`
|
|
|
|
**Permission**: IsAuthenticated
|
|
|
|
**Inherits**: AccountModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/system/settings/modules/` - List module settings
|
|
- `POST /api/v1/system/settings/modules/` - Create module setting
|
|
- `GET /api/v1/system/settings/modules/{id}/` - Get module setting
|
|
- `PUT /api/v1/system/settings/modules/{id}/` - Update module setting
|
|
- `DELETE /api/v1/system/settings/modules/{id}/` - Delete module setting
|
|
|
|
**Custom Actions:**
|
|
- `GET /api/v1/system/settings/modules/module/{module_name}/` - Get settings by module
|
|
- **Response**: `{ "module": "planner", "settings": { ... } }`
|
|
|
|
#### ViewSet: `AISettingsViewSet`
|
|
**Base Path**: `/api/v1/system/settings/ai/`
|
|
|
|
**Permission**: IsAuthenticated
|
|
|
|
**Inherits**: AccountModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/system/settings/ai/` - List AI settings
|
|
- `POST /api/v1/system/settings/ai/` - Create AI setting
|
|
- `GET /api/v1/system/settings/ai/{id}/` - Get AI setting
|
|
- `PUT /api/v1/system/settings/ai/{id}/` - Update AI setting
|
|
- `DELETE /api/v1/system/settings/ai/{id}/` - Delete AI setting
|
|
|
|
### System Status Endpoints
|
|
|
|
#### GET `/api/v1/system/status/`
|
|
**Purpose**: System health check
|
|
|
|
**Authentication**: AllowAny
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "healthy",
|
|
"database": "connected",
|
|
"redis": "connected",
|
|
"celery": "running",
|
|
"version": "1.0.0"
|
|
}
|
|
```
|
|
|
|
**Status Codes**: 200 (OK), 503 (Service Unavailable)
|
|
|
|
#### GET `/api/v1/system/request-metrics/{request_id}/`
|
|
**Purpose**: Get request metrics for debugging
|
|
|
|
**Authentication**: Required (typically admin/developer only)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"request_id": "abc123",
|
|
"cpu_percent": 25.5,
|
|
"memory_mb": 512,
|
|
"io_read_mb": 10.2,
|
|
"io_write_mb": 5.1
|
|
}
|
|
```
|
|
|
|
#### POST `/api/v1/system/webhook/`
|
|
**Purpose**: Gitea webhook endpoint
|
|
|
|
**Authentication**: Webhook secret validation
|
|
|
|
**Request**: Gitea webhook payload
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Webhook processed"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Billing Module Endpoints
|
|
|
|
**Base Path**: `/api/v1/billing/`
|
|
|
|
### Credit Balance Endpoints
|
|
|
|
#### ViewSet: `CreditBalanceViewSet`
|
|
**Base Path**: `/api/v1/billing/credits/balance/`
|
|
|
|
**Permission**: IsAuthenticated
|
|
|
|
**Custom Actions:**
|
|
- `GET /api/v1/billing/credits/balance/balance/` - Get credit balance
|
|
- **Response**:
|
|
```json
|
|
{
|
|
"credits": 1000,
|
|
"plan_credits_per_month": 500,
|
|
"credits_used_this_month": 250,
|
|
"credits_remaining": 750
|
|
}
|
|
```
|
|
|
|
### Credit Usage Endpoints
|
|
|
|
#### ViewSet: `CreditUsageViewSet`
|
|
**Base Path**: `/api/v1/billing/credits/usage/`
|
|
|
|
**Permission**: IsAuthenticated
|
|
|
|
**Inherits**: ReadOnlyModelViewSet (read-only)
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/billing/credits/usage/` - List usage logs (paginated)
|
|
- `GET /api/v1/billing/credits/usage/{id}/` - Get usage log
|
|
|
|
**Filtering:**
|
|
- `operation_type`: Filter by operation type (clustering, ideas, content, images, reparse)
|
|
- `start_date`: Filter by start date (YYYY-MM-DD)
|
|
- `end_date`: Filter by end date (YYYY-MM-DD)
|
|
|
|
**Custom Actions:**
|
|
- `GET /api/v1/billing/credits/usage/summary/` - Get usage summary
|
|
- **Query Params**: `start_date`, `end_date` (optional)
|
|
- **Response**:
|
|
```json
|
|
{
|
|
"total_credits_used": 500,
|
|
"total_cost_usd": 25.50,
|
|
"by_operation": {
|
|
"clustering": 100,
|
|
"ideas": 50,
|
|
"content": 300,
|
|
"images": 50
|
|
}
|
|
}
|
|
```
|
|
|
|
- `GET /api/v1/billing/credits/usage/limits/` - Get usage limits
|
|
- **Response**:
|
|
```json
|
|
{
|
|
"plan_limits": {
|
|
"max_keywords": 10000,
|
|
"max_clusters": 1000,
|
|
"max_ideas": 5000,
|
|
"max_ai_requests": 10000
|
|
},
|
|
"current_usage": {
|
|
"keywords": 5000,
|
|
"clusters": 500,
|
|
"ideas": 2500,
|
|
"ai_requests": 5000
|
|
}
|
|
}
|
|
```
|
|
|
|
### Credit Transaction Endpoints
|
|
|
|
#### ViewSet: `CreditTransactionViewSet`
|
|
**Base Path**: `/api/v1/billing/credits/transactions/`
|
|
|
|
**Permission**: IsAuthenticated
|
|
|
|
**Inherits**: ReadOnlyModelViewSet (read-only)
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/billing/credits/transactions/` - List transactions (paginated)
|
|
- `GET /api/v1/billing/credits/transactions/{id}/` - Get transaction
|
|
|
|
**Filtering:**
|
|
- `transaction_type`: Filter by type (purchase, subscription, refund, deduction, adjustment)
|
|
- `start_date`: Filter by start date
|
|
- `end_date`: Filter by end date
|
|
|
|
**Ordering:**
|
|
- Default: `-created_at` (newest first)
|
|
|
|
---
|
|
|
|
## Frontend API Usage Patterns
|
|
|
|
### API Client Implementation
|
|
|
|
**File**: `frontend/src/services/api.ts`
|
|
|
|
**Base URL Detection:**
|
|
- Checks `VITE_BACKEND_URL` or `VITE_API_URL` environment variable
|
|
- Auto-detects based on current origin (localhost, IP, subdomain)
|
|
- Production default: `https://api.igny8.com/api`
|
|
|
|
**Authentication:**
|
|
- JWT token stored in Zustand auth store
|
|
- Token included in `Authorization: Bearer <token>` header
|
|
- Automatic token refresh on 401 responses
|
|
- Token stored in localStorage (persisted)
|
|
|
|
**Request Function:**
|
|
```typescript
|
|
fetchAPI(endpoint: string, options?: RequestInit)
|
|
```
|
|
|
|
**Features:**
|
|
- Automatic JWT token injection
|
|
- 30-second timeout (configurable)
|
|
- Automatic token refresh on 401
|
|
- Error handling and parsing
|
|
- Content-type detection
|
|
|
|
### Common Usage Patterns
|
|
|
|
**List Endpoints:**
|
|
```typescript
|
|
const response = await fetchAPI('/v1/planner/keywords/?page=1&page_size=25');
|
|
const data = await response.json();
|
|
// Returns: { count, next, previous, results: [...] }
|
|
```
|
|
|
|
**Create Endpoints:**
|
|
```typescript
|
|
const response = await fetchAPI('/v1/planner/keywords/', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ keyword: '...', site_id: 1, sector_id: 1 })
|
|
});
|
|
```
|
|
|
|
**Custom Actions:**
|
|
```typescript
|
|
const response = await fetchAPI('/v1/planner/keywords/auto_cluster/', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ ids: [1, 2, 3], sector_id: 1 })
|
|
});
|
|
// Returns: { success: true, task_id: "abc123" }
|
|
```
|
|
|
|
**Progress Tracking:**
|
|
```typescript
|
|
// Poll progress endpoint
|
|
const progress = await fetchAPI(`/v1/system/settings/task_progress/${taskId}/`);
|
|
// Returns: { state: "PROGRESS", meta: { phase: "AI_CALL", percentage: 50 } }
|
|
```
|
|
|
|
### State Management Integration
|
|
|
|
**Zustand Stores:**
|
|
- Auth Store: Manages JWT token and user data
|
|
- Site Store: Manages current site selection
|
|
- Sector Store: Manages current sector selection
|
|
- Module Stores: Cache API responses (Planner, Writer, Billing)
|
|
|
|
**API Calls from Stores:**
|
|
- Stores use `fetchAPI` for all API calls
|
|
- Responses cached in store state
|
|
- Automatic re-fetch on state changes
|
|
|
|
---
|
|
|
|
## Third-Party Integrations
|
|
|
|
### OpenAI Integration
|
|
|
|
**Purpose**: Text generation (GPT models) and image generation (DALL-E)
|
|
|
|
**Configuration:**
|
|
- Stored in `IntegrationSettings` model
|
|
- Integration type: `openai`
|
|
- Config fields: `apiKey`, `model`, `max_tokens`, `temperature`
|
|
|
|
**API Usage:**
|
|
- Called via `AICore.run_ai_request()` for text generation
|
|
- Called via `AICore.generate_image()` for image generation
|
|
- Account-specific API keys
|
|
- Cost tracking per request
|
|
|
|
**Endpoints Used:**
|
|
- OpenAI API: `https://api.openai.com/v1/chat/completions`
|
|
- OpenAI DALL-E: `https://api.openai.com/v1/images/generations`
|
|
|
|
**Dependencies:**
|
|
- `requests` library for HTTP calls
|
|
- API key stored per account in database
|
|
|
|
### Runware Integration
|
|
|
|
**Purpose**: Alternative image generation service
|
|
|
|
**Configuration:**
|
|
- Stored in `IntegrationSettings` model
|
|
- Integration type: `runware`
|
|
- Config fields: `apiKey`, `model` (e.g., `runware:97@1`), `image_type`
|
|
|
|
**API Usage:**
|
|
- Called via `AICore.generate_image()` for image generation
|
|
- Account-specific API keys
|
|
- Cost tracking per image
|
|
|
|
**Endpoints Used:**
|
|
- Runware API: `https://api.runware.com/v1/images/generate`
|
|
|
|
**Dependencies:**
|
|
- `requests` library for HTTP calls
|
|
- API key stored per account in database
|
|
|
|
### WordPress Integration
|
|
|
|
**Purpose**: Content publishing to WordPress sites
|
|
|
|
**Configuration:**
|
|
- Stored in `Site` model
|
|
- Fields: `wp_url`, `wp_username`, `wp_app_password`
|
|
- Per-site configuration
|
|
|
|
**API Usage:**
|
|
- WordPress REST API calls
|
|
- Creates posts with content HTML
|
|
- Uploads images to media library
|
|
- Sets post meta (keywords, etc.)
|
|
|
|
**Endpoints Used:**
|
|
- WordPress REST API: `{wp_url}/wp-json/wp/v2/posts`
|
|
- WordPress Media API: `{wp_url}/wp-json/wp/v2/media`
|
|
|
|
**Dependencies:**
|
|
- `requests` library for HTTP calls
|
|
- WordPress REST API (built into WordPress)
|
|
|
|
### Gitea Webhook Integration
|
|
|
|
**Purpose**: Receive webhook events from Gitea
|
|
|
|
**Endpoint**: `POST /api/v1/system/webhook/`
|
|
|
|
**Configuration:**
|
|
- Webhook secret validation
|
|
- Processes push events, pull requests, etc.
|
|
|
|
**Dependencies:**
|
|
- Webhook secret stored in environment variables
|
|
|
|
---
|
|
|
|
## Dependencies
|
|
|
|
### Backend Dependencies
|
|
|
|
**Core Framework:**
|
|
- `Django 5.2+`: Web framework
|
|
- `djangorestframework`: REST API framework
|
|
- `django-filter`: Advanced filtering
|
|
- `django-cors-headers`: CORS handling
|
|
|
|
**Authentication:**
|
|
- `PyJWT 2.8.0+`: JWT token handling
|
|
- Custom JWT implementation (not djangorestframework-simplejwt)
|
|
|
|
**Database:**
|
|
- `psycopg2-binary`: PostgreSQL adapter
|
|
- `PostgreSQL 15`: Database
|
|
|
|
**Task Queue:**
|
|
- `Celery 5.3.0+`: Asynchronous task processing
|
|
- `Redis 7`: Celery broker and cache
|
|
|
|
**HTTP Client:**
|
|
- `requests 2.31.0+`: External API calls (OpenAI, Runware, WordPress)
|
|
|
|
**Utilities:**
|
|
- `python-dotenv`: Environment variable management
|
|
- `BeautifulSoup4`: HTML parsing
|
|
- `psutil`: System utilities
|
|
- `docker`: Docker API client
|
|
|
|
### Frontend Dependencies
|
|
|
|
**HTTP Client:**
|
|
- Native `fetch` API (no external HTTP library)
|
|
- Custom `fetchAPI` wrapper in `frontend/src/services/api.ts`
|
|
|
|
**State Management:**
|
|
- `Zustand 5.0.8`: State management
|
|
- Token stored in Zustand auth store
|
|
- API responses cached in module stores
|
|
|
|
**No External API Libraries:**
|
|
- No Axios, no React Query, no SWR
|
|
- Pure fetch API with custom wrapper
|
|
|
|
---
|
|
|
|
## Rate Limiting
|
|
|
|
### Current Status
|
|
|
|
**Rate Limiting**: ❌ **Not Implemented**
|
|
|
|
**Status**: Planned for future implementation
|
|
|
|
**Configuration**: None in current settings
|
|
|
|
### Planned Implementation
|
|
|
|
**Location**: `docs/02-APPLICATION-ARCHITECTURE.md` mentions rate limiting as planned feature
|
|
|
|
**Recommendation**: Implement using DRF throttling classes:
|
|
- `rest_framework.throttling.AnonRateThrottle`: For anonymous users
|
|
- `rest_framework.throttling.UserRateThrottle`: For authenticated users
|
|
- Custom throttling for AI endpoints (higher limits)
|
|
|
|
---
|
|
|
|
## Standardization Recommendations
|
|
|
|
### Current Issues
|
|
|
|
1. **Inconsistent Permission Classes:**
|
|
- Many ViewSets use `permission_classes = []` (AllowAny)
|
|
- Should standardize to `IsAuthenticated` for most endpoints
|
|
- Only public endpoints should use `AllowAny`
|
|
|
|
2. **Inconsistent Response Formats:**
|
|
- Some endpoints return `{ success: true, data: ... }`
|
|
- Some endpoints return DRF standard format
|
|
- Some endpoints return custom formats
|
|
- Should standardize to one format
|
|
|
|
3. **Mixed Authentication:**
|
|
- JWT primary, but session and basic auth also enabled
|
|
- Should document which endpoints use which method
|
|
- Should standardize authentication requirements
|
|
|
|
4. **No Rate Limiting:**
|
|
- All endpoints are unlimited
|
|
- Should implement rate limiting for production
|
|
|
|
5. **Inconsistent Error Handling:**
|
|
- Some endpoints return `{ error: "..." }`
|
|
- Some return `{ success: false, message: "..." }`
|
|
- Should standardize error response format
|
|
|
|
### Recommendations
|
|
|
|
1. **Standardize Response Format:**
|
|
- Use consistent `{ success, data, message, errors }` format
|
|
- Apply to all endpoints
|
|
- Create response mixin for ViewSets
|
|
|
|
2. **Standardize Permissions:**
|
|
- Default to `IsAuthenticated` for all endpoints
|
|
- Only explicitly allow `AllowAny` for public endpoints
|
|
- Document permission requirements
|
|
|
|
3. **Implement Rate Limiting:**
|
|
- Add DRF throttling classes
|
|
- Different limits for different endpoint types
|
|
- Document rate limits
|
|
|
|
4. **Standardize Error Handling:**
|
|
- Use consistent error response format
|
|
- Include error codes for programmatic handling
|
|
- Document all error codes
|
|
|
|
5. **API Versioning:**
|
|
- Current: `/api/v1/`
|
|
- Plan for future versions
|
|
- Document versioning strategy
|
|
|
|
6. **API Documentation:**
|
|
- Consider adding OpenAPI/Swagger documentation
|
|
- Document all endpoints with request/response examples
|
|
- Include authentication requirements
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
### Endpoint Statistics
|
|
|
|
- **Total Endpoints**: 100+ endpoints
|
|
- **Auth Module**: 15+ endpoints
|
|
- **Planner Module**: 20+ endpoints
|
|
- **Writer Module**: 20+ endpoints
|
|
- **System Module**: 30+ endpoints
|
|
- **Billing Module**: 10+ endpoints
|
|
|
|
### Authentication
|
|
|
|
- **Primary**: JWT Bearer tokens
|
|
- **Fallback**: Session authentication
|
|
- **Fallback**: Basic authentication
|
|
- **Account Context**: Set via middleware from JWT
|
|
|
|
### Response Formats
|
|
|
|
- **Success**: `{ success: true, data: ..., message: ... }`
|
|
- **Error**: `{ success: false, error: ..., errors: ... }`
|
|
- **Pagination**: `{ count, next, previous, results: [...] }`
|
|
|
|
### Current Gaps
|
|
|
|
- ❌ No rate limiting
|
|
- ⚠️ Inconsistent permission classes
|
|
- ⚠️ Inconsistent response formats
|
|
- ⚠️ No API documentation (OpenAPI/Swagger)
|
|
- ✅ Good: Consistent pagination
|
|
- ✅ Good: Account isolation
|
|
- ✅ Good: Site/sector filtering
|
|
|
|
### Third-Party Integrations
|
|
|
|
- **OpenAI**: Text and image generation
|
|
- **Runware**: Image generation
|
|
- **WordPress**: Content publishing
|
|
- **Gitea**: Webhook integration
|
|
|
|
---
|
|
|
|
**Document Status**: Complete analysis of all existing API endpoints
|
|
**Last Updated**: 2025-01-XX
|
|
|