- Add REFACTORING-PLAN.md: Plan to remove MODEL_CONFIG and Django settings fallbacks - Add ORPHAN-CODE-AUDIT.md: Audit of unused code and exports - Update CHANGELOG.md: Document API Standard v1.0 completion - Update documentation files
33 KiB
IGNY8 API STANDARD v1.0
Version: 1.0
Date: 2025-01-XX
Status: Active Standard
Purpose: Single source of truth for IGNY8 API contract, implementation, and integration
Applies To:
- Django backend
- React frontend
- WordPress plugin
- 3rd-party API consumers
- Internal automations / CRON / AI functions
Table of Contents
- Overview
- API Versioning & Base URLs
- Authentication & Authorization
- Response Format Standard
- Error Handling Standard
- Rate Limits & Governance
- Pagination & Query Rules
- Standard Request & Response Shapes
- Roles & Permissions Matrix
- Tenant / Site / Sector Scoping
- Module-wise Endpoint Rules
- Logging, Request ID, and Debugging
- Frontend and Plugin Integration Requirements
- Migration Plan for Existing Code
- Testing Strategy
- Change Management
Overview
The IGNY8 API Standard v1.0 establishes a unified, consistent interface for all API endpoints across the platform. This standard ensures:
- Predictability: All endpoints follow the same patterns
- Security: Consistent authentication and authorization
- Maintainability: Standardized error handling and logging
- Scalability: Rate limiting and governance controls
- Developer Experience: Clear documentation and integration patterns
Key Principles
- Unified Response Format: All endpoints return consistent JSON structure
- Layered Authorization: Authentication → Tenant Access → Role → Site/Sector
- Centralized Error Handling: All errors wrapped in unified format
- Scoped Rate Limiting: Different limits for different operation types
- Tenant Isolation: All resources scoped by account/site/sector
- Request Tracking: Every request has a unique ID for debugging
API Versioning & Base URLs
Base URL Structure
Production: https://api.igny8.com/api/v1/
Development: http://localhost:8000/api/v1/
Module Namespaces
All endpoints are organized under these namespaces:
/api/v1/
├── auth/ # Authentication and user management
├── planner/ # Keywords, clusters, content ideas
├── writer/ # Tasks, content, images
├── system/ # Settings, prompts, integrations
└── billing/ # Credits, transactions, usage
Versioning Rules
- v1 remains stable long-term
- Breaking changes require v2
- Deprecations allowed only with explicit timeline
- All endpoints must follow predictable REST patterns
Endpoint Naming Conventions
- Use plural nouns:
/api/v1/planner/keywords/ - Use snake_case for query parameters:
?site_id=1§or_id=2 - Use kebab-case for custom actions:
/api/v1/planner/keywords/auto-cluster/
Authentication & Authorization
Authentication Methods
Primary: JWT Bearer Token
Authorization: Bearer <access_token>
Token Characteristics:
- Contains
user_idandaccount_id - Type:
access(15-minute expiry) - Automatically sets
request.accountvia middleware - Resolves account → tenant context automatically
Token Payload:
{
"user_id": 1,
"account_id": 1,
"type": "access",
"exp": 1234567890
}
Fallback Methods
-
Session Authentication (admin panel)
- Class:
CSRFExemptSessionAuthentication - Use case: Django admin panel (
/admin/)
- Class:
-
Basic Authentication (debug/testing)
- Class:
rest_framework.authentication.BasicAuthentication - Use case: API testing tools (Postman, curl)
- Class:
Authentication Order
- JWT Token Authentication (tried first)
- Session Authentication (fallback)
- Basic Authentication (last fallback)
- If all fail: 401 Unauthorized
Public Endpoints (No Authentication Required)
POST /api/v1/auth/register/POST /api/v1/auth/login/GET /api/v1/auth/plans/GET /api/v1/auth/industries/GET /api/v1/system/status/GET /api/v1/system/ping/(health check)
All other endpoints require JWT authentication.
Authorization Layers
Every endpoint enforces layered authorization:
- User Authentication: User must be authenticated
- Tenant Access: User must belong to the tenant/account
- Role Authorization: User must have appropriate role
- 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
{
"success": true,
"data": {
// Response data (object or array)
},
"message": "Optional human-readable success message"
}
Example:
{
"success": true,
"data": {
"id": 1,
"name": "Example Keyword",
"status": "active"
},
"message": "Keyword created successfully"
}
Error Response
{
"success": false,
"error": "Readable top-level error message",
"errors": {
"field_name": ["Field-specific error messages"]
},
"request_id": "uuid-for-error-tracking"
}
Example:
{
"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"
}
Paginated Response
{
"success": true,
"count": 120,
"next": "http://api.igny8.com/api/v1/endpoint/?page=2",
"previous": null,
"results": [
// Array of results
],
"message": "Optional message"
}
Response Helper Functions
File: backend/igny8_core/api/response.py
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 Standard
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 (400, 401, 403, 404, 409, 422, 500)
- Includes sanitized validation errors under
errors - Always attaches
request_idfor error tracking - Logs full exception details
- In DEBUG mode: includes traceback + request context
Status Code Mapping
| Status Code | Meaning | Response Format |
|---|---|---|
| 200 | OK | { success: true, data: {...} } |
| 201 | Created | { success: true, data: {...} } |
| 400 | Bad Request | { success: false, error: "...", errors: {...} } |
| 401 | Unauthorized | { success: false, error: "Authentication required" } |
| 403 | Forbidden | { success: false, error: "Permission denied" } |
| 404 | Not Found | { success: false, error: "Resource not found" } |
| 409 | Conflict | { success: false, error: "Conflict" } |
| 422 | Unprocessable Entity | { success: false, error: "...", errors: {...} } |
| 429 | Too Many Requests | { success: false, error: "Rate limit exceeded" } |
| 500 | Internal Server Error | { success: false, error: "Internal server error" } |
Error Response Structure
Production Mode:
{
"success": false,
"error": "Internal server error",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
Development Mode (DEBUG=True):
{
"success": false,
"error": "Internal server error",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"debug": {
"exception_type": "ValueError",
"exception_message": "Invalid value",
"view": "KeywordViewSet",
"path": "/api/v1/planner/keywords/",
"method": "POST",
"traceback": "Traceback (most recent call last):\n ..."
}
}
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
- traceback (for 5xx)
- Rotating log files
- Sentry integration hooks for production
Rate Limits & Governance
Rate Limiting Configuration
File: backend/igny8_core/settings.py
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'igny8_core.api.throttles.DebugScopedRateThrottle',
],
'DEFAULT_THROTTLE_RATES': {
# AI Functions - Expensive operations
'ai_function': '10/min', # AI content generation, clustering
'image_gen': '15/min', # Image generation
# Content Operations
'content_write': '30/min', # Content creation, updates
'content_read': '100/min', # Content listing, retrieval
# Authentication
'auth': '20/min', # Login, register, password reset
'auth_strict': '5/min', # Sensitive auth operations
# Planner Operations
'planner': '60/min', # Keyword, cluster, idea operations
'planner_ai': '10/min', # AI-powered planner operations
# Writer Operations
'writer': '60/min', # Task, content management
'writer_ai': '10/min', # AI-powered writer operations
# System Operations
'system': '100/min', # Settings, prompts, profiles
'system_admin': '30/min', # Admin-only system operations
# Billing Operations
'billing': '30/min', # Credit queries, usage logs
'billing_admin': '10/min', # Credit management (admin)
# Default fallback
'default': '100/min', # Default for endpoints without scope
},
}
Throttle Headers
All responses include rate limit information:
X-Throttle-Limit: 10
X-Throttle-Remaining: 9
X-Throttle-Reset: 1640995200
When throttled (429):
HTTP/1.1 429 Too Many Requests
X-Throttle-Limit: 10
X-Throttle-Remaining: 0
Retry-After: 60
Soft Limits (Business Logic)
- 50 tasks per bulk action
- 20 keywords per cluster batch
- 1 cluster → ideas generation
- 1 content → image prompt extraction
- 1 image generation per job
Safety Checks
- Validate all IDs belong to tenant
- Validate dependent records exist
- Reject oversized payloads
- Reject invalid site/sector assignments
- Reject stale/wrong tenant tokens
Debug Mode Bypass
Set IGNY8_DEBUG_THROTTLE=True or DEBUG=True to bypass throttling in development.
Pagination & Query Rules
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
{
"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
],
"message": "Keywords retrieved successfully"
}
Standard Request & Response Shapes
Request Payload Rules
All endpoints must follow:
- snake_case field names
- Predictable field groups
- Standardized pagination params
- Standardized filters
- Standardized bulk update patterns
- Standardized action payloads
- Standardized error messages
Bulk Actions
Standard Format:
{
"ids": [1, 2, 3],
// Additional fields as needed
}
Example:
{
"ids": [1, 2, 3],
"status": "active"
}
Filtering Patterns
Standard Query Parameters:
?search=- Text search?status=- Status filter?site_id=- Site filter?sector_id=- Sector filter?cluster_id=- Cluster filter?content_type=- Content type filter
Request Examples
Create Resource:
POST /api/v1/planner/keywords/
{
"keyword": "example keyword",
"site_id": 1,
"sector_id": 2,
"status": "active"
}
Bulk Update:
POST /api/v1/planner/keywords/bulk_update_status/
{
"ids": [1, 2, 3],
"status": "active"
}
Custom Action:
POST /api/v1/planner/keywords/auto_cluster/
{
"ids": [1, 2, 3, 4, 5],
"sector_id": 2
}
Roles & Permissions Matrix
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 |
Base ViewSet Class
File: backend/igny8_core/api/viewsets.py
from igny8_core.api.viewsets import BaseTenantViewSet
from igny8_core.api.permissions import IsAuthenticatedAndActive, HasTenantAccess
class MyViewSet(BaseTenantViewSet):
permission_classes = [
IsAuthenticatedAndActive,
HasTenantAccess,
]
throttle_scope = 'planner'
queryset = MyModel.objects.all()
serializer_class = MySerializer
Tenant / Site / Sector Scoping
Scoping Rules
Every resource created or fetched must be scoped by:
- Account/Tenant - User's account
- Site - Specific site within account
- Sector - Specific sector within site
Enforcement
Base Classes:
AccountModelViewSet- Handles account isolationSiteSectorModelViewSet- 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
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
Module-wise Endpoint Rules
Planner Module
Covers: Keywords → Clusters → Ideas
Rules:
- All endpoints require authentication
- Auto-cluster limited to 20 keywords/request
- Ideas generation limited to 1 cluster/request
- Standardized payloads for imports/exports
- Bulk actions must validate tenant ownership
- Throttle scope:
planner(standard),planner_ai(AI operations)
Key Endpoints:
GET/POST /api/v1/planner/keywords/POST /api/v1/planner/keywords/auto_cluster/POST /api/v1/planner/clusters/auto_generate_ideas/POST /api/v1/planner/ideas/bulk_queue_to_writer/
Writer Module
Covers: Tasks → Content → Image Prompts → Images
Rules:
- 1 AI content generation per task
- 1 image generation per request
- Bulk actions max 50
- Image prompt extraction uses unified response
- Must align with progress tracking
- Throttle scope:
writer(standard),writer_ai(AI operations),image_gen(image generation)
Key Endpoints:
GET/POST /api/v1/writer/tasks/POST /api/v1/writer/tasks/auto_generate_content/POST /api/v1/writer/content/generate_image_prompts/POST /api/v1/writer/images/generate_images/
System Module
Covers: Prompts, Strategies, Profiles, Integrations, Task Progress
Rules:
- Saving prompts requires editor/admin
- Integration settings require admin/owner
- All tests (OpenAI/Runware) return unified format
- Progress endpoint returns stable JSON for progress modal
- Throttle scope:
system(standard),system_admin(admin operations)
Key Endpoints:
GET/POST /api/v1/system/prompts/POST /api/v1/system/prompts/save/POST /api/v1/system/settings/integrations/{pk}/test/GET /api/v1/system/settings/task_progress/{task_id}/
Billing Module
Covers: Credit Balance, Usage Logs, Transactions
Rules:
- Balance/usage require authenticated tenant
- Transactions require admin/owner
- Unified reporting structure
- No raw model data returned
- Throttle scope:
billing(standard),billing_admin(admin operations)
Key Endpoints:
GET /api/v1/billing/credits/balance/balance/GET /api/v1/billing/credits/usage/GET /api/v1/billing/credits/usage/summary/GET /api/v1/billing/credits/transactions/
Logging, Request ID, and Debugging
Request ID Tracking
Middleware: RequestIDMiddleware
Every request gets a unique request ID:
- Generated UUID if not provided
- Included in response headers:
X-Request-ID - Included in all error responses
- Used for log correlation
Backend Logging
Structured Log Format:
{
"timestamp": "2025-01-15T12:30:00Z",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"endpoint": "/api/v1/planner/keywords/",
"method": "POST",
"user_id": 1,
"account_id": 1,
"status_code": 200,
"error_message": null,
"traceback": null
}
Log Levels:
- INFO: Normal operations
- WARNING: 4xx errors (client errors)
- ERROR: 5xx errors (server errors)
- DEBUG: Detailed debugging (only in DEBUG mode)
Log Files:
logs/django.log- General logslogs/errors.log- Error logs only
Frontend Debug Panel Integration
All responses must support:
- Request ID - For error tracking
- Readable error messages - User-friendly messages
- Consistent progress steps - For AI functions
- Error visibility in real time - For debugging
Progress Modal Standard (AI Functions)
All AI functions must output uniform progress metadata:
Example Steps (Image Prompt Extraction):
1. Smart Image Prompts
2. Checking content and image slots
3. Mapping Content for X Image Prompts
4. Writing Featured Image Prompts
5. Writing X In-article Image Prompts
6. Assigning Prompts to Slots
Success Message:
Featured Image and X In-article Image Prompts ready for image generation
Progress Response Format:
{
"state": "PROGRESS",
"meta": {
"phase": "AI_CALL",
"percentage": 50,
"current_step": "Writing Featured Image Prompts",
"total_steps": 6,
"steps": [
"Smart Image Prompts",
"Checking content and image slots",
"Mapping Content for X Image Prompts",
"Writing Featured Image Prompts",
"Writing X In-article Image Prompts",
"Assigning Prompts to Slots"
]
}
}
Frontend and Plugin Integration Requirements
Frontend Integration
Response Parsing:
const response = await fetchAPI('/v1/planner/keywords/');
const data = await response.json();
if (data.success) {
// Handle success
const keywords = data.data; // or data.results for paginated
} else {
// Handle error
console.error(data.error);
if (data.errors) {
// Handle field-specific errors
Object.keys(data.errors).forEach(field => {
console.error(`${field}: ${data.errors[field].join(', ')}`);
});
}
}
Error Handling:
- 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
errorfield
Pagination:
const response = await fetchAPI('/v1/planner/keywords/?page=1&page_size=25');
const data = await response.json();
if (data.success) {
const keywords = data.results; // Paginated results
const count = data.count;
const next = data.next;
const previous = data.previous;
}
Rate Limit Handling:
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');
}
WordPress Plugin Integration
Requirements:
- Uses the same JWT flow
- No custom plugin-specific endpoints
- Uses the app's
/api/v1/fully - WP only handles mapping + meta assignment
Authentication:
$token = get_option('igny8_api_token');
$response = wp_remote_get('https://api.igny8.com/api/v1/planner/keywords/', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/json',
],
]);
3rd-Party API Integration
Requirements:
- Full compatibility with unified format
- Full access where tenant/permissions allow
- No special handling needed
Example (Python):
import requests
def get_keywords(access_token):
url = 'https://api.igny8.com/api/v1/planner/keywords/'
headers = {
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json'
}
response = requests.get(url, headers=headers)
result = response.json()
if result['success']:
return result['data'] # or result['results'] for paginated
else:
raise Exception(result['error'])
Migration Plan for Existing Code
Phase 1: Foundation (Week 1)
-
Create Response Utilities
- File:
backend/igny8_core/api/response.py - Functions:
success_response(),error_response(),paginated_response() - Unit tests
- File:
-
Create Permission Classes
- File:
backend/igny8_core/api/permissions.py - Classes:
IsAuthenticatedAndActive,HasTenantAccess,IsAdminOrOwner, etc. - Unit tests
- File:
-
Create Base ViewSet
- File:
backend/igny8_core/api/viewsets.py - Class:
BaseTenantViewSet - Automatic permission injection
- File:
-
Create Exception Handler
- File:
backend/igny8_core/api/exception_handlers.py - Function:
custom_exception_handler() - Register in settings
- File:
-
Configure Rate Limiting
- File:
backend/igny8_core/api/throttles.py - Class:
DebugScopedRateThrottle - Configure in settings
- File:
Phase 2: Module Refactoring (Week 2-3)
Refactoring Order (Least to Most Dependent):
-
System Module (12 hours)
- Refactor all ViewSets to use
BaseTenantViewSet - Add throttle scopes
- Replace Response() with helper functions
- Refactor all ViewSets to use
-
Billing Module (8 hours)
- Same refactoring steps
-
Planner Module (16 hours)
- Same refactoring steps
- Special attention to AI functions
-
Writer Module (16 hours)
- Same refactoring steps
- Special attention to AI functions and image generation
-
Auth Module (12 hours)
- Same refactoring steps
- Keep public endpoints (register, login) as
AllowAny
Phase 3: Testing & Validation (Week 4)
-
Unit Tests
- Test all response helpers
- Test permission classes
- Test exception handler
- Test rate limiting
-
Integration Tests
- Test all endpoints return unified format
- Test error handling
- Test rate limiting
- Test permissions
-
Frontend Integration Testing
- Test all workflows
- Verify error handling
- Verify rate limit warnings
- Verify pagination
Phase 4: Documentation & Release (Week 5)
-
Update Documentation
- API usage guide
- Backend implementation docs
- Swagger/OpenAPI (optional)
-
Changelog Entry
- Document all changes
- Breaking changes
- Migration guide
-
Production Deployment
- Staging testing
- Production deployment
- Monitoring setup
Refactoring Checklist Template
For each ViewSet:
- Inherit from
BaseTenantViewSet - Set appropriate
permission_classes - Add
throttle_scope - Replace
Response()withsuccess_response()orerror_response() - Update custom actions with explicit permissions
- Validate payloads in custom actions
- Test endpoint manually
- Verify response format matches specification
- Update documentation
Testing Strategy
Unit Tests
File: backend/igny8_core/api/tests/test_response.py
def test_success_response():
response = success_response(data={"id": 1}, message="Success")
assert response.status_code == 200
data = response.data
assert data['success'] == True
assert data['data'] == {"id": 1}
assert data['message'] == "Success"
def test_error_response():
response = error_response(
error="Validation failed",
errors={"email": ["Invalid"]}
)
assert response.status_code == 400
data = response.data
assert data['success'] == False
assert data['error'] == "Validation failed"
assert data['errors'] == {"email": ["Invalid"]}
File: backend/igny8_core/api/tests/test_permissions.py
def test_has_tenant_access():
user = User.objects.create(account=account1)
request.user = user
request.account = account1
permission = HasTenantAccess()
assert permission.has_permission(request, view) == True
request.account = account2
assert permission.has_permission(request, view) == False
Integration Tests
File: backend/igny8_core/api/tests/test_standardized_endpoints.py
class StandardizedEndpointTestCase(TestCase):
def setUp(self):
self.client = APIClient()
self.user = User.objects.create_user(...)
self.client.force_authenticate(user=self.user)
def test_list_endpoint_returns_unified_format(self):
response = self.client.get('/api/v1/planner/keywords/')
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertIn('success', data)
self.assertTrue(data['success'])
self.assertIn('results', data)
def test_create_endpoint_returns_unified_format(self):
response = self.client.post('/api/v1/planner/keywords/', {
'keyword': 'test',
'site_id': 1,
'sector_id': 1
})
self.assertEqual(response.status_code, 201)
data = response.json()
self.assertIn('success', data)
self.assertTrue(data['success'])
self.assertIn('data', data)
def test_error_returns_unified_format(self):
response = self.client.post('/api/v1/planner/keywords/', {})
self.assertEqual(response.status_code, 400)
data = response.json()
self.assertIn('success', data)
self.assertFalse(data['success'])
self.assertIn('error', data)
self.assertIn('errors', data)
self.assertIn('request_id', data)
Manual Testing
Postman Collection:
- Test all CRUD operations
- Test custom actions
- Test error scenarios
- Test rate limiting
- Verify response format
Frontend Testing:
- Test all workflows
- Verify error messages display correctly
- Verify rate limit warnings
- Verify pagination works
- Check browser console for errors
Test Coverage Goals
- Unit Tests: >90% coverage for response utilities, permissions, exception handler
- Integration Tests: All major endpoints tested
- Manual Tests: All workflows tested
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:
- Document breaking change
- Provide migration guide
- Deprecate in v1 with timeline
- Implement in v2
- 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
Process:
- Implement in v1
- Document in changelog
- No migration required
Changelog Format
File: CHANGELOG.md
## [1.1.0] - 2025-01-XX
### Added
- New endpoint: `GET /api/v1/system/health/`
- Optional field `metadata` in keyword response
### Changed
- Improved error messages for validation failures
- Rate limits increased for AI functions (10/min → 20/min)
### Deprecated
- `GET /api/v1/planner/keywords/legacy/` (will be removed in v2.0.0)
### Removed
- (None)
### Security
- Fixed authentication bypass in custom actions
Communication Plan
-
Internal Team
- Document changes in changelog
- Update internal documentation
- Notify team via Slack/email
-
External API Consumers
- Update API documentation
- Send email notification for breaking changes
- Provide migration guide
-
WordPress Plugin
- Update plugin code if needed
- Test compatibility
- Release plugin update
Rollback Plan
If issues arise:
-
Immediate Rollback
- Revert code changes
- Restore previous version
- Monitor for issues
-
Partial Rollback
- Revert specific module changes
- Keep other improvements
- Fix issues incrementally
-
Feature Flag
- Disable new features via feature flags
- Keep code in place
- Re-enable after fixes
Success Criteria
Definition of Done
- Every endpoint returns unified format
- All errors fully unified
- No endpoint leaks raw DRF format
- No inconsistent auth behavior
- No inconsistent pagination
- No inconsistent validation errors
- Plugin works using same exact API
- Third-party clients can implement without special rules
- Frontend debug panel reads everything correctly
- CRON + automations structured identically
- All tests pass
- Documentation complete
- Changelog updated
Metrics
- Coverage: 100% of endpoints use unified format
- Test Coverage: >90% for core utilities
- Documentation: All endpoints documented
- Breaking Changes: Documented and migration guide provided
- Performance: No significant performance degradation
Appendix
Quick Reference
Response Helpers:
from igny8_core.api.response import success_response, error_response, paginated_response
Permissions:
from igny8_core.api.permissions import (
IsAuthenticatedAndActive,
HasTenantAccess,
IsAdminOrOwner,
IsEditorOrAbove,
IsViewerOrAbove,
)
Base ViewSet:
from igny8_core.api.viewsets import BaseTenantViewSet
Throttle Scopes:
ai_function: 10/minimage_gen: 15/mincontent_write: 30/minauth: 20/minplanner: 60/minwriter: 60/minsystem: 100/minbilling: 30/min
Related Documents
API-ENDPOINTS-ANALYSIS.md- Complete endpoint analysisAPI-IMPLEMENTATION-PLAN-SECTION*.md- Detailed implementation guides (reference)
Document Status: Active Standard - ✅ 100% IMPLEMENTED
Last Updated: 2025-01-XX
Implementation Status: All requirements implemented and verified
- ✅ All endpoints return unified response format
- ✅ All errors fully unified with request_id tracking
- ✅ All ViewSets use proper base classes, pagination, throttles, and permissions
- ✅ All custom @action methods use unified format
- ✅ All public endpoints properly configured
- ✅ Health check endpoint
/api/v1/system/ping/implemented - ✅ All endpoints documented in Swagger/ReDoc Next Review: Quarterly or as needed