API Documentation
API endpoints and functionality documentation.
API Documentation
Overview
The Everything That Can Happen API is a RESTful service that provides endpoints for story management, user authentication, multi-layer image generation, and content management. All endpoints are prefixed with /api/v1.
Base URLs:
- Development:
http://localhost:3001/api/v1 - Production:
https://everything-happens-production.up.railway.app/api/v1
Error Handling and Logging
Global Error Interception
The application implements a Global Exception Filter that automatically captures and logs all errors throughout the system:
- Automatic Logging: All
throw new Error()statements and unhandled exceptions are automatically logged to the internal logging service - Admin Visibility: Errors appear in the Admin Debug Logs interface (
/admin/logs) - Categorization: Errors are automatically categorized based on the request path:
OPENAI: OpenAI API related errors (/reports/openai/*)AUTH: Authentication errors (/auth/*)USER: User management errors (/users/*)STORY: Story-related errors (/story/*,/stories/*)API: General API errorsSYSTEM: System-level errors
Error Context
Each logged error includes comprehensive context:
- User information (if authenticated)
- IP address and user agent
- Request method and path
- Query parameters and request body (sensitive data redacted)
- Full error stack trace
- Timestamp and request ID
Sensitive Data Protection
The logging system automatically redacts sensitive fields from request bodies:
password,token,secret,apiKey,authorization, etc.
OpenAI Error Monitoring
OpenAI API errors (such as usage data fetching failures) are automatically:
- Logged with
OPENAIcategory - Include full API error details
- Accessible to admins via the Debug Logs interface
- Include request context for troubleshooting
Authentication
Headers
Authorization: Bearer <token>
Content-Type: application/json
Story Node Settings
Story node settings allow customization of AI generation parameters for individual story nodes. Settings follow an inheritance hierarchy: Node Settings โ Parent Node Settings โ Story Settings โ System Defaults.
Get Node Settings Status
GET /api/v1/stories/nodes/{nodeId}/settings
Purpose: Check if a story node has custom settings and get settings metadata.
Path Parameters:
nodeId: The story node identifier
Response:
{
"hasCustomSettings": false,
"settingsUUID": "parent-settings-uuid-here",
"message": "Node uses inherited settings from parent or story defaults"
}
Note: The hasCustomSettings field indicates whether the node has its own custom settings (true) or inherits settings from parent/story (false). The settingsUUID shows which settings record is being used.
Enable Custom Settings
POST /api/v1/stories/nodes/{nodeId}/settings/custom
Purpose: Enable custom settings for a story node, creating a new settings record.
Path Parameters:
nodeId: The story node identifier
Response:
{
"message": "Custom settings enabled for node",
"settingsUUID": "newly-created-settings-uuid"
}
Note: This creates a new settings record and sets useCustomSettings = true for the node.
Disable Custom Settings
DELETE /api/v1/stories/nodes/{nodeId}/settings/custom
Purpose: Disable custom settings for a story node, reverting to inherited settings.
Path Parameters:
nodeId: The story node identifier
Response:
{
"message": "Custom settings removed for node. Node now uses inherited settings.",
"settingsUUID": "parent-or-story-settings-uuid"
}
Note: This sets useCustomSettings = false and reverts to parent or story settings.
Authentication Endpoints
Register User
POST /api/v1/auth/register
Purpose: Create a new user account with email verification.
Request Body:
{
"email": "string",
"password": "string"
}
Response:
{
"message": "User registered successfully. Please check your email for verification.",
"user": {
"id": "string",
"email": "string",
"roles": ["player"],
"emailVerified": false
}
}
Login User
POST /api/v1/auth/login
Purpose: Authenticate user and receive JWT token.
Request Body:
{
"email": "string",
"password": "string"
}
Response:
{
"message": "Login successful",
"user": {
"id": "string",
"email": "string",
"roles": ["string"],
"emailVerified": true
}
}
Note: JWT token is set as an HttpOnly cookie for security.
Logout User
POST /api/v1/auth/logout
Purpose: Clear authentication session and JWT cookie.
Response:
{
"message": "Logout successful"
}
Verify JWT Token
GET /api/v1/auth/verify
Purpose: Verify current JWT token and get user information.
Headers Required: Authorization: Bearer <token> or valid JWT cookie
Response:
{
"user": {
"id": "string",
"email": "string",
"roles": ["string"],
"emailVerified": true
}
}
Email Verification
POST /api/v1/auth/verify-email
Purpose: Verify user email address using verification token.
Request Body:
{
"token": "string"
}
Response:
{
"message": "Email verified successfully"
}
Password Reset Request
POST /api/v1/auth/password-reset
Purpose: Request password reset email.
Request Body:
{
"email": "string"
}
Response:
{
"message": "Password reset email sent"
}
Password Reset Confirmation
POST /api/v1/auth/password-reset/confirm
Purpose: Confirm password reset with token and new password.
Request Body:
{
"token": "string",
"newPassword": "string"
}
Response:
{
"message": "Password reset successful"
}
Story Management
Generate Next Story Node
POST /api/v1/story/generate-next
Purpose: Dynamically generates the next story node when a pre-existing node for the chosen optionโs nextNodeId is not found.
Role Required: Storyteller or higher
Behavior:
- The backendโs
StoryServicecalls OpenAI GPT-3.5-turbo to generate thetitle,storyText, andoptionsfor the new node - Constructs image generation prompts for enabled image layers (background, middle, foreground)
- Generates images for enabled layers, currently supports GTP-IMAGE-1, DALL-E 3 and DALL-E-2
- Stores images in hierarchical Cloudflare R2 storage
- Saves the new
StoryNodeDatato the database - Returns the complete story node with layer images
Request Body:
{
"currentScenarioId": "string",
"currentNodeId": "string",
"currentStoryText": "string",
"chosenOption": {
"text": "string",
"nextNodeId": "string"
}
}
Response: (Success: 200 OK)
{
"scenarioId": "string",
"nodeId": "string",
"parentId": "string",
"title": "string",
"storyText": "string",
"imageUrl": "string",
"layerImages": {
"background": "string",
"middle": "string",
"foreground": "string"
},
"options": [
{
"text": "string",
"nextNodeId": "string"
}
],
"viewCount": 1
}
Get Specific Story Node
GET /api/v1/story/node/:nodeId
Purpose: Retrieves a specific story node by its ID from the backendโs data store.
Parameters:
nodeId(string, required): The ID of the story node to retrieve
Response: (Success: 200 OK)
{
"scenarioId": "string",
"nodeId": "string",
"parentId": "string",
"title": "string",
"storyText": "string",
"imageUrl": "string",
"layerImages": {
"background": "string",
"middle": "string",
"foreground": "string"
},
"options": [
{
"text": "string",
"nextNodeId": "string"
}
],
"viewCount": "number",
"lastViewed": "string"
}
Get Multi-Layer Images
GET /api/v1/story/node/:nodeId/layers
Purpose: Retrieve available layer images for a specific story node.
Parameters:
nodeId(string, required): The ID of the story node
Response: (Success: 200 OK)
{
"background": "string",
"middle": "string",
"foreground": "string"
}
Note: Only returns URLs for layers that have generated images.
Story Node Settings
The Story Node Settings system provides granular control over AI generation parameters at the individual story node level, enabling dynamic storytelling with customized AI behavior for different scenes and narrative moments.
Get Effective Parameters
GET /api/v1/story-nodes/:nodeId/settings
Purpose: Retrieve the effective AI generation parameters for a story node, following the resolution hierarchy (custom settings โ parent inheritance โ story defaults โ system defaults).
Role Required: Player or higher (for owned/accessible stories)
Parameters:
nodeId(string, required): The ID of the story node
Response: (Success: 200 OK)
{
"nodeId": "string",
"hasCustomSettings": "boolean",
"settingsUUID": "string",
"parameters": {
"aiSystemPrompt": "string",
"titleGenerationInstructions": "string",
"storyTextGenerationInstructions": "string",
"choiceGenerationInstructions": "string",
"imageGenerationInstructions": "string"
},
"storyParameters": {
"aiSystemPrompt": "string",
"titleGenerationInstructions": "string",
"storyTextGenerationInstructions": "string",
"choiceGenerationInstructions": "string",
"imageGenerationInstructions": "string"
}
}
Set Custom Settings
PUT /api/v1/story-nodes/:nodeId/settings/custom
Purpose: Apply custom AI generation parameters to a specific story node.
Role Required: Storyteller or higher (must own the story or have edit access)
Parameters:
nodeId(string, required): The ID of the story node
Request Body:
{
"parameters": {
"aiSystemPrompt": "string",
"titleGenerationInstructions": "string",
"storyTextGenerationInstructions": "string",
"choiceGenerationInstructions": "string",
"imageGenerationInstructions": "string"
}
}
Response: (Success: 200 OK)
{
"success": true,
"message": "Custom settings applied successfully",
"settingsUUID": "string"
}
Remove Custom Settings
DELETE /api/v1/story-nodes/:nodeId/settings/custom
Purpose: Remove custom settings from a story node, reverting to story defaults or parent inheritance.
Role Required: Storyteller or higher (must own the story or have edit access)
Parameters:
nodeId(string, required): The ID of the story node
Response: (Success: 204 No Content)
Update Shared Settings
PUT /api/v1/story-nodes/:nodeId/settings/update/:settingsUUID
Purpose: Update shared settings using copy-on-write approach. Creates a new settings record and updates all nodes using the specified UUID to reference the new settings.
Role Required: Storyteller or higher (must own the story or have edit access)
Parameters:
nodeId(string, required): The ID of the story nodesettingsUUID(string, required): The UUID of the settings to update
Request Body:
{
"parameters": {
"aiSystemPrompt": "string",
"titleGenerationInstructions": "string",
"storyTextGenerationInstructions": "string",
"choiceGenerationInstructions": "string",
"imageGenerationInstructions": "string"
}
}
Response: (Success: 200 OK)
{
"success": true,
"message": "Settings updated successfully (copy-on-write)",
"settingsUUID": "string"
}
Validate Settings
POST /api/v1/story-nodes/:nodeId/settings/validate
Purpose: Validate AI generation parameters without applying them. Checks parameter lengths, content safety, and AI compatibility.
Role Required: Storyteller or higher
Parameters:
nodeId(string, required): The ID of the story node
Request Body:
{
"parameters": {
"aiSystemPrompt": "string",
"titleGenerationInstructions": "string",
"storyTextGenerationInstructions": "string",
"choiceGenerationInstructions": "string",
"imageGenerationInstructions": "string"
}
}
Response: (Success: 200 OK)
{
"isValid": "boolean",
"errors": ["string"]
}
Validation Rules:
- AI System Prompt: Must be under 12000 characters
- Title Generation Instructions: Must be under 500 characters
- Story Text Generation Instructions: Must be under 1000 characters
- Choice Generation Instructions: Must be under 500 characters
- Image Generation Instructions: Must be under 12000 characters
- Content safety checks prevent inappropriate or harmful content
- XSS prevention (no script tags or javascript: protocols)
Settings Inheritance
The system implements a hierarchical fallback approach for resolving AI generation parameters:
- Custom Node Settings: If the node has a
storyNodeSettingsUUID, use those specific parameters - Parent Inheritance: If no custom settings, inherit from parent node settings
- Story Defaults: Fall back to story-level default parameters
- System Defaults: Final fallback to built-in system parameters
UUID-Based Sharing
Multiple story nodes can share the same settings by referencing the same settingsUUID. This enables:
- Consistent AI behavior across related story sections
- Efficient storage (settings stored once, referenced by many nodes)
- Bulk updates via the copy-on-write mechanism
Error Responses
400 Bad Request - Invalid parameters or validation failures:
{
"error": "Bad Request",
"message": "Invalid parameters: AI System Prompt must be under 12000 characters",
"statusCode": 400
}
401 Unauthorized - Missing or invalid authentication:
{
"error": "Unauthorized",
"message": "Authentication required",
"statusCode": 401
}
403 Forbidden - Insufficient permissions:
{
"error": "Forbidden",
"message": "You do not have permission to modify settings for this story",
"statusCode": 403
}
404 Not Found - Node or settings not found:
{
"error": "Not Found",
"message": "Story node not found: node-123",
"statusCode": 404
}
Story Collection Management
Get Stories
GET /api/v1/stories
Purpose: List available stories with metadata.
Response:
{
"stories": [
{
"id": "string",
"ifid": "string",
"title": "string",
"description": "string",
"initialNodeId": "string",
"metadata": {
"genre": "string",
"theme": "string",
"createdAt": "string",
"updatedAt": "string",
"version": "string",
"author": "string",
"tags": ["string"]
},
"layerConfig": {
"background": "boolean",
"middle": "boolean",
"foreground": "boolean"
},
"isPublished": "boolean",
"playCount": "number"
}
]
}
Get Story Details
GET /api/v1/stories/{storyId}
Purpose: Get detailed information about a specific story.
Response:
{
"id": "string",
"ifid": "string",
"title": "string",
"description": "string",
"initialNodeId": "string",
"metadata": {
"genre": "string",
"theme": "string",
"createdAt": "string",
"updatedAt": "string",
"version": "string",
"author": "string",
"tags": ["string"]
},
"layerConfig": {
"background": "boolean",
"middle": "boolean",
"foreground": "boolean"
},
"systemPrompt": "string",
"imagePromptTemplate": "string",
"isPublished": "boolean",
"playCount": "number"
}
Create Story
POST /api/v1/stories
Role Required: Storyteller or higher
Request Body:
{
"title": "string",
"description": "string",
"initialNodeId": "string",
"metadata": {
"genre": "string",
"theme": "string",
"version": "string",
"author": "string",
"tags": ["string"]
},
"layerConfig": {
"background": "boolean",
"middle": "boolean",
"foreground": "boolean"
},
"systemPrompt": "string",
"imagePromptTemplate": "string"
}
Response:
{
"id": "string",
"ifid": "string",
"title": "string",
"description": "string",
"initialNodeId": "string",
"metadata": {
"genre": "string",
"theme": "string",
"createdAt": "string",
"updatedAt": "string",
"version": "string",
"author": "string",
"tags": ["string"]
},
"layerConfig": {
"background": "boolean",
"middle": "boolean",
"foreground": "boolean"
},
"isPublished": false,
"playCount": 0
}
Update Story
PUT /api/v1/stories/{storyId}
Role Required: Storyteller or higher (must be story author or admin)
Request Body:
{
"title": "string",
"description": "string",
"metadata": {
"genre": "string",
"theme": "string",
"version": "string",
"author": "string",
"tags": ["string"]
},
"layerConfig": {
"background": "boolean",
"middle": "boolean",
"foreground": "boolean"
},
"systemPrompt": "string",
"imagePromptTemplate": "string",
"isPublished": "boolean"
}
Response:
{
"id": "string",
"ifid": "string",
"title": "string",
"description": "string",
"initialNodeId": "string",
"metadata": {
"genre": "string",
"theme": "string",
"createdAt": "string",
"updatedAt": "string",
"version": "string",
"author": "string",
"tags": ["string"]
},
"layerConfig": {
"background": "boolean",
"middle": "boolean",
"foreground": "boolean"
},
"isPublished": "boolean",
"playCount": "number"
}
Delete Story
DELETE /api/v1/stories/{storyId}
Role Required: Admin or story author
Response: 204 No Content
Image Management
Get Story Node Image
GET /api/v1/story/images/:nodeId.png
Purpose: Retrieve the main image for a story node (legacy single image support).
Parameters:
nodeId(string, required): The ID of the story node
Response: Image file (PNG format)
Get Image Variants
GET /api/v1/story/images/variants/:nodeId
Purpose: Get available image size variants for a story node.
Parameters:
nodeId(string, required): The ID of the story node
Response:
{
"variants": [
{
"size": "original",
"url": "string",
"width": 1024,
"height": 1024,
"format": "png"
},
{
"size": "full",
"url": "string",
"width": 1024,
"height": 1024,
"format": "webp"
},
{
"size": "tablet",
"url": "string",
"width": 768,
"height": 768,
"format": "webp"
},
{
"size": "mobile",
"url": "string",
"width": 480,
"height": 480,
"format": "webp"
},
{
"size": "thumb",
"url": "string",
"width": 200,
"height": 200,
"format": "webp"
}
]
}
Generate Image
POST /api/v1/story/images/generate
Role Required: Storyteller or higher
Purpose: Generate new image(s) for a story node with optional layer configuration.
Request Body:
{
"nodeId": "string",
"prompt": "string",
"layerConfig": {
"background": "boolean",
"middle": "boolean",
"foreground": "boolean"
}
}
Response:
{
"nodeId": "string",
"images": {
"background": "string",
"middle": "string",
"foreground": "string"
},
"generatedAt": "string"
}
Chat Integration
ChatGPT Proxy
POST /api/v1/chat/completions
Purpose: Proxy endpoint for ChatGPT integration with conversation history.
Request Body:
{
"message": "string",
"history": [
{
"role": "user|assistant",
"content": "string"
}
]
}
Response:
{
"response": "string",
"usage": {
"prompt_tokens": "number",
"completion_tokens": "number",
"total_tokens": "number"
}
}
User Management
Get User Profile
GET /api/v1/users/profile
Role Required: Authenticated user
Response:
{
"id": "string",
"email": "string",
"roles": ["string"],
"emailVerified": "boolean",
"createdAt": "string",
"lastLogin": "string",
"metadata": {
"registrationIp": "string",
"lastLoginIp": "string"
}
}
Update User Profile
PUT /api/v1/users/profile
Role Required: Authenticated user
Request Body:
{
"email": "string"
}
Response:
{
"id": "string",
"email": "string",
"roles": ["string"],
"emailVerified": "boolean",
"updatedAt": "string"
}
Admin & Monitoring
Get System Logs
GET /api/v1/logs
Role Required: Admin
Query Parameters:
page(number, optional): Page number for pagination (default: 1)limit(number, optional): Number of logs per page (default: 50)level(string, optional): Filter by log level (DEBUG, INFO, WARN, ERROR, FATAL)category(string, optional): Filter by category (USER, STORY, AUTH, API, SYSTEM, DATABASE, IMAGE, EMAIL)userId(string, optional): Filter by user IDuserEmail(string, optional): Filter by user emailipAddress(string, optional): Filter by IP addressstartDate(string, optional): Filter logs after this date (ISO format)endDate(string, optional): Filter logs before this date (ISO format)search(string, optional): Full-text search in titles and messages
Response:
{
"logs": [
{
"_id": "string",
"level": "string",
"category": "string",
"title": "string",
"message": "string",
"timestamp": "string",
"userId": "string",
"userEmail": "string",
"ipAddress": "string",
"metadata": {
"nodeId": "string",
"storyId": "string",
"requestId": "string",
"userAgent": "string"
}
}
],
"total": "number",
"page": "number",
"totalPages": "number"
}
Get Log Statistics
GET /api/v1/logs/stats
Role Required: Admin
Response:
{
"totalLogs": "number",
"logsByLevel": {
"DEBUG": "number",
"INFO": "number",
"WARN": "number",
"ERROR": "number",
"FATAL": "number"
},
"logsByCategory": {
"USER": "number",
"STORY": "number",
"AUTH": "number",
"API": "number",
"SYSTEM": "number",
"DATABASE": "number",
"IMAGE": "number",
"EMAIL": "number"
}
}
Get System Analytics
GET /api/v1/analytics
Role Required: Admin
Response:
{
"users": {
"total": "number",
"verified": "number",
"active": "number"
},
"stories": {
"total": "number",
"published": "number",
"totalNodes": "number"
},
"images": {
"total": "number",
"byLayer": {
"background": "number",
"middle": "number",
"foreground": "number"
}
},
"performance": {
"averageResponseTime": "number",
"errorRate": "number",
"uptime": "number"
}
}
OpenAI Usage Reports
Get OpenAI Completion Usage
GET /api/v1/reports/openai/completions
Role Required: Admin or Moderator
Purpose: Retrieve OpenAI completion usage data for monitoring API consumption and costs.
Query Parameters:
date(string, optional): Date in YYYY-MM-DD format (defaults to yesterday)bucket_width(string, optional): Time bucket width -1dor1h(defaults to1d)limit(number, optional): Maximum number of records to return (max 10000, defaults to 1000)page(string, optional): Pagination cursor for large datasets
Response:
{
"object": "list",
"data": [
{
"aggregation_timestamp": 1672531200,
"n_requests": 100,
"operation": "chat.completions",
"snapshot_id": "snapshot-id",
"n_context_tokens_total": 5000,
"n_generated_tokens_total": 2000
}
],
"has_more": false
}
Get OpenAI Image Usage
GET /api/v1/reports/openai/images
Role Required: Admin or Moderator
Purpose: Retrieve OpenAI image generation usage data for monitoring API consumption and costs.
Query Parameters:
date(string, optional): Date in YYYY-MM-DD format (defaults to yesterday)bucket_width(string, optional): Time bucket width -1dor1h(defaults to1d)limit(number, optional): Maximum number of records to return (max 10000, defaults to 1000)page(string, optional): Pagination cursor for large datasets
Response:
{
"object": "list",
"data": [
{
"aggregation_timestamp": 1672531200,
"n_requests": 50,
"operation": "images.generations",
"snapshot_id": "snapshot-id",
"num_images": 75,
"size": "1024x1024",
"source": "dalle-3"
}
],
"has_more": false
}
Get OpenAI Usage Statistics
GET /api/v1/reports/openai/stats
Role Required: Admin or Moderator
Purpose: Get aggregated usage statistics for both completions and images over a date range.
Query Parameters:
start_date(string, optional): Start date in YYYY-MM-DD format (defaults to 7 days ago)end_date(string, optional): End date in YYYY-MM-DD format (defaults to yesterday)
Response:
{
"totalCompletionRequests": 150,
"totalCompletionTokens": 7500,
"totalImageRequests": 75,
"totalImages": 100,
"dateRange": {
"start": "2023-01-01",
"end": "2023-01-07"
}
}
Role-Based Access Control
Role Hierarchy
- Guest - Unauthenticated users (read-only access)
- Player - Standard authenticated users
- Storyteller - Content creators
- Moderator - Content moderators
- Admin - Full system access
Permission Requirements
| Endpoint | Guest | Player | Storyteller | Moderator | Admin |
|---|---|---|---|---|---|
| GET /story/node/:id | โ | โ | โ | โ | โ |
| POST /story/generate-next | โ | โ | โ | โ | โ |
| POST /stories | โ | โ | โ | โ | โ |
| PUT /stories/:id | โ | โ | โ * | โ | โ |
| DELETE /stories/:id | โ | โ | โ * | โ | โ |
| GET /logs | โ | โ | โ | โ | โ |
| GET /analytics | โ | โ | โ | โ | โ |
| GET /reports/openai/* | โ | โ | โ | โ | โ |
*Storytellers can only modify their own stories
Error Responses
Standard Error Format
{
"statusCode": "number",
"message": "string",
"error": "string",
"timestamp": "string",
"path": "string"
}
Common Error Codes
400 Bad Request: Invalid request body or parameters401 Unauthorized: Authentication required or invalid token403 Forbidden: Insufficient permissions for the requested action404 Not Found: Resource not found409 Conflict: Resource already exists or conflict with current state429 Too Many Requests: Rate limit exceeded500 Internal Server Error: Server error or external service failure
Authentication Errors
{
"statusCode": 401,
"message": "Invalid credentials",
"error": "Unauthorized"
}
Permission Errors
{
"statusCode": 403,
"message": "Insufficient permissions. Required role: Storyteller",
"error": "Forbidden"
}
Validation Errors
{
"statusCode": 400,
"message": [
"email must be a valid email",
"password must be longer than or equal to 8 characters"
],
"error": "Bad Request"
}
Rate Limiting
- Authentication endpoints: 5 requests per minute per IP
- Story generation: 10 requests per hour per user
- Image generation: 5 requests per hour per user
- General API: 100 requests per minute per user
Webhooks (Planned)
Future webhook support for:
- Story node creation
- User registration
- Image generation completion
- Content moderation events