Files
igny8/unified-api/API-ENDPOINTS-ANALYSIS.md

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