1516 lines
44 KiB
Markdown
1516 lines
44 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
|
|
**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
|
|
├── account/ # Account settings, team, and usage analytics
|
|
├── integration/ # Site integrations and sync
|
|
├── system/ # Settings, prompts, integrations
|
|
├── admin/billing/ # Admin-only billing management
|
|
├── billing/ # Credits, transactions, usage
|
|
├── planner/ # Keywords, clusters, content ideas
|
|
├── writer/ # Tasks, content, images
|
|
├── automation/ # Automation configuration and runs
|
|
├── linker/ # Internal linking operations
|
|
├── optimizer/ # Content optimization operations
|
|
└── publisher/ # Publishing records and deployments
|
|
```
|
|
|
|
### Module → Tag Map (Swagger/ReDoc)
|
|
- Authentication → `Authentication`
|
|
- Account → `Account`
|
|
- Integration → `Integration`
|
|
- System → `System`
|
|
- Admin Billing → `Admin Billing`
|
|
- Billing → `Billing`
|
|
- Planner → `Planner`
|
|
- Writer → `Writer`
|
|
- Automation → `Automation`
|
|
- Linker → `Linker`
|
|
- Optimizer → `Optimizer`
|
|
- Publisher → `Publisher`
|
|
|
|
Tag display order (docs): Authentication, Account, Integration, System, Admin Billing, Billing, Planner, Writer, Automation, Linker, Optimizer, Publisher
|
|
|
|
### 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
|
|
|
|
**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..."
|
|
},
|
|
"message": "Login successful"
|
|
}
|
|
```
|
|
|
|
#### 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
|
|
|
|
### Admin Billing & Credits (Admin-only, Unified)
|
|
|
|
**Base Path**: `/api/v1/admin/billing/` (all admin billing/credits live here)
|
|
|
|
- `GET /api/v1/admin/billing/stats/` - System billing stats (admin-only)
|
|
- `GET /api/v1/admin/billing/invoices/` - Admin invoice listing (all accounts)
|
|
- `GET /api/v1/admin/billing/payments/` - Admin payment listing (all accounts)
|
|
- `GET /api/v1/admin/billing/pending_payments/` - Pending manual payments (admin review queue)
|
|
- `POST /api/v1/admin/billing/{id}/approve_payment/` - Approve manual payment (admin-only)
|
|
- `POST /api/v1/admin/billing/{id}/reject_payment/` - Reject manual payment (admin-only)
|
|
- `GET /api/v1/admin/billing/payment-method-configs/` - List payment method configs (country-level); query: `country_code`, `payment_method`
|
|
- `POST /api/v1/admin/billing/payment-method-configs/` - Create payment method config
|
|
- `GET /api/v1/admin/billing/payment-method-configs/{id}/` - Retrieve payment method config
|
|
- `PATCH/PUT /api/v1/admin/billing/payment-method-configs/{id}/` - Update payment method config
|
|
- `DELETE /api/v1/admin/billing/payment-method-configs/{id}/` - Delete payment method config
|
|
- `GET /api/v1/admin/billing/account-payment-methods/` - List account payment methods (query `account_id` to scope)
|
|
- `POST /api/v1/admin/billing/account-payment-methods/` - Create account payment method
|
|
- `GET /api/v1/admin/billing/account-payment-methods/{id}/` - Retrieve account payment method
|
|
- `PATCH/PUT /api/v1/admin/billing/account-payment-methods/{id}/` - Update account payment method
|
|
- `DELETE /api/v1/admin/billing/account-payment-methods/{id}/` - Delete account payment method
|
|
- `POST /api/v1/admin/billing/account-payment-methods/{id}/set_default/` - Set default account payment method
|
|
- `GET /api/v1/admin/credit-costs/` - List credit cost configurations (admin-only)
|
|
- `POST /api/v1/admin/credit-costs/` - Update credit cost configurations (admin-only)
|
|
- `GET /api/v1/admin/users/` - List users/accounts with credit info (admin-only)
|
|
- `POST /api/v1/admin/users/{user_id}/adjust-credits/` - Adjust user credits (admin-only)
|
|
|
|
> Non-standard/legacy endpoints to deprecate and remove (do not use):
|
|
> - `/api/v1/billing/admin/stats/`
|
|
> - `/api/v1/billing/admin/invoices/`
|
|
> - `/api/v1/billing/admin/payments/`
|
|
> - `/api/v1/billing/admin/pending_payments/`
|
|
> - `/api/v1/billing/admin/{id}/approve_payment/`
|
|
> - `/api/v1/billing/admin/{id}/reject_payment/`
|
|
|
|
|
|
### 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/` - 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
|
|
|
|
#### Credit Packages
|
|
|
|
**Base Path**: `/api/v1/billing/credit-packages/`
|
|
**Permission**: IsAuthenticated
|
|
|
|
- `GET /api/v1/billing/credit-packages/` - List available credit packages
|
|
- `POST /api/v1/billing/credit-packages/{id}/purchase/` - Purchase a credit package
|
|
|
|
#### Invoices
|
|
|
|
**Base Path**: `/api/v1/billing/invoices/`
|
|
**Permission**: IsAuthenticated
|
|
|
|
- `GET /api/v1/billing/invoices/` - List invoices
|
|
- `GET /api/v1/billing/invoices/{id}/` - Get invoice detail
|
|
- `GET /api/v1/billing/invoices/{id}/download_pdf/` - Download invoice PDF
|
|
|
|
#### Payment Methods
|
|
|
|
**Base Path**: `/api/v1/billing/payment-methods/`
|
|
**Permission**: IsAuthenticated
|
|
|
|
- `GET /api/v1/billing/payment-methods/` - List payment methods
|
|
- `POST /api/v1/billing/payment-methods/` - Create payment method
|
|
- `GET /api/v1/billing/payment-methods/{id}/` - Get payment method
|
|
- `PUT /api/v1/billing/payment-methods/{id}/` - Update payment method
|
|
- `PATCH /api/v1/billing/payment-methods/{id}/` - Partial update payment method
|
|
- `DELETE /api/v1/billing/payment-methods/{id}/` - Delete payment method
|
|
- `POST /api/v1/billing/payment-methods/{id}/set_default/` - Set default payment method
|
|
- `GET /api/v1/billing/payment-methods/available/` - List available payment methods (config-driven)
|
|
|
|
#### Payments
|
|
|
|
**Base Path**: `/api/v1/billing/payments/`
|
|
**Permission**: IsAuthenticated
|
|
|
|
- `GET /api/v1/billing/payments/` - List payments
|
|
- `POST /api/v1/billing/payments/manual/` - Submit manual payment for approval
|
|
|
|
#### Transactions (alias-free)
|
|
|
|
**Base Path**: `/api/v1/billing/transactions/`
|
|
**Permission**: IsAuthenticated
|
|
|
|
- `GET /api/v1/billing/transactions/` - List transactions (with current balance included)
|
|
|
|
---
|
|
|
|
## 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)
|
|
|
|
### Endpoint Change & Documentation Checklist (Unified API)
|
|
|
|
1) Design
|
|
- Map to an existing module/tag; if new, add to Module Namespaces and Tag Map.
|
|
- Choose path under the correct base (`/api/v1/{module}/...`); avoid new sub-namespaces unless justified.
|
|
|
|
2) Implement
|
|
- Use unified response helpers and proper permissions/rate limits.
|
|
- Add `extend_schema` tags matching the module tag.
|
|
|
|
3) Schema & Docs
|
|
- Ensure swagger tag exists in `SPECTACULAR_SETTINGS` with the agreed order.
|
|
- Regenerate/reload the API (server restart) so `/api/schema/` reflects changes.
|
|
- Verify in Swagger UI (`/api/docs/`) and ReDoc (`/api/redoc/`) that the operation is under the right tag.
|
|
|
|
4) Reference Updates
|
|
- Update this reference file with the new endpoint(s) under the correct module section.
|
|
- Update `CHANGELOG.md` (type, summary, impacted clients).
|
|
|
|
5) Deprecation (if applicable)
|
|
- Mark legacy routes, add timeline, and keep compatibility shims only temporarily.
|
|
|
|
---
|
|
|
|
## 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
|
|
**API Version**: 1.0.0
|
|
**Status**: ✅ **100% IMPLEMENTED**
|
|
|