HG Content System - API Documentation¶
Last Updated: 2025-12-30
This document provides comprehensive API documentation for all services in the HG Content System. The system consists of four main modules: Content Production Module (CPM), Instructions Module (IM), Strategy Management Module (SMM), and the Frontend Next.js application.
Table of Contents¶
- Authentication
- Content Production Module (CPM) API
- Instructions Module (IM) API
- Strategy Management Module (SMM) API
- Frontend Next.js API Routes
- Error Handling
- Rate Limiting
Authentication¶
Overview¶
The HG Content System uses different authentication methods depending on the service:
- CPM & IM: API Key authentication using Bearer tokens
- SMM: Header-based user authentication (X-User-ID)
- Frontend: NextAuth JWT authentication (session cookies)
NextAuth Authentication (Frontend)¶
The frontend uses NextAuth 4.x with JWT strategy for user authentication.
Session Cookie¶
After login, a session is stored in an HttpOnly cookie:
API Route Authentication¶
Frontend API routes verify the JWT token using getToken():
// lib/auth-helper.ts
import { getToken } from 'next-auth/jwt'
export async function getAuthUserId(request: NextRequest): Promise<string | null> {
const secret = process.env.NEXTAUTH_SECRET ?? process.env.AUTH_SECRET
const token = await getToken({ req: request, secret })
if (token?.sub) return token.sub
return null
}
Inter-Service Calls¶
When the frontend calls backend services, it passes the authenticated user ID:
API Key Authentication (CPM & IM)¶
Format¶
- Production:
cpm_live_<random_32_chars> - Development:
cpm_test_<random_32_chars>
Headers¶
Permissions¶
read: View job status and resultswrite: Create new content generation jobsadmin: Administrative operations
Content Production Module (CPM) API¶
Base URL: http://localhost:8002 (development)
Endpoints¶
POST /generate¶
Generate content using specified LLM provider with IM integration.
Authentication: Required (Bearer token) Permissions: write
Request Body:
{
"content_type": "blog",
"prompt": "Write about AI in healthcare",
"client_id": "client-uuid",
"llm_provider": "openai",
"keywords": ["AI", "healthcare", "technology"],
"length": "medium",
"model": "gpt-4",
"parameters": {
"temperature": 0.7,
"max_tokens": 2000
}
}
Request Schema: - content_type (string, required): Type of content to generate - prompt (string, required): Content generation prompt - client_id (string, required): Client identifier - llm_provider (string, optional): LLM provider to use (default: "openai") - keywords (array[string], optional): SEO keywords for content - length (string, optional): Content length ("short"/"medium"/"long") - model (string, optional): Specific model to use - parameters (object, optional): Additional parameters
Response:
{
"job_id": "job-uuid",
"status": "pending",
"message": "Content generation job queued successfully"
}
Status Codes: - 200: Job created successfully - 400: Invalid request data - 401: Unauthorized - 403: Insufficient permissions - 500: Internal server error
GET /jobs/{job_id}¶
Get status and result of a content generation job.
Authentication: Required (Bearer token) Permissions: read
Path Parameters: - job_id (string): Unique job identifier
Response:
{
"job_id": "job-uuid",
"status": "completed",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:35:00Z",
"content_type": "blog",
"client_id": "client-uuid",
"result": {
"content": "Generated content...",
"metadata": {
"word_count": 1500,
"model_used": "gpt-4",
"cost_estimate": 0.12
}
},
"error": null
}
Status Values: - pending: Job queued for processing - in_progress: Currently being processed - completed: Successfully completed - failed: Processing failed - cancelled: Job was cancelled
Status Codes: - 200: Job found and returned - 401: Unauthorized - 403: Insufficient permissions - 404: Job not found - 500: Internal server error
GET /jobs¶
List jobs for the authenticated client.
Authentication: Required (Bearer token) Permissions: read
Query Parameters: - status (string, optional): Filter by job status - limit (integer, optional): Maximum number of jobs (default: 20, max: 100) - offset (integer, optional): Number of jobs to skip (default: 0)
Response:
{
"jobs": [
{
"job_id": "job-uuid-1",
"status": "completed",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:35:00Z",
"content_type": "blog",
"client_id": "client-uuid",
"result": {...},
"error": null
}
],
"total": 1,
"limit": 20,
"offset": 0
}
Status Codes: - 200: Jobs retrieved successfully - 400: Invalid query parameters - 401: Unauthorized - 403: Insufficient permissions - 500: Internal server error
GET /health¶
Health check endpoint for monitoring.
Authentication: Not required
Response:
Status Codes: - 200: Service healthy - 503: Service unhealthy
GET /¶
Root endpoint with basic service information.
Authentication: Not required
Response:
{
"service": "Content Production Module",
"version": "1.0.0",
"status": "operational",
"docs": "/docs"
}
Instructions Module (IM) API¶
Base URL: http://localhost:8001 (development)
Endpoints¶
POST /generate-prompt¶
Create a new prompt generation job.
Authentication: Required (Bearer token) Permissions: write
Request Body:
{
"client_id": "client-uuid",
"content_type": "blog",
"topic": "AI in healthcare",
"keywords": ["AI", "healthcare", "machine learning"],
"context": {
"target_audience": "healthcare professionals",
"tone": "professional"
}
}
Request Schema: - client_id (uuid, required): Client identifier - content_type (enum, required): Type of content ("blog", "social", "email", etc.) - topic (string, required): Topic for prompt generation - keywords (array[string], optional): Keywords to include - context (object, optional): Additional context information
Response:
Status Codes: - 202: Job created successfully - 400: Invalid request parameters - 401: Unauthorized - 503: Service unavailable
GET /prompt/{job_id}¶
Get prompt generation job status and results.
Authentication: Required (Bearer token) Permissions: read
Path Parameters: - job_id (uuid): Unique job identifier
Response (Completed):
{
"job_id": "job-uuid",
"status": "completed",
"prompt": "Enhanced prompt for content generation...",
"metadata": {
"templates_used": ["blog_template_v1"],
"enhancements_applied": ["seo_optimization", "tone_adjustment"]
},
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:32:00Z"
}
Response (In Progress):
Response (Failed):
{
"job_id": "job-uuid",
"status": "failed",
"error": "Template not found for content type",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:31:00Z"
}
Status Codes: - 200: Job completed - returns prompt - 202: Job still processing - 404: Job not found - 503: Service unavailable
GET /templates/{client_id}¶
Get templates for a specific client (Debug endpoint).
Authentication: Required (Bearer token) Permissions: read
Path Parameters: - client_id (string): Client identifier
Query Parameters: - content_type (string, optional): Filter by content type - active_only (boolean, optional): Return only active templates (default: true)
Response:
{
"client_id": "client-uuid",
"templates": [
{
"id": "template-uuid",
"name": "Blog Template v1",
"content_type": "blog",
"template": "Write a {length} blog post about {topic}...",
"active": true,
"created_at": "2024-01-15T10:30:00Z"
}
],
"count": 1
}
Status Codes: - 200: Templates retrieved successfully - 404: Client not found - 503: Service unavailable
GET /health¶
Service health check endpoint.
Authentication: Not required
Response:
{
"status": "healthy",
"service": "Instructions Module",
"version": "1.0.0",
"timestamp": "2024-01-15T10:30:00Z",
"database_status": "connected",
"openai_status": "enabled",
"task_manager": {
"active_tasks": 3,
"total_tasks": 15,
"total_completed": 12,
"total_failed": 0
}
}
Status Codes: - 200: Service healthy - 503: Service unhealthy
GET /stats¶
Get service statistics and metrics.
Authentication: Required (Bearer token) Permissions: read
Query Parameters: - client_id (string, optional): Filter statistics by client
Response:
{
"service": "Instructions Module",
"version": "1.0.0",
"timestamp": "2024-01-15T10:30:00Z",
"filter": {
"client_id": "client-uuid"
},
"job_statistics": {
"total_jobs": 150,
"completed_jobs": 145,
"failed_jobs": 3,
"pending_jobs": 2
},
"task_manager_metrics": {
"task_counts": {
"active": 3,
"total": 15
},
"total_completed": 145,
"total_failed": 3
},
"template_cache": {
"cached_templates": 25,
"cache_max_age_seconds": 3600
}
}
Status Codes: - 200: Statistics retrieved successfully - 503: Service unavailable
Strategy Management Module (SMM) API¶
Base URL: http://localhost:8003 (development)
Authentication¶
Uses header-based authentication with X-User-ID header.
Headers:
Endpoints¶
GET /api/strategies/{client_id}¶
Get consolidated strategy for a client.
Authentication: Required (X-User-ID header)
Path Parameters: - client_id (uuid): Client identifier
Response:
{
"id": "strategy-uuid",
"client_id": "client-uuid",
"name": "Main Strategy",
"description": "Primary content strategy",
"config": {
"brand_voice": "Professional and approachable",
"target_audience": "Healthcare professionals",
"content_pillars": "Education, Innovation, Trust",
"tone": {
"formality": "professional",
"voice": "authoritative",
"engagement": "educational"
},
"content_guidelines": {
"min_words": 500,
"max_words": 2000,
"required_sections": ["introduction", "main_content", "conclusion"],
"citation_required": true,
"difficulty_level": "professional"
}
},
"active": true,
"version": 1,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z",
"seo_rules": [
{
"id": "rule-uuid",
"rule_type": "keywords",
"rules": {
"value": "healthcare AI",
"weight": 0.8
},
"priority": 1,
"active": true
}
],
"content_preferences": [
{
"content_type": "blog",
"preferences": {
"style": "informative",
"structure": "problem-solution-benefit"
}
}
]
}
Status Codes: - 200: Strategy retrieved successfully - 403: Access denied - 404: Strategy not found - 503: Service unavailable
PUT /api/strategies/{client_id}¶
Update a client's strategy with versioning.
Authentication: Required (X-User-ID header)
Path Parameters: - client_id (uuid): Client identifier
Request Body:
{
"config": {
"brand_voice": "Updated brand voice",
"target_audience": "Updated target audience"
},
"change_summary": "Updated brand voice and target audience"
}
Response: Returns updated consolidated strategy (same format as GET)
Status Codes: - 200: Strategy updated successfully - 403: Access denied - 404: Strategy not found - 503: Service unavailable
GET /api/seo-rules/{client_id}¶
Get all SEO rules for a client.
Authentication: Required (X-User-ID header)
Path Parameters: - client_id (uuid): Client identifier
Query Parameters: - rule_type (string, optional): Filter by rule type - active_only (boolean, optional): Return only active rules (default: true)
Response:
{
"client_id": "client-uuid",
"rules": [
{
"id": "rule-uuid",
"client_id": "client-uuid",
"rule_type": "keywords",
"rules": {
"value": "healthcare AI",
"weight": 0.8
},
"priority": 1,
"active": true,
"created_at": "2024-01-15T10:30:00Z"
}
],
"total": 1
}
Status Codes: - 200: SEO rules retrieved successfully - 403: Access denied
POST /api/seo-rules/{client_id}¶
Create a new SEO rule for a client.
Authentication: Required (X-User-ID header)
Path Parameters: - client_id (uuid): Client identifier
Request Body:
{
"rule_type": "keywords",
"rules": {
"value": "machine learning healthcare",
"weight": 0.7
},
"priority": 2,
"active": true
}
Response: Returns created SEO rule
Status Codes: - 201: SEO rule created successfully - 403: Access denied - 503: Service unavailable
PUT /api/seo-rules/{client_id}/{rule_id}¶
Update an existing SEO rule.
Authentication: Required (X-User-ID header)
Path Parameters: - client_id (uuid): Client identifier - rule_id (uuid): SEO rule identifier
Request Body (partial update):
Response: Returns updated SEO rule
Status Codes: - 200: SEO rule updated successfully - 403: Access denied - 404: SEO rule not found - 503: Service unavailable
DELETE /api/seo-rules/{client_id}/{rule_id}¶
Delete an SEO rule.
Authentication: Required (X-User-ID header)
Path Parameters: - client_id (uuid): Client identifier - rule_id (uuid): SEO rule identifier
Response:
Status Codes: - 200: SEO rule deleted successfully - 403: Access denied - 404: SEO rule not found - 503: Service unavailable
PUT /api/content-preferences/{client_id}/{content_type}¶
Update content preferences for a specific content type.
Authentication: Required (X-User-ID header)
Path Parameters: - client_id (uuid): Client identifier - content_type (enum): Content type ("blog", "social", "email", etc.)
Request Body:
{
"preferences": {
"style": "conversational",
"structure": "introduction-body-cta",
"length_preference": "medium"
}
}
Response:
{
"success": true,
"message": "Content preferences for blog updated successfully",
"data": {
"preference_id": "preference-uuid"
}
}
Status Codes: - 200: Content preferences updated successfully - 403: Access denied - 503: Service unavailable
GET /health¶
Service health check endpoint.
Authentication: Not required
Response:
{
"status": "healthy",
"service": "Strategy Management Module",
"version": "1.0.0",
"timestamp": "2024-01-15T10:30:00Z"
}
Status Codes: - 200: Service healthy - 503: Service unhealthy
Frontend Next.js API Routes¶
Base URL: http://localhost:3000 (development)
Authentication¶
Uses NextAuth JWT authentication with session cookies.
Endpoints¶
GET /api/analytics¶
Get analytics and metrics data.
Authentication: Required (NextAuth session)
Query Parameters: - client_id (string, optional): Filter by specific client - start_date (string, optional): Start date for analytics (ISO format) - end_date (string, optional): End date for analytics (ISO format)
Response:
{
"totalSpent": 45.67,
"totalContent": 150,
"avgCostPerContent": 0.30,
"costByProvider": [
{
"provider": "gpt-4",
"cost": 30.50,
"percentage": 66.8
}
],
"dailyCosts": [
{
"date": "2024-01-15",
"cost": 5.20
}
],
"totalJobs": 180,
"completedJobs": 150,
"failedJobs": 5,
"avgProcessingTime": 45,
"successRate": 83.33,
"contentByType": [
{
"type": "blog",
"count": 80,
"percentage": 44.4
}
],
"jobsOverTime": [
{
"date": "2024-01-15",
"count": 12
}
],
"statusDistribution": [
{
"status": "completed",
"count": 150,
"percentage": 83.3
}
],
"clientBreakdown": [
{
"client": "Client A",
"count": 90,
"percentage": 50.0
}
]
}
Status Codes: - 200: Analytics retrieved successfully - 401: Unauthorized - 500: Internal server error
POST /api/content/generate¶
Generate content by forwarding request to CPM service.
Authentication: Required (NextAuth session)
Request Body:
{
"client_id": "client-uuid",
"content_type": "blog",
"topic": "AI in healthcare",
"keywords": ["AI", "healthcare", "technology"],
"additional_instructions": "Focus on practical applications",
"length": "medium",
"tone": "professional"
}
Request Schema: - client_id (uuid, required): Client identifier - content_type (enum, required): Content type ("blog", "social", "local", "email", "landing") - topic (string, required): Content topic (1-500 chars) - keywords (array[string], required): Keywords (1-10 items) - additional_instructions (string, optional): Additional instructions (max 1000 chars) - length (enum, optional): Content length ("short", "medium", "long") - tone (enum, optional): Content tone ("professional", "casual", "friendly", "authoritative")
Response: Forwards CPM response
Status Codes: - 201: Content generation job created - 400: Invalid request data - 401: Unauthorized - 403: Access denied to client - 503: CPM service not configured
GET /api/jobs¶
List jobs for accessible clients.
Authentication: Required (NextAuth session)
Query Parameters: - client_id (string, optional): Filter by specific client - limit (integer, optional): Maximum number of jobs (default: 20) - offset (integer, optional): Number of jobs to skip (default: 0) - status (string, optional): Filter by job status
Response:
{
"jobs": [
{
"id": "job-uuid",
"client_id": "client-uuid",
"content_type": "blog",
"status": "completed",
"created_at": "2024-01-15T10:30:00Z",
"completed_at": "2024-01-15T10:35:00Z",
"result": {...},
"clients": {
"id": "client-uuid",
"name": "Client Name"
}
}
],
"total": 1,
"limit": 20,
"offset": 0
}
Status Codes: - 200: Jobs retrieved successfully - 401: Unauthorized - 500: Internal server error
GET /api/jobs/[jobId]¶
Get specific job details.
Authentication: Required (NextAuth session)
Path Parameters: - jobId (string): Job identifier
Response: Returns job object with client information
Status Codes: - 200: Job retrieved successfully - 401: Unauthorized - 403: Access denied - 404: Job not found - 500: Internal server error
GET /api/v2/strategies¶
List strategies for a client.
Authentication: Required (NextAuth session)
Query Parameters: - clientId (string, required): Client identifier
Response:
[
{
"id": "strategy-uuid",
"client_id": "client-uuid",
"name": "Main Strategy",
"description": "Primary content strategy",
"active": true,
"config": {
"brand_voice": "Professional and approachable",
"target_audience": "Healthcare professionals"
},
"seo_rules": [
{
"id": "rule-uuid",
"type": "keyword",
"value": "healthcare AI",
"weight": 0.8
}
],
"created_at": "2024-01-15T10:30:00Z"
}
]
Status Codes: - 200: Strategies retrieved successfully - 400: Client ID required - 401: Unauthorized - 403: Access denied - 500: Internal server error
POST /api/v2/strategies¶
Create a new strategy.
Authentication: Required (NextAuth session with admin/manager role)
Request Body:
{
"client_id": "client-uuid",
"name": "New Strategy",
"description": "Strategy description",
"active": true,
"config": {
"brand_voice": "Professional",
"target_audience": "Healthcare professionals",
"tone": {
"formality": "professional",
"voice": "authoritative"
}
},
"seo_rules": [
{
"type": "keyword",
"value": "healthcare AI",
"weight": 0.8
}
]
}
Response: Returns created strategy with transformed SEO rules
Status Codes: - 201: Strategy created successfully - 400: Invalid request data - 401: Unauthorized - 403: Insufficient permissions - 500: Internal server error
PUT /api/v2/strategies¶
Update an existing strategy.
Authentication: Required (NextAuth session with admin/manager role)
Query Parameters: - id (string, required): Strategy identifier
Request Body: Same format as POST (partial updates allowed)
Response: Returns updated strategy
Status Codes: - 200: Strategy updated successfully - 400: Strategy ID required - 401: Unauthorized - 403: Insufficient permissions - 404: Strategy not found - 500: Internal server error
DELETE /api/v2/strategies¶
Delete a strategy.
Authentication: Required (NextAuth session with admin role)
Query Parameters: - id (string, required): Strategy identifier
Response:
Status Codes: - 200: Strategy deleted successfully - 400: Strategy ID required - 401: Unauthorized - 403: Insufficient permissions - 404: Strategy not found - 500: Internal server error
GET /api/health¶
Frontend service health check.
Authentication: Not required
Response:
Status Codes: - 200: Service healthy
GET /auth/callback¶
NextAuth authentication callback handler.
Authentication: Not required (handles auth flow)
Query Parameters: - Managed by NextAuth internally
Response: Redirects to /dashboard
Error Handling¶
Standard Error Response Format¶
All services return errors in a consistent format:
{
"error": "Error message",
"detail": "Detailed error description",
"code": "ERROR_CODE",
"timestamp": "2024-01-15T10:30:00Z"
}
Common HTTP Status Codes¶
- 200: OK - Request successful
- 201: Created - Resource created successfully
- 202: Accepted - Request accepted for processing
- 400: Bad Request - Invalid request data
- 401: Unauthorized - Authentication required or failed
- 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
Service-Specific Error Codes¶
CPM Errors¶
INVALID_CLIENT_ID: Client ID mismatchWRITE_PERMISSION_REQUIRED: Write permission neededJOB_NOT_FOUND: Job does not existJOB_CREATION_FAILED: Failed to create job
IM Errors¶
INVALID_PARAMETERS: Request validation failedJOB_ERROR: Database job operation failedTEMPLATE_ERROR: Template operation failedOPENAI_ERROR: OpenAI service error
SMM Errors¶
STRATEGY_ERROR: Strategy operation failedSEO_RULE_ERROR: SEO rule operation failedACCESS_DENIED: User lacks client access
Frontend Errors¶
UNAUTHORIZED: NextAuth authentication failed or session expiredACCESS_DENIED: User lacks client permissionsCPM_SERVICE_ERROR: CPM service communication failedVALIDATION_ERROR: Request data validation failed
Rate Limiting¶
CPM & IM Rate Limiting¶
Rate limits are enforced per API key with the following default limits:
- Per Minute: 60 requests
- Per Hour: 1,000 requests
- Per Day: 10,000 requests
Rate Limit Headers¶
Responses include rate limit information:
Rate Limit Exceeded Response¶
{
"error": "Rate limit exceeded: 60 requests per minute",
"code": "RATE_LIMIT_EXCEEDED",
"retry_after": 60
}
Status Code: 429 Too Many Requests
Frontend Rate Limiting¶
The frontend service does not implement additional rate limiting beyond authentication requirements and standard Next.js/Vercel/Coolify platform limits.
SMM Rate Limiting¶
SMM does not currently implement rate limiting but relies on authentication and authorization controls.
Usage Examples¶
Complete Content Generation Workflow¶
-
Generate Content (Frontend → CPM):
-
Check Job Status:
-
Get Analytics:
Strategy Management¶
-
Get Client Strategy:
-
Update Strategy:
-
Create SEO Rule:
API Versioning¶
Current Versions¶
- CPM: v1.0.0
- IM: v1.0.0
- SMM: v1.0.0
- Frontend: v1.0.0
Versioning Strategy¶
- CPM/IM/SMM: Version included in service metadata, no URL versioning
- Frontend: URL-based versioning for breaking changes (e.g.,
/api/v2/strategies)
Deprecation Policy¶
- Deprecated endpoints will be marked with
X-Deprecated: trueheader - 6-month notice before removal
- Migration guides provided for breaking changes
Development & Testing¶
Environment Variables¶
CPM¶
DATABASE_URL=postgresql://...
REDIS_URL=redis://localhost:6379
IM_SERVICE_URL=http://localhost:8001
ENVIRONMENT=development
IM¶
SMM¶
Frontend¶
NEXT_PUBLIC_SUPABASE_URL=https://...
NEXT_PUBLIC_SUPABASE_ANON_KEY=...
CPM_SERVICE_URL=http://localhost:8002
API Documentation URLs¶
- CPM: http://localhost:8002/docs
- IM: http://localhost:8001/docs
- SMM: http://localhost:8003/docs
- Frontend: Available through this document
Last Updated: January 15, 2024 Version: 1.0.0