1808 lines
47 KiB
Markdown
1808 lines
47 KiB
Markdown
# IGNY8 API Complete Reference v1.0
|
|
|
|
**Base URL**: `https://api.igny8.com/api/v1/`
|
|
**Version**: 1.0.0
|
|
**Last Updated**: 2025-01-XX (Added 6 missing modules: Linker, Optimizer, Publisher, Site Builder, Automation, Integration)
|
|
**Status**: ✅ **100% IMPLEMENTED** - All endpoints use unified format
|
|
|
|
**Purpose**: Complete, unified reference for IGNY8 API covering authentication, endpoints, response formats, error handling, rate limiting, permissions, and integration examples.
|
|
|
|
---
|
|
|
|
## Table of Contents
|
|
|
|
1. [Quick Start](#quick-start)
|
|
2. [Overview & Architecture](#overview--architecture)
|
|
3. [Authentication & Authorization](#authentication--authorization)
|
|
4. [Response Format Standard](#response-format-standard)
|
|
5. [Error Handling](#error-handling)
|
|
6. [Rate Limiting](#rate-limiting)
|
|
7. [Pagination](#pagination)
|
|
8. [Roles & Permissions](#roles--permissions)
|
|
9. [Tenant / Site / Sector Scoping](#tenant--site--sector-scoping)
|
|
10. [Complete Endpoint Reference](#complete-endpoint-reference)
|
|
11. [Integration Examples](#integration-examples)
|
|
12. [Testing & Debugging](#testing--debugging)
|
|
13. [Change Management](#change-management)
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
### Interactive Documentation
|
|
|
|
- **Swagger UI**: `https://api.igny8.com/api/docs/`
|
|
- **ReDoc**: `https://api.igny8.com/api/redoc/`
|
|
- **OpenAPI Schema**: `https://api.igny8.com/api/schema/`
|
|
|
|
### Basic Example
|
|
|
|
```python
|
|
import requests
|
|
|
|
BASE_URL = "https://api.igny8.com/api/v1"
|
|
|
|
# 1. Login
|
|
response = requests.post(
|
|
f"{BASE_URL}/auth/login/",
|
|
json={"email": "user@example.com", "password": "password"}
|
|
)
|
|
data = response.json()
|
|
|
|
if data['success']:
|
|
token = data['data']['access']
|
|
|
|
# 2. Use token for authenticated requests
|
|
headers = {
|
|
'Authorization': f'Bearer {token}',
|
|
'Content-Type': 'application/json'
|
|
}
|
|
|
|
# 3. Get keywords
|
|
response = requests.get(
|
|
f"{BASE_URL}/planner/keywords/",
|
|
headers=headers
|
|
)
|
|
result = response.json()
|
|
|
|
if result['success']:
|
|
keywords = result['results'] # Paginated results
|
|
print(f"Found {result['count']} keywords")
|
|
```
|
|
|
|
---
|
|
|
|
## Overview & Architecture
|
|
|
|
### API Standard v1.0 - Key Principles
|
|
|
|
1. **Unified Response Format**: All endpoints return consistent JSON structure
|
|
2. **Layered Authorization**: Authentication → Tenant Access → Role → Site/Sector
|
|
3. **Centralized Error Handling**: All errors wrapped in unified format
|
|
4. **Scoped Rate Limiting**: Different limits for different operation types
|
|
5. **Tenant Isolation**: All resources scoped by account/site/sector
|
|
6. **Request Tracking**: Every request has a unique ID for debugging
|
|
|
|
### Base URL Structure
|
|
|
|
```
|
|
Production: https://api.igny8.com/api/v1/
|
|
Development: http://localhost:8000/api/v1/
|
|
```
|
|
|
|
### Module Namespaces
|
|
|
|
```
|
|
/api/v1/
|
|
├── auth/ # Authentication and user management
|
|
├── planner/ # Keywords, clusters, content ideas
|
|
├── writer/ # Tasks, content, images
|
|
├── linker/ # Internal linking operations
|
|
├── optimizer/ # Content optimization and scoring
|
|
├── publisher/ # Publishing records and site deployment
|
|
├── site-builder/ # Site blueprint management
|
|
├── automation/ # Automation rules and scheduled tasks
|
|
├── integration/ # External platform integrations
|
|
├── system/ # Settings, prompts, integrations
|
|
└── billing/ # Credits, transactions, usage
|
|
```
|
|
|
|
### Technology Stack
|
|
|
|
- **Framework**: Django REST Framework (DRF)
|
|
- **Authentication**: JWT Bearer tokens (primary), Session (fallback), Basic (fallback)
|
|
- **Pagination**: CustomPageNumberPagination (default: 10, max: 100)
|
|
- **Rate Limiting**: Scoped throttles per module/operation type
|
|
- **OpenAPI**: drf-spectacular for schema generation
|
|
|
|
### Implementation Status
|
|
|
|
✅ **100% Complete** - All endpoints implemented with:
|
|
- Unified response format
|
|
- Proper authentication and authorization
|
|
- Rate limiting configured
|
|
- Error handling standardized
|
|
- Request ID tracking
|
|
- Complete Swagger/OpenAPI documentation
|
|
|
|
---
|
|
|
|
## Authentication & Authorization
|
|
|
|
### Authentication Methods
|
|
|
|
#### Primary: JWT Bearer Token
|
|
|
|
```
|
|
Authorization: Bearer <access_token>
|
|
```
|
|
|
|
**Token Characteristics:**
|
|
- Contains `user_id` and `account_id`
|
|
- Type: `access` (15-minute expiry)
|
|
- Automatically sets `request.account` via middleware
|
|
- Resolves account → tenant context automatically
|
|
|
|
**Token Payload:**
|
|
```json
|
|
{
|
|
"user_id": 1,
|
|
"account_id": 1,
|
|
"type": "access",
|
|
"exp": 1234567890
|
|
}
|
|
```
|
|
|
|
#### Fallback Methods
|
|
|
|
1. **Session Authentication** (admin panel)
|
|
- Class: `CSRFExemptSessionAuthentication`
|
|
- Use case: Django admin panel (`/admin/`)
|
|
|
|
2. **Basic Authentication** (debug/testing)
|
|
- Class: `rest_framework.authentication.BasicAuthentication`
|
|
- Use case: API testing tools (Postman, curl)
|
|
|
|
### Authentication Order
|
|
|
|
1. JWT Token Authentication (tried first)
|
|
2. Session Authentication (fallback)
|
|
3. Basic Authentication (last fallback)
|
|
4. If all fail: 401 Unauthorized
|
|
|
|
### Getting an Access Token
|
|
|
|
**Login Endpoint:**
|
|
```http
|
|
POST /api/v1/auth/login/
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"email": "user@example.com",
|
|
"password": "your_password"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"user": {
|
|
"id": 1,
|
|
"email": "user@example.com",
|
|
"username": "user",
|
|
"role": "owner",
|
|
"account": { ... }
|
|
},
|
|
"access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
},
|
|
"request_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
### Token Expiration
|
|
|
|
- **Access Token**: 15 minutes
|
|
- **Refresh Token**: 7 days
|
|
|
|
**Refresh Token:**
|
|
```http
|
|
POST /api/v1/auth/refresh/
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"refresh": "your_refresh_token"
|
|
}
|
|
```
|
|
|
|
### Public Endpoints (No Authentication Required)
|
|
|
|
- `POST /api/v1/auth/register/` - User registration
|
|
- `POST /api/v1/auth/login/` - User login
|
|
- `GET /api/v1/auth/plans/` - List plans
|
|
- `GET /api/v1/auth/industries/` - List industries
|
|
- `GET /api/v1/system/status/` - System health check
|
|
- `GET /api/v1/system/ping/` - Health check endpoint
|
|
- `GET /api/v1/publisher/sites/{site_id}/definition/` - Get site definition for Sites Renderer
|
|
|
|
**All other endpoints require JWT authentication.**
|
|
|
|
### Authorization Layers
|
|
|
|
Every endpoint enforces layered authorization:
|
|
|
|
1. **User Authentication**: User must be authenticated
|
|
2. **Tenant Access**: User must belong to the tenant/account
|
|
3. **Role Authorization**: User must have appropriate role
|
|
4. **Site/Sector Access**: User must have access to requested site/sector
|
|
|
|
---
|
|
|
|
## Response Format Standard
|
|
|
|
### Mandatory Format
|
|
|
|
**This is the global standard for all endpoints - no exceptions.**
|
|
|
|
### Success Response
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"id": 1,
|
|
"name": "Example Keyword",
|
|
"status": "active"
|
|
},
|
|
"message": "Optional human-readable success message",
|
|
"request_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
### Paginated Response
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"count": 120,
|
|
"next": "http://api.igny8.com/api/v1/planner/keywords/?page=3",
|
|
"previous": "http://api.igny8.com/api/v1/planner/keywords/?page=1",
|
|
"results": [
|
|
{"id": 1, "name": "Keyword 1"},
|
|
{"id": 2, "name": "Keyword 2"},
|
|
...
|
|
],
|
|
"request_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
### Error Response
|
|
|
|
```json
|
|
{
|
|
"success": false,
|
|
"error": "Readable top-level error message",
|
|
"errors": {
|
|
"field_name": ["Field-specific error messages"]
|
|
},
|
|
"request_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
### Response Helper Functions
|
|
|
|
**File:** `backend/igny8_core/api/response.py`
|
|
|
|
```python
|
|
from igny8_core.api.response import success_response, error_response, paginated_response
|
|
|
|
# Success response
|
|
return success_response(
|
|
data={"id": 1, "name": "Example"},
|
|
message="Resource created successfully",
|
|
status_code=status.HTTP_201_CREATED
|
|
)
|
|
|
|
# Error response
|
|
return error_response(
|
|
error="Validation failed",
|
|
errors={"email": ["Invalid email format"]},
|
|
status_code=status.HTTP_400_BAD_REQUEST
|
|
)
|
|
|
|
# Paginated response
|
|
paginator = CustomPageNumberPagination()
|
|
page = paginator.paginate_queryset(queryset, request)
|
|
serializer = MySerializer(page, many=True)
|
|
paginated_data = paginator.get_paginated_response(serializer.data).data
|
|
return paginated_response(paginated_data, message="Resources retrieved successfully")
|
|
```
|
|
|
|
---
|
|
|
|
## Error Handling
|
|
|
|
### HTTP Status Codes
|
|
|
|
| Code | Meaning | Description |
|
|
|------|---------|-------------|
|
|
| 200 | OK | Request successful |
|
|
| 201 | Created | Resource created successfully |
|
|
| 204 | No Content | Resource deleted successfully |
|
|
| 400 | Bad Request | Validation error or invalid request |
|
|
| 401 | Unauthorized | Authentication required |
|
|
| 403 | Forbidden | Permission denied |
|
|
| 404 | Not Found | Resource not found |
|
|
| 409 | Conflict | Resource conflict (e.g., duplicate) |
|
|
| 422 | Unprocessable Entity | Validation failed |
|
|
| 429 | Too Many Requests | Rate limit exceeded |
|
|
| 500 | Internal Server Error | Server error |
|
|
|
|
### Centralized Exception Handler
|
|
|
|
**File:** `backend/igny8_core/api/exception_handlers.py`
|
|
|
|
All exceptions are handled by a centralized exception handler that:
|
|
- Wraps all errors in unified format
|
|
- Uses proper HTTP status codes
|
|
- Includes sanitized validation errors under `errors`
|
|
- Always attaches `request_id` for error tracking
|
|
- Logs full exception details
|
|
- In DEBUG mode: includes traceback + request context
|
|
|
|
### Error Response Examples
|
|
|
|
**Validation Error (400):**
|
|
```json
|
|
{
|
|
"success": false,
|
|
"error": "Validation failed",
|
|
"errors": {
|
|
"email": ["Invalid email format"],
|
|
"password": ["Password must be at least 8 characters"]
|
|
},
|
|
"request_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
**Authentication Error (401):**
|
|
```json
|
|
{
|
|
"success": false,
|
|
"error": "Authentication required",
|
|
"request_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
**Permission Error (403):**
|
|
```json
|
|
{
|
|
"success": false,
|
|
"error": "Permission denied",
|
|
"request_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
**Rate Limit (429):**
|
|
```json
|
|
{
|
|
"success": false,
|
|
"error": "Rate limit exceeded",
|
|
"request_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
### Server-side Logging
|
|
|
|
- All 4xx errors logged as **warning**
|
|
- All 5xx errors logged as **error**
|
|
- Structured format with timestamp, request_id, endpoint, user_id, account_id, status_code, error_message
|
|
- Rotating log files
|
|
- Sentry integration hooks for production
|
|
|
|
---
|
|
|
|
## Rate Limiting
|
|
|
|
### Rate Limiting Configuration
|
|
|
|
Rate limits are scoped by operation type. Check response headers for limit information:
|
|
|
|
- `X-Throttle-Limit`: Maximum requests allowed
|
|
- `X-Throttle-Remaining`: Remaining requests in current window
|
|
- `X-Throttle-Reset`: Time when limit resets (Unix timestamp)
|
|
|
|
### Rate Limit Scopes
|
|
|
|
| Scope | Limit | Description |
|
|
|-------|-------|-------------|
|
|
| `ai_function` | 10/min | AI content generation, clustering |
|
|
| `image_gen` | 15/min | Image generation |
|
|
| `content_write` | 30/min | Content creation, updates |
|
|
| `content_read` | 100/min | Content listing, retrieval |
|
|
| `auth` | 20/min | Login, register, password reset |
|
|
| `auth_strict` | 5/min | Sensitive auth operations |
|
|
| `planner` | 60/min | Keyword, cluster, idea operations |
|
|
| `planner_ai` | 10/min | AI-powered planner operations |
|
|
| `writer` | 60/min | Task, content management |
|
|
| `writer_ai` | 10/min | AI-powered writer operations |
|
|
| `system` | 100/min | Settings, prompts, profiles |
|
|
| `system_admin` | 30/min | Admin-only system operations |
|
|
| `billing` | 30/min | Credit queries, usage logs |
|
|
| `billing_admin` | 10/min | Credit management (admin) |
|
|
| `default` | 100/min | Default for endpoints without scope |
|
|
|
|
### Handling Rate Limits
|
|
|
|
When rate limited (429), the response includes:
|
|
- Error message: "Rate limit exceeded"
|
|
- Headers with reset time
|
|
- Wait until `X-Throttle-Reset` before retrying
|
|
|
|
**Example:**
|
|
```http
|
|
HTTP/1.1 429 Too Many Requests
|
|
X-Throttle-Limit: 60
|
|
X-Throttle-Remaining: 0
|
|
X-Throttle-Reset: 1700123456
|
|
Retry-After: 60
|
|
|
|
{
|
|
"success": false,
|
|
"error": "Rate limit exceeded",
|
|
"request_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
### Debug Mode Bypass
|
|
|
|
Set `IGNY8_DEBUG_THROTTLE=True` or `DEBUG=True` to bypass throttling in development.
|
|
|
|
---
|
|
|
|
## Pagination
|
|
|
|
### Pagination Configuration
|
|
|
|
**Default Settings:**
|
|
- Default page size: **10**
|
|
- Maximum page size: **100**
|
|
- Query parameter: `page_size` (optional)
|
|
- Page parameter: `page` (default: 1)
|
|
|
|
### Query Parameters
|
|
|
|
**Pagination:**
|
|
```
|
|
?page=2&page_size=25
|
|
```
|
|
|
|
**Filtering:**
|
|
```
|
|
?status=active
|
|
?site_id=1
|
|
?sector_id=2
|
|
?cluster_id=5
|
|
```
|
|
|
|
**Search:**
|
|
```
|
|
?search=keyword
|
|
```
|
|
|
|
**Ordering:**
|
|
```
|
|
?ordering=-created_at
|
|
?ordering=name,status
|
|
```
|
|
|
|
### Pagination Response Format
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"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": [
|
|
// Array of results
|
|
],
|
|
"request_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
### Pagination Fields
|
|
|
|
- `count`: Total number of items
|
|
- `next`: URL to next page (null if last page)
|
|
- `previous`: URL to previous page (null if first page)
|
|
- `results`: Array of items for current page
|
|
|
|
---
|
|
|
|
## Roles & Permissions
|
|
|
|
### Role Hierarchy
|
|
|
|
```
|
|
owner > admin > editor > viewer > system_bot
|
|
```
|
|
|
|
### Standard Permission Classes
|
|
|
|
**File:** `backend/igny8_core/api/permissions.py`
|
|
|
|
| Permission Class | Description | Use Case |
|
|
|-----------------|------------|----------|
|
|
| `IsAuthenticatedAndActive` | User authenticated and active | Base permission for most endpoints |
|
|
| `HasTenantAccess` | User belongs to tenant/account | Tenant isolation |
|
|
| `IsViewerOrAbove` | Viewer, editor, admin, or owner | Read-only operations |
|
|
| `IsEditorOrAbove` | Editor, admin, or owner | Content operations |
|
|
| `IsAdminOrOwner` | Admin or owner only | Settings, keys, billing |
|
|
|
|
### Permission Matrix by Endpoint Type
|
|
|
|
| Endpoint Type | Required Permissions | Roles Allowed |
|
|
|--------------|---------------------|---------------|
|
|
| Public (register, login) | `AllowAny` | Anyone |
|
|
| Read-only (list, retrieve) | `IsAuthenticatedAndActive` + `HasTenantAccess` | All authenticated users |
|
|
| Content operations | `IsAuthenticatedAndActive` + `HasTenantAccess` + `IsEditorOrAbove` | Editor, Admin, Owner |
|
|
| User management | `IsAuthenticatedAndActive` + `HasTenantAccess` + `IsAdminOrOwner` | Admin, Owner |
|
|
| Billing/Transactions | `IsAuthenticatedAndActive` + `HasTenantAccess` + `IsAdminOrOwner` | Admin, Owner |
|
|
| Integration settings | `IsAuthenticatedAndActive` + `HasTenantAccess` + `IsAdminOrOwner` | Admin, Owner |
|
|
|
|
---
|
|
|
|
## Tenant / Site / Sector Scoping
|
|
|
|
### Scoping Rules
|
|
|
|
Every resource created or fetched must be scoped by:
|
|
|
|
1. **Account/Tenant** - User's account
|
|
2. **Site** - Specific site within account
|
|
3. **Sector** - Specific sector within site
|
|
|
|
### Enforcement
|
|
|
|
**Base Classes:**
|
|
- `AccountModelViewSet` - Handles account isolation
|
|
- `SiteSectorModelViewSet` - Filters queries by site/sector
|
|
|
|
**Requirements:**
|
|
- All custom actions must use `.get_queryset()` to avoid bypassing filters
|
|
- Any ID list must be verified to belong to the authenticated tenant
|
|
- Site/sector access validated based on user role
|
|
|
|
### Scoping Example
|
|
|
|
```python
|
|
class KeywordViewSet(SiteSectorModelViewSet):
|
|
# Automatically filters by:
|
|
# 1. account (from request.account)
|
|
# 2. site_id (from query params or request)
|
|
# 3. sector_id (from query params or request)
|
|
|
|
queryset = Keyword.objects.all()
|
|
serializer_class = KeywordSerializer
|
|
|
|
def get_queryset(self):
|
|
# Base class handles account/site/sector filtering
|
|
queryset = super().get_queryset()
|
|
# Additional filtering can be added here
|
|
return queryset
|
|
```
|
|
|
|
---
|
|
|
|
## Complete Endpoint Reference
|
|
|
|
### Authentication Endpoints
|
|
|
|
**Base Path**: `/api/v1/auth/`
|
|
|
|
#### POST `/api/v1/auth/register/`
|
|
**Purpose**: User registration
|
|
**Authentication**: None (AllowAny)
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"email": "user@example.com",
|
|
"password": "password123",
|
|
"password_confirm": "password123"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"user": {
|
|
"id": 1,
|
|
"email": "user@example.com",
|
|
"role": "owner",
|
|
"account": { ... }
|
|
}
|
|
},
|
|
"message": "Registration successful"
|
|
}
|
|
```
|
|
|
|
#### POST `/api/v1/auth/login/`
|
|
**Purpose**: User login
|
|
**Authentication**: None (AllowAny)
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"email": "user@example.com",
|
|
"password": "password123"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"user": { ... },
|
|
"access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
|
|
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc...",
|
|
"access_expires_at": "2025-01-XXT...",
|
|
"refresh_expires_at": "2025-01-XXT..."
|
|
},
|
|
"message": "Login successful",
|
|
"request_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
}
|
|
```
|
|
|
|
#### POST `/api/v1/auth/refresh/`
|
|
**Purpose**: Refresh access token
|
|
**Authentication**: None (requires refresh token)
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"refresh": "your_refresh_token"
|
|
}
|
|
```
|
|
|
|
#### POST `/api/v1/auth/change-password/`
|
|
**Purpose**: Change user password
|
|
**Authentication**: Required (IsAuthenticated)
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"old_password": "oldpass123",
|
|
"new_password": "newpass123",
|
|
"new_password_confirm": "newpass123"
|
|
}
|
|
```
|
|
|
|
#### GET `/api/v1/auth/me/`
|
|
**Purpose**: Get current user information
|
|
**Authentication**: Required (IsAuthenticated)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"user": {
|
|
"id": 1,
|
|
"email": "user@example.com",
|
|
"role": "owner",
|
|
"account": { ... },
|
|
"accessible_sites": [ ... ]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### User Management Endpoints
|
|
|
|
**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
|
|
|
|
**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
|
|
|
|
**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
|
|
|
|
**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
|
|
|
|
### Planner Module Endpoints
|
|
|
|
**Base Path**: `/api/v1/planner/`
|
|
|
|
#### Keyword Management
|
|
|
|
**Base Path**: `/api/v1/planner/keywords/`
|
|
**Permission**: IsAuthenticatedAndActive + HasTenantAccess
|
|
**Inherits**: SiteSectorModelViewSet
|
|
|
|
**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`, `difficulty_max` - Difficulty range
|
|
- `volume_min`, `volume_max` - Volume range
|
|
- `site_id` - Filter by site (query param)
|
|
- `sector_id` - Filter by sector (query param)
|
|
|
|
**Search:**
|
|
- `search` - Search by keyword text
|
|
|
|
**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] }`
|
|
- `POST /api/v1/planner/keywords/bulk_update_status/` - Bulk update status
|
|
- Request: `{ "ids": [1, 2, 3], "status": "active" }`
|
|
- `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 }`
|
|
- `GET /api/v1/planner/keywords/export/` - Export keywords to CSV
|
|
- `POST /api/v1/planner/keywords/import_keywords/` - Import keywords from CSV
|
|
- `POST /api/v1/planner/keywords/auto_cluster/` - Auto-cluster keywords using AI
|
|
- Request: `{ "ids": [1, 2, 3, ...], "sector_id": 1 }`
|
|
- Max Keywords: 20 per batch
|
|
- Returns: Celery task ID for progress tracking
|
|
|
|
#### Cluster Management
|
|
|
|
**Base Path**: `/api/v1/planner/clusters/`
|
|
**Permission**: IsAuthenticatedAndActive + HasTenantAccess
|
|
**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
|
|
|
|
**Custom Actions:**
|
|
- `POST /api/v1/planner/clusters/bulk_delete/` - Bulk delete clusters
|
|
- `POST /api/v1/planner/clusters/auto_generate_ideas/` - Auto-generate content ideas
|
|
- Request: `{ "ids": [1] }` (max 1 cluster per batch)
|
|
- Returns: Celery task ID for progress tracking
|
|
|
|
#### Content Ideas Management
|
|
|
|
**Base Path**: `/api/v1/planner/ideas/`
|
|
**Permission**: IsAuthenticatedAndActive + HasTenantAccess
|
|
**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)
|
|
|
|
**Custom Actions:**
|
|
- `POST /api/v1/planner/ideas/bulk_delete/` - Bulk delete ideas
|
|
- `POST /api/v1/planner/ideas/bulk_queue_to_writer/` - Queue ideas to writer (create tasks)
|
|
- Request: `{ "ids": [1, 2, 3] }`
|
|
|
|
### Writer Module Endpoints
|
|
|
|
**Base Path**: `/api/v1/writer/`
|
|
|
|
#### Task Management
|
|
|
|
**Base Path**: `/api/v1/writer/tasks/`
|
|
**Permission**: IsAuthenticatedAndActive + HasTenantAccess
|
|
**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
|
|
|
|
**Custom Actions:**
|
|
- `POST /api/v1/writer/tasks/bulk_delete/` - Bulk delete tasks
|
|
- `POST /api/v1/writer/tasks/bulk_update/` - Bulk update task status
|
|
- `POST /api/v1/writer/tasks/auto_generate_content/` - Auto-generate content using AI
|
|
- Request: `{ "ids": [1, 2, 3, ...] }` (max 50 tasks per batch)
|
|
- Returns: Celery task ID for progress tracking
|
|
|
|
#### Content Management
|
|
|
|
**Base Path**: `/api/v1/writer/content/`
|
|
**Permission**: IsAuthenticatedAndActive + HasTenantAccess
|
|
**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)
|
|
|
|
**Custom Actions:**
|
|
- `POST /api/v1/writer/content/generate_image_prompts/` - Generate image prompts from content
|
|
- Request: `{ "ids": [1, 2, 3] }`
|
|
- Returns: Celery task ID for progress tracking
|
|
|
|
#### Image Management
|
|
|
|
**Base Path**: `/api/v1/writer/images/`
|
|
**Permission**: IsAuthenticatedAndActive + HasTenantAccess
|
|
**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
|
|
- `GET /api/v1/writer/images/content_images/` - Get images for content
|
|
- Query Params: `content_id` (required)
|
|
- `POST /api/v1/writer/images/generate_images/` - Generate images using AI
|
|
- Request: `{ "ids": [1, 2, 3, ...] }`
|
|
- Returns: Celery task ID for progress tracking
|
|
- `POST /api/v1/writer/images/bulk_update/` - Bulk update image status
|
|
|
|
### System Module Endpoints
|
|
|
|
**Base Path**: `/api/v1/system/`
|
|
|
|
#### AI Prompt Management
|
|
|
|
**Base Path**: `/api/v1/system/prompts/`
|
|
**Permission**: IsAuthenticatedAndActive + HasTenantAccess
|
|
**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
|
|
- `POST /api/v1/system/prompts/save/` - Save prompt (requires editor/admin)
|
|
- `POST /api/v1/system/prompts/reset/` - Reset prompt to default
|
|
|
|
#### Integration Settings
|
|
|
|
**Base Path**: `/api/v1/system/settings/integrations/`
|
|
**Permission**: IsAdminOrOwner
|
|
|
|
**Custom URL Patterns:**
|
|
- `GET /api/v1/system/settings/integrations/{pk}/` - Get integration settings
|
|
- `POST /api/v1/system/settings/integrations/{pk}/save/` - Save integration settings
|
|
- `PUT /api/v1/system/settings/integrations/{pk}/` - Update integration settings
|
|
- `POST /api/v1/system/settings/integrations/{pk}/test/` - Test connection
|
|
- Request: `{ "provider": "openai" }` or `{ "provider": "runware" }`
|
|
- `POST /api/v1/system/settings/integrations/{pk}/generate/` - Test image generation
|
|
- `GET /api/v1/system/settings/task_progress/{task_id}/` - Get Celery task progress
|
|
- `GET /api/v1/system/integrations/image_generation/` - Get image generation settings
|
|
|
|
#### System Status
|
|
|
|
**Base Path**: `/api/v1/system/`
|
|
|
|
- `GET /api/v1/system/status/` - System health check (AllowAny)
|
|
- `GET /api/v1/system/ping/` - Health check endpoint (AllowAny)
|
|
- `GET /api/v1/system/request-metrics/{request_id}/` - Get request metrics for debugging
|
|
|
|
### Linker Module Endpoints
|
|
|
|
**Base Path**: `/api/v1/linker/`
|
|
**Permission**: IsAuthenticatedAndActive + HasTenantAccess
|
|
|
|
#### Process Content for Internal Linking
|
|
|
|
- `POST /api/v1/linker/process/` - Process single content item for internal linking
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"content_id": 123
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"content_id": 123,
|
|
"suggested_links": [
|
|
{
|
|
"target_content_id": 456,
|
|
"target_title": "Related Article",
|
|
"anchor_text": "relevant keyword",
|
|
"confidence": 0.85
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Batch Process Content
|
|
|
|
- `POST /api/v1/linker/batch_process/` - Process multiple content items for linking
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"content_ids": [123, 456, 789]
|
|
}
|
|
```
|
|
|
|
### Optimizer Module Endpoints
|
|
|
|
**Base Path**: `/api/v1/optimizer/`
|
|
**Permission**: IsAuthenticatedAndActive + HasTenantAccess
|
|
|
|
#### Optimize Content
|
|
|
|
- `POST /api/v1/optimizer/optimize/` - Optimize content (auto-detects entry point)
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"ids": [123, 456],
|
|
"entry_point": "seo" // Optional: "seo", "readability", "engagement"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"optimized_content": "...",
|
|
"seo_score": 85,
|
|
"readability_score": 78,
|
|
"engagement_score": 82
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Batch Optimize Content
|
|
|
|
- `POST /api/v1/optimizer/batch_optimize/` - Batch optimize multiple content items
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"ids": [123, 456, 789],
|
|
"entry_point": "seo" // Optional
|
|
}
|
|
```
|
|
|
|
#### Analyze Content
|
|
|
|
- `POST /api/v1/optimizer/analyze/` - Analyze content without optimization
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"id": 123
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"seo_score": 75,
|
|
"readability_score": 70,
|
|
"engagement_score": 68,
|
|
"recommendations": [
|
|
"Add more internal links",
|
|
"Improve heading structure"
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Publisher Module Endpoints
|
|
|
|
**Base Path**: `/api/v1/publisher/`
|
|
**Permission**: IsAuthenticatedAndActive + HasTenantAccess
|
|
|
|
#### Publishing Records
|
|
|
|
**Base Path**: `/api/v1/publisher/publishing-records/`
|
|
**Inherits**: SiteSectorModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/publisher/publishing-records/` - List publishing records (paginated)
|
|
- `POST /api/v1/publisher/publishing-records/` - Create publishing record
|
|
- `GET /api/v1/publisher/publishing-records/{id}/` - Get publishing record
|
|
- `PUT /api/v1/publisher/publishing-records/{id}/` - Update publishing record
|
|
- `DELETE /api/v1/publisher/publishing-records/{id}/` - Delete publishing record
|
|
|
|
**Filtering:**
|
|
- `status` - Filter by publishing status
|
|
- `destination_type` - Filter by destination (wordpress, sites_renderer, etc.)
|
|
- `site_id` - Filter by site
|
|
- `sector_id` - Filter by sector
|
|
|
|
#### Deployment Records
|
|
|
|
**Base Path**: `/api/v1/publisher/deployments/`
|
|
**Inherits**: SiteSectorModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/publisher/deployments/` - List deployment records (paginated)
|
|
- `POST /api/v1/publisher/deployments/` - Create deployment record
|
|
- `GET /api/v1/publisher/deployments/{id}/` - Get deployment record
|
|
- `PUT /api/v1/publisher/deployments/{id}/` - Update deployment record
|
|
- `DELETE /api/v1/publisher/deployments/{id}/` - Delete deployment record
|
|
|
|
#### Publishing Actions
|
|
|
|
- `POST /api/v1/publisher/publish/` - Publish content to destination
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"content_id": 123,
|
|
"destination_type": "wordpress",
|
|
"destination_id": 1
|
|
}
|
|
```
|
|
|
|
- `POST /api/v1/publisher/deploy/` - Deploy site blueprint
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"blueprint_id": 456,
|
|
"environment": "production"
|
|
}
|
|
```
|
|
|
|
- `POST /api/v1/publisher/check_readiness/` - Check deployment readiness
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"blueprint_id": 456
|
|
}
|
|
```
|
|
|
|
#### Public Endpoint (No Authentication)
|
|
|
|
- `GET /api/v1/publisher/sites/{site_id}/definition/` - Get site definition for Sites Renderer
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"site_id": 1,
|
|
"slug": "example-site",
|
|
"blueprints": [...],
|
|
"pages": [...]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Site Builder Module Endpoints
|
|
|
|
**Base Path**: `/api/v1/site-builder/`
|
|
**Permission**: IsAuthenticatedAndActive + HasTenantAccess
|
|
|
|
#### Site Blueprints
|
|
|
|
**Base Path**: `/api/v1/site-builder/blueprints/`
|
|
**Inherits**: SiteSectorModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/site-builder/blueprints/` - List site blueprints (paginated)
|
|
- `POST /api/v1/site-builder/blueprints/` - Create site blueprint
|
|
- `GET /api/v1/site-builder/blueprints/{id}/` - Get blueprint details
|
|
- `PUT /api/v1/site-builder/blueprints/{id}/` - Update blueprint
|
|
- `DELETE /api/v1/site-builder/blueprints/{id}/` - Delete blueprint
|
|
|
|
**Custom Actions:**
|
|
- `POST /api/v1/site-builder/blueprints/{id}/generate_structure/` - Generate site structure using AI
|
|
- `POST /api/v1/site-builder/blueprints/{id}/generate_all_pages/` - Generate all pages for blueprint
|
|
- `POST /api/v1/site-builder/blueprints/{id}/create_tasks/` - Create Writer tasks for pages
|
|
- `GET /api/v1/site-builder/blueprints/{id}/progress/` - Get cluster-level completion status
|
|
- `POST /api/v1/site-builder/blueprints/{id}/clusters/attach/` - Attach planner clusters
|
|
- `POST /api/v1/site-builder/blueprints/{id}/clusters/detach/` - Detach clusters
|
|
- `GET /api/v1/site-builder/blueprints/{id}/taxonomies/` - List taxonomies
|
|
- `POST /api/v1/site-builder/blueprints/{id}/taxonomies/` - Create taxonomy
|
|
- `POST /api/v1/site-builder/blueprints/{id}/taxonomies/import/` - Import taxonomies
|
|
- `POST /api/v1/site-builder/blueprints/bulk_delete/` - Bulk delete blueprints
|
|
|
|
**Filtering:**
|
|
- `status` - Filter by blueprint status
|
|
- `site_id` - Filter by site
|
|
- `sector_id` - Filter by sector
|
|
|
|
#### Page Blueprints
|
|
|
|
**Base Path**: `/api/v1/site-builder/pages/`
|
|
**Inherits**: SiteSectorModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/site-builder/pages/` - List page blueprints (paginated)
|
|
- `POST /api/v1/site-builder/pages/` - Create page blueprint
|
|
- `GET /api/v1/site-builder/pages/{id}/` - Get page details
|
|
- `PUT /api/v1/site-builder/pages/{id}/` - Update page
|
|
- `DELETE /api/v1/site-builder/pages/{id}/` - Delete page
|
|
|
|
**Custom Actions:**
|
|
- `POST /api/v1/site-builder/pages/{id}/generate_content/` - Generate content for page
|
|
- `POST /api/v1/site-builder/pages/{id}/regenerate/` - Regenerate page content
|
|
|
|
**Filtering:**
|
|
- `site_blueprint_id` - Filter by site blueprint
|
|
- `status` - Filter by page status
|
|
|
|
#### Site Assets
|
|
|
|
- `GET /api/v1/site-builder/assets/` - List files for site
|
|
|
|
**Query Parameters:**
|
|
- `site_id` - Filter by site
|
|
- `file_type` - Filter by file type
|
|
|
|
- `POST /api/v1/site-builder/assets/` - Upload file
|
|
|
|
**Request:** Multipart form data
|
|
```json
|
|
{
|
|
"file": "<file>",
|
|
"site_id": 1,
|
|
"file_type": "image"
|
|
}
|
|
```
|
|
|
|
- `DELETE /api/v1/site-builder/assets/` - Delete file
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"file_path": "path/to/file.jpg",
|
|
"site_id": 1
|
|
}
|
|
```
|
|
|
|
#### Site Builder Metadata
|
|
|
|
- `GET /api/v1/site-builder/metadata/` - Get metadata (business types, audience profiles, etc.)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"business_types": [...],
|
|
"audience_profiles": [...],
|
|
"brand_personalities": [...],
|
|
"hero_imagery_directions": [...]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Automation Module Endpoints
|
|
|
|
**Base Path**: `/api/v1/automation/`
|
|
**Permission**: IsAuthenticatedAndActive + HasTenantAccess
|
|
|
|
#### Automation Rules
|
|
|
|
**Base Path**: `/api/v1/automation/rules/`
|
|
**Inherits**: SiteSectorModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/automation/rules/` - List automation rules (paginated)
|
|
- `POST /api/v1/automation/rules/` - Create automation rule
|
|
- `GET /api/v1/automation/rules/{id}/` - Get rule details
|
|
- `PUT /api/v1/automation/rules/{id}/` - Update rule
|
|
- `DELETE /api/v1/automation/rules/{id}/` - Delete rule
|
|
|
|
**Custom Actions:**
|
|
- `POST /api/v1/automation/rules/{id}/execute/` - Manually execute automation rule
|
|
|
|
**Filtering:**
|
|
- `status` - Filter by rule status (active, inactive)
|
|
- `trigger_type` - Filter by trigger type
|
|
- `site_id` - Filter by site
|
|
- `sector_id` - Filter by sector
|
|
|
|
#### Scheduled Tasks
|
|
|
|
**Base Path**: `/api/v1/automation/scheduled-tasks/`
|
|
**Inherits**: AccountModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/automation/scheduled-tasks/` - List scheduled tasks (paginated)
|
|
- `POST /api/v1/automation/scheduled-tasks/` - Create scheduled task
|
|
- `GET /api/v1/automation/scheduled-tasks/{id}/` - Get task details
|
|
- `PUT /api/v1/automation/scheduled-tasks/{id}/` - Update task
|
|
- `DELETE /api/v1/automation/scheduled-tasks/{id}/` - Delete task
|
|
|
|
**Filtering:**
|
|
- `status` - Filter by task status
|
|
- `task_type` - Filter by task type
|
|
- `next_run_date` - Filter by next run date
|
|
|
|
### Integration Module Endpoints
|
|
|
|
**Base Path**: `/api/v1/integration/`
|
|
**Permission**: IsAuthenticatedAndActive + HasTenantAccess
|
|
|
|
#### Site Integrations
|
|
|
|
**Base Path**: `/api/v1/integration/integrations/`
|
|
**Inherits**: SiteSectorModelViewSet
|
|
|
|
**Standard CRUD:**
|
|
- `GET /api/v1/integration/integrations/` - List site integrations (paginated)
|
|
- `POST /api/v1/integration/integrations/` - Create integration
|
|
- `GET /api/v1/integration/integrations/{id}/` - Get integration details
|
|
- `PUT /api/v1/integration/integrations/{id}/` - Update integration
|
|
- `DELETE /api/v1/integration/integrations/{id}/` - Delete integration
|
|
|
|
**Custom Actions:**
|
|
- `POST /api/v1/integration/integrations/{id}/test_connection/` - Test connection to integrated platform
|
|
|
|
**Request:**
|
|
```json
|
|
{}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"connected": true,
|
|
"message": "Connection successful"
|
|
}
|
|
}
|
|
```
|
|
|
|
- `POST /api/v1/integration/integrations/{id}/sync/` - Sync content with integrated platform
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"content_ids": [123, 456],
|
|
"sync_type": "full" // or "incremental"
|
|
}
|
|
```
|
|
|
|
- `GET /api/v1/integration/integrations/{id}/sync_health/` - Get sync health status
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"last_sync": "2025-01-XXT...",
|
|
"sync_status": "healthy",
|
|
"pending_items": 0,
|
|
"failed_items": 0
|
|
}
|
|
}
|
|
```
|
|
|
|
**Filtering:**
|
|
- `platform_type` - Filter by platform (wordpress, shopify, etc.)
|
|
- `status` - Filter by integration status
|
|
- `site_id` - Filter by site
|
|
- `sector_id` - Filter by sector
|
|
|
|
### Billing Module Endpoints
|
|
|
|
**Base Path**: `/api/v1/billing/`
|
|
|
|
#### Credit Balance
|
|
|
|
**Base Path**: `/api/v1/billing/credits/balance/`
|
|
**Permission**: IsAuthenticatedAndActive + HasTenantAccess
|
|
|
|
- `GET /api/v1/billing/credits/balance/balance/` - Get credit balance
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"credits": 1000,
|
|
"plan_credits_per_month": 500,
|
|
"credits_used_this_month": 250,
|
|
"credits_remaining": 750
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Credit Usage
|
|
|
|
**Base Path**: `/api/v1/billing/credits/usage/`
|
|
**Permission**: IsAuthenticatedAndActive + HasTenantAccess
|
|
|
|
**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
|
|
- `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
|
|
- `GET /api/v1/billing/credits/usage/limits/` - Get usage limits
|
|
|
|
#### Credit Transactions
|
|
|
|
**Base Path**: `/api/v1/billing/credits/transactions/`
|
|
**Permission**: IsAdminOrOwner
|
|
|
|
**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
|
|
- `start_date` - Filter by start date
|
|
- `end_date` - Filter by end date
|
|
|
|
---
|
|
|
|
## Integration Examples
|
|
|
|
### Python
|
|
|
|
```python
|
|
import requests
|
|
|
|
BASE_URL = "https://api.igny8.com/api/v1"
|
|
|
|
# Login
|
|
response = requests.post(
|
|
f"{BASE_URL}/auth/login/",
|
|
json={"email": "user@example.com", "password": "password"}
|
|
)
|
|
data = response.json()
|
|
|
|
if data['success']:
|
|
token = data['data']['access']
|
|
|
|
# Use token for authenticated requests
|
|
headers = {
|
|
'Authorization': f'Bearer {token}',
|
|
'Content-Type': 'application/json'
|
|
}
|
|
|
|
# Get keywords
|
|
response = requests.get(
|
|
f"{BASE_URL}/planner/keywords/?page=1&page_size=25",
|
|
headers=headers
|
|
)
|
|
result = response.json()
|
|
|
|
if result['success']:
|
|
keywords = result['results']
|
|
print(f"Found {result['count']} keywords")
|
|
else:
|
|
print(f"Error: {result['error']}")
|
|
```
|
|
|
|
### JavaScript
|
|
|
|
```javascript
|
|
const BASE_URL = 'https://api.igny8.com/api/v1';
|
|
|
|
// Login
|
|
const loginResponse = await fetch(`${BASE_URL}/auth/login/`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
email: 'user@example.com',
|
|
password: 'password'
|
|
})
|
|
});
|
|
|
|
const loginData = await loginResponse.json();
|
|
|
|
if (loginData.success) {
|
|
const token = loginData.data.access;
|
|
|
|
// Use token for authenticated requests
|
|
const headers = {
|
|
'Authorization': `Bearer ${token}`,
|
|
'Content-Type': 'application/json'
|
|
};
|
|
|
|
// Get keywords
|
|
const keywordsResponse = await fetch(
|
|
`${BASE_URL}/planner/keywords/?page=1&page_size=25`,
|
|
{ headers }
|
|
);
|
|
|
|
const keywordsData = await keywordsResponse.json();
|
|
|
|
if (keywordsData.success) {
|
|
const keywords = keywordsData.results;
|
|
console.log(`Found ${keywordsData.count} keywords`);
|
|
} else {
|
|
console.error('Error:', keywordsData.error);
|
|
}
|
|
}
|
|
```
|
|
|
|
### cURL
|
|
|
|
```bash
|
|
# Login
|
|
curl -X POST https://api.igny8.com/api/v1/auth/login/ \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"email":"user@example.com","password":"password"}'
|
|
|
|
# Get keywords (with token)
|
|
curl -X GET https://api.igny8.com/api/v1/planner/keywords/ \
|
|
-H "Authorization: Bearer YOUR_TOKEN" \
|
|
-H "Content-Type: application/json"
|
|
```
|
|
|
|
### Frontend Integration (TypeScript)
|
|
|
|
```typescript
|
|
// Using fetchAPI wrapper (automatically extracts data from unified format)
|
|
import { fetchAPI } from './services/api';
|
|
|
|
// List keywords
|
|
const response = await fetchAPI('/v1/planner/keywords/?page=1&page_size=25');
|
|
// response is already extracted: { count, next, previous, results }
|
|
|
|
// Create keyword
|
|
const newKeyword = await fetchAPI('/v1/planner/keywords/', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
keyword: 'example keyword',
|
|
site_id: 1,
|
|
sector_id: 2,
|
|
status: 'active'
|
|
})
|
|
});
|
|
|
|
// Error handling
|
|
try {
|
|
const data = await fetchAPI('/v1/planner/keywords/');
|
|
} catch (error) {
|
|
// Error is already parsed from unified format
|
|
console.error(error.message);
|
|
if (error.errors) {
|
|
// Handle field-specific errors
|
|
Object.keys(error.errors).forEach(field => {
|
|
console.error(`${field}: ${error.errors[field].join(', ')}`);
|
|
});
|
|
}
|
|
}
|
|
```
|
|
|
|
### WordPress Plugin Integration (PHP)
|
|
|
|
```php
|
|
class Igny8API {
|
|
private $base_url = 'https://api.igny8.com/api/v1';
|
|
private $token;
|
|
|
|
public function login($email, $password) {
|
|
$response = wp_remote_post($this->base_url . '/auth/login/', [
|
|
'headers' => ['Content-Type' => 'application/json'],
|
|
'body' => json_encode(['email' => $email, 'password' => $password])
|
|
]);
|
|
|
|
$data = json_decode(wp_remote_retrieve_body($response), true);
|
|
|
|
if ($data['success']) {
|
|
$this->token = $data['data']['access'];
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public function getKeywords($page = 1, $page_size = 25) {
|
|
$response = wp_remote_get(
|
|
$this->base_url . '/planner/keywords/?page=' . $page . '&page_size=' . $page_size,
|
|
[
|
|
'headers' => [
|
|
'Authorization' => 'Bearer ' . $this->token,
|
|
'Content-Type' => 'application/json'
|
|
]
|
|
]
|
|
);
|
|
|
|
$data = json_decode(wp_remote_retrieve_body($response), true);
|
|
|
|
if ($data['success']) {
|
|
return $data['results'];
|
|
}
|
|
|
|
return [];
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Testing & Debugging
|
|
|
|
### Request ID Tracking
|
|
|
|
Every API request includes a unique `request_id` in the response. Use this ID for:
|
|
- Debugging issues
|
|
- Log correlation
|
|
- Support requests
|
|
|
|
The `request_id` is included in:
|
|
- All success responses
|
|
- All error responses
|
|
- Response headers (`X-Request-ID`)
|
|
|
|
### Progress Tracking (AI Functions)
|
|
|
|
All AI functions return a Celery task ID for progress tracking:
|
|
|
|
**Request:**
|
|
```json
|
|
POST /api/v1/planner/keywords/auto_cluster/
|
|
{
|
|
"ids": [1, 2, 3, 4, 5],
|
|
"sector_id": 1
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"task_id": "abc123-def456-ghi789"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Poll Progress:**
|
|
```json
|
|
GET /api/v1/system/settings/task_progress/abc123-def456-ghi789/
|
|
```
|
|
|
|
**Progress Response:**
|
|
```json
|
|
{
|
|
"state": "PROGRESS",
|
|
"meta": {
|
|
"phase": "AI_CALL",
|
|
"percentage": 50,
|
|
"message": "Processing keywords...",
|
|
"request_steps": [...],
|
|
"response_steps": [...],
|
|
"cost": 0.05,
|
|
"tokens": 1500
|
|
}
|
|
}
|
|
```
|
|
|
|
### Error Handling Best Practices
|
|
|
|
**401 Unauthorized**: Trigger logout → redirect to login
|
|
**403 Forbidden**: Show permission alert
|
|
**429 Too Many Requests**: Show rate limit warning with retry time
|
|
**4xx/5xx**: Display error message from `error` field
|
|
|
|
### Rate Limit Monitoring
|
|
|
|
```typescript
|
|
const throttleLimit = response.headers.get('X-Throttle-Limit');
|
|
const throttleRemaining = response.headers.get('X-Throttle-Remaining');
|
|
|
|
if (parseInt(throttleRemaining) < 5) {
|
|
showNotification('Approaching rate limit', 'warning');
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Change Management
|
|
|
|
### Versioning Strategy
|
|
|
|
- **v1** remains stable long-term
|
|
- Breaking changes require **v2**
|
|
- Deprecations allowed only with explicit timeline
|
|
- Non-breaking changes can be added to v1
|
|
|
|
### Breaking Changes
|
|
|
|
**Definition:** Changes that require client code updates
|
|
|
|
**Examples:**
|
|
- Removing an endpoint
|
|
- Changing response structure
|
|
- Changing authentication method
|
|
- Removing a field from response
|
|
|
|
**Process:**
|
|
1. Document breaking change
|
|
2. Provide migration guide
|
|
3. Deprecate in v1 with timeline
|
|
4. Implement in v2
|
|
5. Maintain v1 for deprecation period
|
|
|
|
### Non-Breaking Changes
|
|
|
|
**Definition:** Changes that don't require client code updates
|
|
|
|
**Examples:**
|
|
- Adding new endpoints
|
|
- Adding optional fields to response
|
|
- Adding new query parameters
|
|
- Performance improvements
|
|
|
|
### Changelog
|
|
|
|
All API changes are documented in `CHANGELOG.md` with:
|
|
- Version number
|
|
- Date
|
|
- Type (Added, Changed, Fixed, Deprecated, Removed, Security)
|
|
- Description
|
|
- Affected areas
|
|
- Migration notes (if applicable)
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
### Implementation Status
|
|
|
|
✅ **100% Complete** - All endpoints implemented with:
|
|
- Unified response format (`{success, data, message, errors, request_id}`)
|
|
- Proper authentication and authorization (JWT Bearer tokens)
|
|
- Rate limiting configured (scoped by operation type)
|
|
- Error handling standardized (centralized exception handler)
|
|
- Request ID tracking (every request has unique ID)
|
|
- Complete Swagger/OpenAPI documentation
|
|
- Tenant/site/sector scoping (automatic filtering)
|
|
- Pagination standardized (default: 10, max: 100)
|
|
|
|
### Key Features
|
|
|
|
- **100+ endpoints** across 5 modules
|
|
- **Unified response format** for all endpoints
|
|
- **Scoped rate limiting** (10-100 requests/minute depending on operation)
|
|
- **Layered authorization** (Authentication → Tenant → Role → Site/Sector)
|
|
- **Complete OpenAPI documentation** (Swagger UI, ReDoc)
|
|
- **Request ID tracking** for debugging
|
|
- **Progress tracking** for AI functions
|
|
- **Comprehensive error handling** with clear messages
|
|
|
|
### Access Points
|
|
|
|
- **Interactive Documentation**: `https://api.igny8.com/api/docs/`
|
|
- **ReDoc**: `https://api.igny8.com/api/redoc/`
|
|
- **OpenAPI Schema**: `https://api.igny8.com/api/schema/`
|
|
|
|
---
|
|
|
|
**Last Updated**: 2025-01-XX (Added 6 missing modules: Linker, Optimizer, Publisher, Site Builder, Automation, Integration)
|
|
**API Version**: 1.0.0
|
|
**Status**: ✅ **100% IMPLEMENTED** - All 10 modules documented with complete endpoint reference
|
|
|