""" API Documentation System - OpenAPI/Swagger documentation - Endpoint discovery - Schema validation """ from fastapi.openapi.utils import get_openapi from fastapi import FastAPI import json from typing import Dict, List, Any, Optional from pathlib import Path import os class APIDocumentation: """API documentation generator""" @staticmethod def generate_openapi_schema(app: FastAPI) -> Dict[str, Any]: """Generate OpenAPI schema""" return get_openapi( title="Moharek GEO Platform API", version="1.0.0", description="AI-powered Generative Engine Optimization platform", routes=app.routes, ) @staticmethod def get_endpoint_docs() -> List[Dict[str, Any]]: """Get documentation for all endpoints""" return [ { "path": "/api/crawl", "method": "POST", "description": "Crawl website and analyze content", "parameters": { "url": "Website URL to crawl", "org_name": "Organization name", "org_url": "Organization URL", "max_pages": "Maximum pages to crawl (default: 3)", "runs": "Number of runs to average (default: 1)" }, "response": { "ok": "Success status", "message": "Response message", "mean_score": "Average GEO score", "median_score": "Median GEO score", "variance": "Score variance" }, "rate_limit": "10 requests/hour", "authentication": "Optional (Bearer token)" }, { "path": "/api/jobs", "method": "POST", "description": "Enqueue a crawl job", "parameters": { "url": "Website URL", "org_name": "Organization name", "org_url": "Organization URL", "max_pages": "Maximum pages (default: 3)", "runs": "Number of runs (default: 1)" }, "response": { "ok": "Success status", "job_id": "Job ID for tracking" }, "rate_limit": "30 requests/minute", "authentication": "Optional" }, { "path": "/api/jobs/{job_id}", "method": "GET", "description": "Get job status", "parameters": { "job_id": "Job ID" }, "response": { "ok": "Success status", "job": "Job details including status and progress" }, "rate_limit": "100 requests/minute", "authentication": "Optional" }, { "path": "/ws/jobs/{job_id}", "method": "WebSocket", "description": "Real-time job progress updates", "parameters": { "job_id": "Job ID" }, "response": "Job status updates in real-time", "rate_limit": "Unlimited", "authentication": "Optional" }, { "path": "/api/analyze", "method": "POST", "description": "Analyze crawled content", "parameters": { "job_id": "Job ID (optional)", "api_keys": "API keys for external services" }, "response": { "ok": "Success status", "analysis": "Content analysis results", "geo_score": "GEO visibility score", "competitor_insight": "Competitor analysis" }, "rate_limit": "20 requests/hour", "authentication": "Optional" }, { "path": "/api/recommendations", "method": "POST", "description": "Generate SEO recommendations", "parameters": { "job_id": "Job ID (optional)", "api_keys": "API keys for external services" }, "response": { "ok": "Success status", "recommendations": "List of recommendations", "audit": "Audit data", "geo_score": "GEO score" }, "rate_limit": "20 requests/hour", "authentication": "Optional" }, { "path": "/api/keywords", "method": "POST", "description": "Extract and analyze keywords", "parameters": { "url": "Website URL", "max_pages": "Maximum pages (default: 1)", "enrich": "Enrich with search volume data", "analytics": "Return analytics data" }, "response": { "ok": "Success status", "keywords": "List of keywords", "analytics": "Keyword analytics (if requested)" }, "rate_limit": "15 requests/hour", "authentication": "Optional" }, { "path": "/api/content/generate", "method": "POST", "description": "Generate AI content", "parameters": { "keyword": "Target keyword", "lang": "Language (default: en)", "target_site": "Target website", "prefer_backend": "AI backend (groq/openai)" }, "response": { "ok": "Success status", "result": "Generated content" }, "rate_limit": "5 requests/hour", "authentication": "Optional" }, { "path": "/api/content/optimize", "method": "POST", "description": "Optimize existing content", "parameters": { "content": "Content to optimize", "keyword": "Target keyword", "lang": "Language (default: en)" }, "response": { "ok": "Success status", "result": "Optimized content" }, "rate_limit": "10 requests/hour", "authentication": "Optional" }, { "path": "/api/users/register", "method": "POST", "description": "Register new user", "parameters": { "email": "User email", "password": "User password", "company_id": "Company ID (optional)" }, "response": { "ok": "Success status", "user_id": "New user ID", "token": "Authentication token" }, "rate_limit": "5 requests/minute", "authentication": "None" }, { "path": "/api/users/login", "method": "POST", "description": "Login user", "parameters": { "email": "User email", "password": "User password" }, "response": { "ok": "Success status", "token": "Authentication token", "user": "User details" }, "rate_limit": "10 requests/minute", "authentication": "None" }, { "path": "/api/users/me", "method": "GET", "description": "Get current user", "parameters": {}, "response": { "ok": "Success status", "user": "User details" }, "rate_limit": "100 requests/minute", "authentication": "Required (Bearer token)" }, { "path": "/api/notifications", "method": "GET", "description": "Get user notifications", "parameters": { "unread_only": "Only unread notifications" }, "response": { "ok": "Success status", "notifications": "List of notifications", "count": "Total count" }, "rate_limit": "50 requests/minute", "authentication": "Required" }, { "path": "/api/2fa/setup", "method": "POST", "description": "Setup two-factor authentication", "parameters": {}, "response": { "ok": "Success status", "secret": "2FA secret", "qr_code": "QR code for authenticator app" }, "rate_limit": "5 requests/minute", "authentication": "Required" }, { "path": "/api/support/tickets", "method": "POST", "description": "Create support ticket", "parameters": { "subject": "Ticket subject", "description": "Ticket description", "category": "Ticket category", "priority": "Priority level" }, "response": { "ok": "Success status", "ticket_id": "New ticket ID" }, "rate_limit": "10 requests/hour", "authentication": "Required" }, { "path": "/api/ads/dashboard", "method": "GET", "description": "Get ads dashboard data", "parameters": { "demo": "Use demo data", "days": "Number of days (default: 30)" }, "response": { "ok": "Success status", "summary": "KPI summary", "campaigns": "Campaign data" }, "rate_limit": "20 requests/hour", "authentication": "Optional" }, { "path": "/api/geo/visibility", "method": "POST", "description": "Check AI visibility score", "parameters": { "brand": "Brand name", "queries": "Search queries", "api_keys": "API keys" }, "response": { "ok": "Success status", "result": "Visibility score and details" }, "rate_limit": "20 requests/hour", "authentication": "Optional" }, { "path": "/health", "method": "GET", "description": "Health check endpoint", "parameters": {}, "response": { "status": "Service status", "service": "Service name" }, "rate_limit": "Unlimited", "authentication": "None" } ] @staticmethod def get_error_codes() -> Dict[str, str]: """Get error code documentation""" return { "200": "OK - Request successful", "201": "Created - Resource created successfully", "400": "Bad Request - Invalid parameters", "401": "Unauthorized - Authentication required", "403": "Forbidden - Insufficient permissions", "404": "Not Found - Resource not found", "429": "Too Many Requests - Rate limit exceeded", "500": "Internal Server Error - Server error", "503": "Service Unavailable - Service temporarily unavailable" } @staticmethod def get_authentication_docs() -> Dict[str, Any]: """Get authentication documentation""" return { "methods": [ { "type": "Bearer Token", "description": "JWT token in Authorization header", "example": "Authorization: Bearer ", "endpoints": "Most endpoints" }, { "type": "API Key", "description": "API key for external services", "example": "api_keys: {openai: , groq: }", "endpoints": "Content generation, analysis" } ], "token_expiry": "24 hours", "refresh": "Login again to get new token" } @staticmethod def get_rate_limit_docs() -> Dict[str, Any]: """Get rate limit documentation""" return { "default": "100 requests/minute", "endpoints": { "/api/crawl": "10 requests/hour", "/api/analyze": "20 requests/hour", "/api/keywords": "15 requests/hour", "/api/content/generate": "5 requests/hour", "/api/search": "30 requests/hour" }, "headers": { "X-RateLimit-Limit": "Maximum requests allowed", "X-RateLimit-Remaining": "Remaining requests", "Retry-After": "Seconds to wait before retry" }, "exceeded": "Returns 429 status code" } @staticmethod def save_documentation(output_path: str = None): """Save documentation to file""" if not output_path: output_path = Path(os.environ.get('OUTPUT_DIR', './output')) / 'api_docs.json' docs = { "title": "Moharek GEO Platform API", "version": "1.0.0", "description": "AI-powered Generative Engine Optimization platform", "endpoints": APIDocumentation.get_endpoint_docs(), "error_codes": APIDocumentation.get_error_codes(), "authentication": APIDocumentation.get_authentication_docs(), "rate_limits": APIDocumentation.get_rate_limit_docs() } Path(output_path).write_text(json.dumps(docs, indent=2)) return output_path # Generate documentation on import try: APIDocumentation.save_documentation() except Exception as e: print(f"Warning: Could not save API documentation: {e}")