Files
igny8/docs/API-COMPLETE-REFERENCE.md
IGNY8 VPS (Salman) fc6dd5623a Add refresh token functionality and improve login response handling
- Introduced RefreshTokenView to allow users to refresh their access tokens using a valid refresh token.
- Enhanced LoginView to ensure correct user/account loading and improved error handling during user serialization.
- Updated API response structure to include access and refresh token expiration times.
- Adjusted frontend API handling to support both new and legacy token response formats.
2025-11-16 21:06:22 +00:00

37 KiB

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
  2. Overview & Architecture
  3. Authentication & Authorization
  4. Response Format Standard
  5. Error Handling
  6. Rate Limiting
  7. Pagination
  8. Roles & Permissions
  9. Tenant / Site / Sector Scoping
  10. Complete Endpoint Reference
  11. Integration Examples
  12. Testing & Debugging
  13. 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

import requests

BASE_URL = "https://api.igny8.com/api/v1"

# 1. Login
response = requests.post(
    f"{BASE_URL}/auth/login/",
    json={"email": "user@example.com", "password": "password"}
)
data = response.json()

if data['success']:
    token = data['data']['access']
    
    # 2. Use token for authenticated requests
    headers = {
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json'
    }
    
    # 3. Get keywords
    response = requests.get(
        f"{BASE_URL}/planner/keywords/",
        headers=headers
    )
    result = response.json()
    
    if result['success']:
        keywords = result['results']  # Paginated results
        print(f"Found {result['count']} keywords")

Overview & Architecture

API Standard v1.0 - Key Principles

  1. Unified Response Format: All endpoints return consistent JSON structure
  2. Layered Authorization: Authentication → Tenant Access → Role → Site/Sector
  3. Centralized Error Handling: All errors wrapped in unified format
  4. Scoped Rate Limiting: Different limits for different operation types
  5. Tenant Isolation: All resources scoped by account/site/sector
  6. Request Tracking: Every request has a unique ID for debugging

Base URL Structure

Production: https://api.igny8.com/api/v1/
Development: http://localhost:8000/api/v1/

Module Namespaces

/api/v1/
├── auth/          # Authentication and user management
├── planner/       # Keywords, clusters, content ideas
├── writer/        # Tasks, content, images
├── system/        # Settings, prompts, integrations
└── billing/       # Credits, transactions, usage

Technology Stack

  • Framework: Django REST Framework (DRF)
  • Authentication: JWT Bearer tokens (primary), Session (fallback), Basic (fallback)
  • Pagination: CustomPageNumberPagination (default: 10, max: 100)
  • Rate Limiting: Scoped throttles per module/operation type
  • OpenAPI: drf-spectacular for schema generation

Implementation Status

100% Complete - All endpoints implemented with:

  • Unified response format
  • Proper authentication and authorization
  • Rate limiting configured
  • Error handling standardized
  • Request ID tracking
  • Complete Swagger/OpenAPI documentation

Authentication & Authorization

Authentication Methods

Primary: JWT Bearer Token

Authorization: Bearer <access_token>

Token Characteristics:

  • Contains user_id and account_id
  • Type: access (15-minute expiry)
  • Automatically sets request.account via middleware
  • Resolves account → tenant context automatically

Token Payload:

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

POST /api/v1/auth/login/
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "your_password"
}

Response:

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

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

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

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

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

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):

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

{
  "success": false,
  "error": "Authentication required",
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Permission Error (403):

{
  "success": false,
  "error": "Permission denied",
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Rate Limit (429):

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

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

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:

{
  "email": "user@example.com",
  "password": "password123",
  "password_confirm": "password123"
}

Response:

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

{
  "email": "user@example.com",
  "password": "password123"
}

Response:

{
  "success": true,
  "data": {
    "user": { ... },
    "access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
    "refresh": "eyJ0eXAiOiJKV1QiLCJhbGc...",
    "access_expires_at": "2025-01-XXT...",
    "refresh_expires_at": "2025-01-XXT..."
  },
  "message": "Login successful",
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

POST /api/v1/auth/refresh/

Purpose: Refresh access token
Authentication: None (requires refresh token)

Request:

{
  "refresh": "your_refresh_token"
}

POST /api/v1/auth/change-password/

Purpose: Change user password
Authentication: Required (IsAuthenticated)

Request:

{
  "old_password": "oldpass123",
  "new_password": "newpass123",
  "new_password_confirm": "newpass123"
}

GET /api/v1/auth/me/

Purpose: Get current user information
Authentication: Required (IsAuthenticated)

Response:

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

Billing Module Endpoints

Base Path: /api/v1/billing/

Credit Balance

Base Path: /api/v1/billing/credits/balance/
Permission: IsAuthenticatedAndActive + HasTenantAccess

  • GET /api/v1/billing/credits/balance/balance/ - Get credit balance

Response:

{
  "success": true,
  "data": {
    "credits": 1000,
    "plan_credits_per_month": 500,
    "credits_used_this_month": 250,
    "credits_remaining": 750
  }
}

Credit Usage

Base Path: /api/v1/billing/credits/usage/
Permission: IsAuthenticatedAndActive + HasTenantAccess

Standard CRUD:

  • GET /api/v1/billing/credits/usage/ - List usage logs (paginated)
  • GET /api/v1/billing/credits/usage/{id}/ - Get usage log

Filtering:

  • operation_type - Filter by operation type
  • start_date - Filter by start date (YYYY-MM-DD)
  • end_date - Filter by end date (YYYY-MM-DD)

Custom Actions:

  • GET /api/v1/billing/credits/usage/summary/ - Get usage summary
  • GET /api/v1/billing/credits/usage/limits/ - Get usage limits

Credit Transactions

Base Path: /api/v1/billing/credits/transactions/
Permission: IsAdminOrOwner

Standard CRUD:

  • GET /api/v1/billing/credits/transactions/ - List transactions (paginated)
  • GET /api/v1/billing/credits/transactions/{id}/ - Get transaction

Filtering:

  • transaction_type - Filter by type
  • start_date - Filter by start date
  • end_date - Filter by end date

Integration Examples

Python

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

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

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

// 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)

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:

POST /api/v1/planner/keywords/auto_cluster/
{
  "ids": [1, 2, 3, 4, 5],
  "sector_id": 1
}

Response:

{
  "success": true,
  "data": {
    "task_id": "abc123-def456-ghi789"
  }
}

Poll Progress:

GET /api/v1/system/settings/task_progress/abc123-def456-ghi789/

Progress Response:

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

const throttleLimit = response.headers.get('X-Throttle-Limit');
const throttleRemaining = response.headers.get('X-Throttle-Remaining');

if (parseInt(throttleRemaining) < 5) {
  showNotification('Approaching rate limit', 'warning');
}

Change Management

Versioning Strategy

  • v1 remains stable long-term
  • Breaking changes require v2
  • Deprecations allowed only with explicit timeline
  • Non-breaking changes can be added to v1

Breaking Changes

Definition: Changes that require client code updates

Examples:

  • Removing an endpoint
  • Changing response structure
  • Changing authentication method
  • Removing a field from response

Process:

  1. Document breaking change
  2. Provide migration guide
  3. Deprecate in v1 with timeline
  4. Implement in v2
  5. Maintain v1 for deprecation period

Non-Breaking Changes

Definition: Changes that don't require client code updates

Examples:

  • Adding new endpoints
  • Adding optional fields to response
  • Adding new query parameters
  • Performance improvements

Changelog

All API changes are documented in CHANGELOG.md with:

  • Version number
  • Date
  • Type (Added, Changed, Fixed, Deprecated, Removed, Security)
  • Description
  • Affected areas
  • Migration notes (if applicable)

Summary

Implementation Status

100% Complete - All endpoints implemented with:

  • Unified response format ({success, data, message, errors, request_id})
  • Proper authentication and authorization (JWT Bearer tokens)
  • Rate limiting configured (scoped by operation type)
  • Error handling standardized (centralized exception handler)
  • Request ID tracking (every request has unique ID)
  • Complete Swagger/OpenAPI documentation
  • Tenant/site/sector scoping (automatic filtering)
  • Pagination standardized (default: 10, max: 100)

Key Features

  • 100+ endpoints across 5 modules
  • Unified response format for all endpoints
  • Scoped rate limiting (10-100 requests/minute depending on operation)
  • Layered authorization (Authentication → Tenant → Role → Site/Sector)
  • Complete OpenAPI documentation (Swagger UI, ReDoc)
  • Request ID tracking for debugging
  • Progress tracking for AI functions
  • Comprehensive error handling with clear messages

Access Points

  • Interactive Documentation: https://api.igny8.com/api/docs/
  • ReDoc: https://api.igny8.com/api/redoc/
  • OpenAPI Schema: https://api.igny8.com/api/schema/

Last Updated: 2025-01-XX
API Version: 1.0.0
Status: 100% IMPLEMENTED