# 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 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 ` 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