11 KiB
IGNY8 API Documentation v1.0
Base URL: https://api.igny8.com/api/v1/
Version: 1.0.0
Last Updated: 2025-11-16
Quick Links
- Interactive API Documentation (Swagger UI)
- Authentication Guide
- Response Format
- Error Handling
- Rate Limiting
- Pagination
- Endpoint Reference
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 loginPOST /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: Alwaysfalseerror: Top-level error messageerrors: 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 allowedX-Throttle-Remaining: Remaining requests in current windowX-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-Resetbefore 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 itemsnext: 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:
- Check the Interactive Documentation
- Review Error Codes Reference
- Contact support with your
request_id
Last Updated: 2025-11-16
API Version: 1.0.0