Files
igny8/docs/API-DOCUMENTATION.md

11 KiB

IGNY8 API Documentation v1.0

Base URL: https://api.igny8.com/api/v1/
Version: 1.0.0
Last Updated: 2025-11-16


Swagger UI

Interactive API documentation is available at:

  • Swagger UI: https://api.igny8.com/api/docs/
  • ReDoc: https://api.igny8.com/api/redoc/
  • OpenAPI Schema: https://api.igny8.com/api/schema/

The Swagger UI provides:

  • Interactive endpoint testing
  • Request/response examples
  • Authentication testing
  • Schema definitions
  • Code samples in multiple languages

Authentication

JWT Bearer Token

All endpoints require JWT Bearer token authentication except:

  • POST /api/v1/auth/login/ - User login
  • POST /api/v1/auth/register/ - User registration

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"
    },
    "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  },
  "request_id": "uuid"
}

Using the Token

Include the token in the Authorization header:

GET /api/v1/planner/keywords/
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

Token Expiration

  • Access Token: 15 minutes
  • Refresh Token: 7 days

Use the refresh token to get a new access token:

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

{
  "refresh": "your_refresh_token"
}

Response Format

Success Response

All successful responses follow this unified format:

{
  "success": true,
  "data": {
    "id": 1,
    "name": "Example",
    ...
  },
  "message": "Optional success message",
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Paginated Response

List endpoints return paginated data:

{
  "success": true,
  "count": 100,
  "next": "https://api.igny8.com/api/v1/planner/keywords/?page=2",
  "previous": null,
  "results": [
    {"id": 1, "name": "Keyword 1"},
    {"id": 2, "name": "Keyword 2"},
    ...
  ],
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Error Response

All error responses follow this unified format:

{
  "success": false,
  "error": "Validation failed",
  "errors": {
    "email": ["This field is required"],
    "password": ["Password too short"]
  },
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

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

Error Response Structure

All errors include:

  • success: Always false
  • error: Top-level error message
  • errors: Field-specific errors (for validation errors)
  • request_id: Unique request ID for debugging

Example Error Responses

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

Not Found (404):

{
  "success": false,
  "error": "Resource not found",
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Rate Limit (429):

{
  "success": false,
  "error": "Rate limit exceeded",
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Rate Limiting

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

{
  "success": false,
  "error": "Rate limit exceeded",
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Pagination

List endpoints support pagination with query parameters:

  • page: Page number (default: 1)
  • page_size: Items per page (default: 10, max: 100)

Example Request

GET /api/v1/planner/keywords/?page=2&page_size=20

Paginated Response

{
  "success": true,
  "count": 100,
  "next": "https://api.igny8.com/api/v1/planner/keywords/?page=3&page_size=20",
  "previous": "https://api.igny8.com/api/v1/planner/keywords/?page=1&page_size=20",
  "results": [
    {"id": 21, "name": "Keyword 21"},
    {"id": 22, "name": "Keyword 22"},
    ...
  ],
  "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

Endpoint Reference

Authentication Endpoints

Login

POST /api/v1/auth/login/

Register

POST /api/v1/auth/register/

Refresh Token

POST /api/v1/auth/refresh/

Planner Endpoints

List Keywords

GET /api/v1/planner/keywords/

Create Keyword

POST /api/v1/planner/keywords/

Get Keyword

GET /api/v1/planner/keywords/{id}/

Update Keyword

PUT /api/v1/planner/keywords/{id}/
PATCH /api/v1/planner/keywords/{id}/

Delete Keyword

DELETE /api/v1/planner/keywords/{id}/

Auto Cluster Keywords

POST /api/v1/planner/keywords/auto_cluster/

Writer Endpoints

List Tasks

GET /api/v1/writer/tasks/

Create Task

POST /api/v1/writer/tasks/

System Endpoints

System Status

GET /api/v1/system/status/

List Prompts

GET /api/v1/system/prompts/

Billing Endpoints

Credit Balance

GET /api/v1/billing/credits/balance/balance/

Usage Summary

GET /api/v1/billing/credits/usage/summary/

Code 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/",
        headers=headers
    )
    keywords_data = response.json()
    
    if keywords_data['success']:
        keywords = keywords_data['results']
        print(f"Found {keywords_data['count']} keywords")
    else:
        print(f"Error: {keywords_data['error']}")
else:
    print(f"Login failed: {data['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/`,
        { 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);
    }
} else {
    console.error('Login failed:', loginData.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"

Request ID

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)

Support

For API support:


Last Updated: 2025-11-16
API Version: 1.0.0