Files
igny8/unified-api/API-STANDARD-v1.0.md
IGNY8 VPS (Salman) 7cd0e1a807 Add health check endpoint and refactor integration response handling
- Introduced a new public health check endpoint at `api/ping/` to verify API responsiveness.
- Refactored integration response handling to utilize a unified success and error response format across various methods in `IntegrationSettingsViewSet`, improving consistency and clarity in API responses.
- Updated URL patterns to include the new ping endpoint and adjusted imports accordingly.
2025-11-16 07:01:19 +00:00

32 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

  1. Overview
  2. API Versioning & Base URLs
  3. Authentication & Authorization
  4. Response Format Standard
  5. Error Handling Standard
  6. Rate Limits & Governance
  7. Pagination & Query Rules
  8. Standard Request & Response Shapes
  9. Roles & Permissions Matrix
  10. Tenant / Site / Sector Scoping
  11. Module-wise Endpoint Rules
  12. Logging, Request ID, and Debugging
  13. Frontend and Plugin Integration Requirements
  14. Migration Plan for Existing Code
  15. Testing Strategy
  16. 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

  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

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&sector_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_id and account_id
  • Type: access (15-minute expiry)
  • Automatically sets request.account via middleware
  • Resolves account → tenant context automatically

Token Payload:

{
  "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

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:

  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

{
  "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_id for 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:

  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

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 logs
  • logs/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 error field

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)

  1. Create Response Utilities

    • File: backend/igny8_core/api/response.py
    • Functions: success_response(), error_response(), paginated_response()
    • Unit tests
  2. Create Permission Classes

    • File: backend/igny8_core/api/permissions.py
    • Classes: IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner, etc.
    • Unit tests
  3. Create Base ViewSet

    • File: backend/igny8_core/api/viewsets.py
    • Class: BaseTenantViewSet
    • Automatic permission injection
  4. Create Exception Handler

    • File: backend/igny8_core/api/exception_handlers.py
    • Function: custom_exception_handler()
    • Register in settings
  5. Configure Rate Limiting

    • File: backend/igny8_core/api/throttles.py
    • Class: DebugScopedRateThrottle
    • Configure in settings

Phase 2: Module Refactoring (Week 2-3)

Refactoring Order (Least to Most Dependent):

  1. System Module (12 hours)

    • Refactor all ViewSets to use BaseTenantViewSet
    • Add throttle scopes
    • Replace Response() with helper functions
  2. Billing Module (8 hours)

    • Same refactoring steps
  3. Planner Module (16 hours)

    • Same refactoring steps
    • Special attention to AI functions
  4. Writer Module (16 hours)

    • Same refactoring steps
    • Special attention to AI functions and image generation
  5. Auth Module (12 hours)

    • Same refactoring steps
    • Keep public endpoints (register, login) as AllowAny

Phase 3: Testing & Validation (Week 4)

  1. Unit Tests

    • Test all response helpers
    • Test permission classes
    • Test exception handler
    • Test rate limiting
  2. Integration Tests

    • Test all endpoints return unified format
    • Test error handling
    • Test rate limiting
    • Test permissions
  3. Frontend Integration Testing

    • Test all workflows
    • Verify error handling
    • Verify rate limit warnings
    • Verify pagination

Phase 4: Documentation & Release (Week 5)

  1. Update Documentation

    • API usage guide
    • Backend implementation docs
    • Swagger/OpenAPI (optional)
  2. Changelog Entry

    • Document all changes
    • Breaking changes
    • Migration guide
  3. 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() with success_response() or error_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:

  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

Process:

  1. Implement in v1
  2. Document in changelog
  3. 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

  1. Internal Team

    • Document changes in changelog
    • Update internal documentation
    • Notify team via Slack/email
  2. External API Consumers

    • Update API documentation
    • Send email notification for breaking changes
    • Provide migration guide
  3. WordPress Plugin

    • Update plugin code if needed
    • Test compatibility
    • Release plugin update

Rollback Plan

If issues arise:

  1. Immediate Rollback

    • Revert code changes
    • Restore previous version
    • Monitor for issues
  2. Partial Rollback

    • Revert specific module changes
    • Keep other improvements
    • Fix issues incrementally
  3. 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/min
  • image_gen: 15/min
  • content_write: 30/min
  • auth: 20/min
  • planner: 60/min
  • writer: 60/min
  • system: 100/min
  • billing: 30/min
  • API-ENDPOINTS-ANALYSIS.md - Complete endpoint analysis
  • API-IMPLEMENTATION-PLAN-SECTION*.md - Detailed implementation guides (reference)

Document Status: Active Standard
Last Updated: 2025-01-XX
Next Review: Quarterly or as needed