feature/api-development #1

Merged
usulpro merged 47 commits from feature/api-development into main 2025-11-29 23:03:01 +07:00
3 changed files with 595 additions and 664 deletions
Showing only changes of commit 213a378532 - Show all commits

View File

@ -1,664 +0,0 @@
# Banatie API Reference
Banatie is a REST API service for AI-powered image generation using the Gemini Flash Image model.
## Base URL
```
http://localhost:3000
```
## Authentication
All API endpoints (except `/health`, `/api/info`, and `/api/bootstrap/*`) require authentication via API key.
### API Key Types
1. **Master Keys** - Full admin access, never expire, can create/revoke other keys
2. **Project Keys** - Standard access for image generation, expire in 90 days
### Using API Keys
Include your API key in the `X-API-Key` header:
```bash
curl -X POST http://localhost:3000/api/generate \
-H "X-API-Key: bnt_your_key_here" \
-F "prompt=..." \
-F "filename=..."
```
### Getting Your First API Key
1. **Bootstrap** - Create initial master key (one-time only):
```bash
curl -X POST http://localhost:3000/api/bootstrap/initial-key
```
2. **Create Project Key** - Use master key to create project keys:
```bash
curl -X POST http://localhost:3000/api/admin/keys \
-H "X-API-Key: YOUR_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{"type": "project", "projectId": "my-project", "name": "My Project Key"}'
```
**Important:** Save keys securely when created - they cannot be retrieved later!
## Content Types
- **Request**: `multipart/form-data` for file uploads, `application/json` for JSON endpoints
- **Response**: `application/json`
## Rate Limits
All authenticated endpoints (those requiring API keys) are rate limited:
- **Per API Key:** 100 requests per hour
- **Applies to:**
- `POST /api/generate`
- `POST /api/text-to-image`
- `POST /api/upload`
- `POST /api/enhance`
- **Not rate limited:**
- Public endpoints (`GET /health`, `GET /api/info`)
- Bootstrap endpoint (`POST /api/bootstrap/initial-key`)
- Admin endpoints (require master key, but no rate limit)
- Image serving endpoints (`GET /api/images/:orgId/:projectId/:category/:filename`)
Rate limit information included in response headers:
- `X-RateLimit-Limit`: Maximum requests per window
- `X-RateLimit-Remaining`: Requests remaining
- `X-RateLimit-Reset`: When the limit resets (ISO 8601)
**429 Too Many Requests:** Returned when limit exceeded with `Retry-After` header
---
## Endpoints
### Overview
| Endpoint | Method | Authentication | Rate Limit | Description |
|----------|--------|----------------|------------|-------------|
| `/health` | GET | None | No | Health check |
| `/api/info` | GET | None | No | API information |
| `/api/bootstrap/initial-key` | POST | None (one-time) | No | Create first master key |
| `/api/admin/keys` | POST | Master Key | No | Create new API keys |
| `/api/admin/keys` | GET | Master Key | No | List all API keys |
| `/api/admin/keys/:keyId` | DELETE | Master Key | No | Revoke API key |
| `/api/generate` | POST | API Key | 100/hour | Generate images with files |
| `/api/text-to-image` | POST | API Key | 100/hour | Generate images (JSON only) |
| `/api/upload` | POST | API Key | 100/hour | Upload single image file |
| `/api/enhance` | POST | API Key | 100/hour | Enhance text prompts |
| `/api/images/:orgId/:projectId/:category/:filename` | GET | None | No | Serve specific image file |
| `/api/images/generated` | GET | API Key | 100/hour | List generated images |
---
### Authentication & Admin
#### `POST /api/bootstrap/initial-key`
Create the first master API key. This endpoint works only once when no keys exist.
**Authentication:** None required (public endpoint, one-time use)
**Response (201):**
```json
{
"apiKey": "bnt_...",
"type": "master",
"name": "Initial Master Key",
"expiresAt": null,
"message": "IMPORTANT: Save this key securely. You will not see it again!"
}
```
**Error (403):**
```json
{
"error": "Bootstrap not allowed",
"message": "API keys already exist. Use /api/admin/keys to create new keys."
}
```
---
#### `POST /api/admin/keys`
Create a new API key (master or project).
**Authentication:** Master key required via `X-API-Key` header
**Request Body:**
```json
{
"type": "master | project",
"projectId": "required-for-project-keys",
"name": "optional-friendly-name",
"expiresInDays": 90
}
```
**Response (201):**
```json
{
"apiKey": "bnt_...",
"metadata": {
"id": "uuid",
"type": "project",
"projectId": "my-project",
"name": "My Project Key",
"expiresAt": "2025-12-29T17:08:02.536Z",
"scopes": ["generate", "read"],
"createdAt": "2025-09-30T17:08:02.553Z"
},
"message": "IMPORTANT: Save this key securely. You will not see it again!"
}
```
---
#### `GET /api/admin/keys`
List all API keys.
**Authentication:** Master key required
**Response (200):**
```json
{
"keys": [
{
"id": "uuid",
"type": "master",
"projectId": null,
"name": "Initial Master Key",
"scopes": ["*"],
"isActive": true,
"createdAt": "2025-09-30T17:01:23.456Z",
"expiresAt": null,
"lastUsedAt": "2025-09-30T17:08:45.123Z",
"createdBy": null
}
],
"total": 1
}
```
---
#### `DELETE /api/admin/keys/:keyId`
Revoke an API key (soft delete).
**Authentication:** Master key required
**Response (200):**
```json
{
"message": "API key revoked successfully",
"keyId": "uuid"
}
```
---
### Health Check
#### `GET /health`
Health check endpoint with server status.
**Response:**
```json
{
"status": "healthy",
"timestamp": "2023-11-20T10:00:00.000Z",
"uptime": 12345.67,
"environment": "development",
"version": "1.0.0"
}
```
---
### API Information
#### `GET /api/info`
Returns API metadata and configuration limits.
**Response:**
```json
{
"name": "Banatie - Nano Banana Image Generation API",
"version": "1.0.0",
"description": "REST API service for AI-powered image generation using Gemini Flash Image model",
"endpoints": {
"GET /health": "Health check",
"GET /api/info": "API information",
"POST /api/generate": "Generate images from text prompt with optional reference images",
"POST /api/text-to-image": "Generate images from text prompt only (JSON)",
"POST /api/enhance": "Enhance and optimize prompts for better image generation"
},
"limits": {
"maxFileSize": "5MB",
"maxFiles": 3,
"supportedFormats": ["PNG", "JPEG", "JPG", "WebP"]
}
}
```
---
### Generate Image
#### `POST /api/generate`
Generate images from text prompts with optional reference images.
**Authentication:** API key required (master or project)
**Rate Limit:** 100 requests per hour per API key
**Content-Type:** `multipart/form-data`
**Parameters:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `prompt` | string | Yes | Text description of the image to generate (1-5000 chars) |
| `filename` | string | Yes | Desired filename for the generated image |
| `files` | file[] | No | Reference images (max 3 files, 5MB each) |
| `autoEnhance` | boolean | No | Enable automatic prompt enhancement |
| `enhancementOptions` | object | No | Enhancement configuration options |
**Enhancement Options:**
| Field | Type | Options | Default | Description |
|-------|------|---------|---------|-------------|
| `template` | string | `photorealistic`, `illustration`, `minimalist`, `sticker`, `product`, `comic`, `general` | `photorealistic` | Prompt engineering template to apply |
**Example Request:**
```bash
curl -X POST http://localhost:3000/api/generate \
-H "X-API-Key: bnt_your_api_key_here" \
-F "prompt=A majestic mountain landscape at sunset" \
-F "filename=mountain-sunset" \
-F "autoEnhance=true" \
-F "files=@reference1.jpg" \
-F "files=@reference2.png"
```
**Success Response (200):**
```json
{
"success": true,
"message": "Image generated successfully",
"data": {
"filename": "mountain-sunset-20231120-100000.png",
"filepath": "./results/mountain-sunset-20231120-100000.png",
"description": "Generated image description",
"model": "gemini-1.5-flash",
"generatedAt": "2023-11-20T10:00:00.000Z",
"promptEnhancement": {
"originalPrompt": "A mountain landscape",
"enhancedPrompt": "A majestic mountain landscape at golden hour with dramatic lighting",
"detectedLanguage": "en",
"appliedTemplate": "scenic_landscape",
"enhancements": ["lighting_enhancement", "composition_improvement"]
}
}
}
```
**Error Response (400/500):**
```json
{
"success": false,
"message": "Image generation failed",
"error": "Validation failed: Prompt is required"
}
```
---
### Text-to-Image (JSON)
#### `POST /api/text-to-image`
Generate images from text prompts only using JSON payload. Simplified endpoint for text-only requests without file uploads.
**Authentication:** API key required (master or project)
**Rate Limit:** 100 requests per hour per API key
**Content-Type:** `application/json`
**Request Body:**
```json
{
"prompt": "A beautiful sunset over mountains",
"filename": "sunset_image",
"aspectRatio": "16:9",
"autoEnhance": true,
"enhancementOptions": {
"template": "photorealistic",
"mood": "peaceful",
"lighting": "golden hour"
}
}
```
**Parameters:**
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `prompt` | string | Yes | - | Text description of the image to generate (3-2000 chars) |
| `filename` | string | Yes | - | Desired filename for the generated image (alphanumeric, underscore, hyphen only) |
| `aspectRatio` | string | No | `"1:1"` | Image aspect ratio (`"1:1"`, `"2:3"`, `"3:2"`, `"3:4"`, `"4:3"`, `"4:5"`, `"5:4"`, `"9:16"`, `"16:9"`, `"21:9"`) |
| `autoEnhance` | boolean | No | `true` | Enable automatic prompt enhancement (set to `false` to use prompt as-is) |
| `enhancementOptions` | object | No | - | Enhancement configuration options |
| `meta` | object | No | - | Metadata for request tracking |
**Enhancement Options:**
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `template` | string | No | `"photorealistic"` | Prompt engineering template: `"photorealistic"`, `"illustration"`, `"minimalist"`, `"sticker"`, `"product"`, `"comic"`, `"general"` |
**Meta Object:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `tags` | string[] | No | Array of string tags for tracking/grouping requests (not stored, only logged) |
**Example Request:**
```bash
curl -X POST http://localhost:3000/api/text-to-image \
-H "X-API-Key: bnt_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A beautiful sunset over mountains with golden clouds",
"filename": "test_sunset",
"aspectRatio": "16:9",
"autoEnhance": true,
"enhancementOptions": {
"template": "photorealistic"
},
"meta": {
"tags": ["demo", "sunset"]
}
}'
```
**Success Response (200):**
```json
{
"success": true,
"message": "Image generated successfully",
"data": {
"filename": "test_sunset.png",
"filepath": "results/test_sunset.png",
"description": "Here's a beautiful sunset over mountains with golden clouds for you!",
"model": "Nano Banana",
"generatedAt": "2025-09-26T15:04:27.705Z",
"promptEnhancement": {
"originalPrompt": "A beautiful sunset over mountains",
"enhancedPrompt": "A breathtaking photorealistic sunset over majestic mountains...",
"detectedLanguage": "English",
"appliedTemplate": "landscape",
"enhancements": ["lighting_enhancement", "composition_improvement"]
}
}
}
```
**Error Response (400/500):**
```json
{
"success": false,
"message": "Validation failed",
"error": "Prompt is required"
}
```
**Key Differences from /api/generate:**
- **JSON only**: No file upload support
- **Faster**: No multipart parsing overhead
- **Simpler testing**: Easy to use with curl or API clients
- **Same features**: Supports all enhancement options
- **Auto-enhance by default**: `autoEnhance` defaults to `true`, set explicitly to `false` to use prompt as-is
**Template Descriptions:**
- `photorealistic`: Photography-focused with camera angles, lens types, lighting, and fine details
- `illustration`: Art style specifications with line work, color palette, and shading techniques
- `minimalist`: Emphasis on negative space, simple composition, and subtle elements
- `sticker`: Bold outlines, kawaii style, clean design, transparent background style
- `product`: Studio lighting setups, commercial photography terms, surfaces, and angles
- `comic`: Panel style, art technique, mood, and dialogue/caption integration
- `general`: Balanced approach with clear descriptions and artistic detail
---
### Upload File
#### `POST /api/upload`
Upload a single image file to project storage.
**Authentication:** Project API key required (master keys not allowed)
**Rate Limit:** 100 requests per hour per API key
**Content-Type:** `multipart/form-data`
**Parameters:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `file` | file | Yes | Single image file (PNG, JPEG, JPG, WebP) |
| `metadata` | JSON | No | Optional metadata (description, tags) |
**File Specifications:**
- **Max file size:** 5MB
- **Supported formats:** PNG, JPEG, JPG, WebP
- **Max files per request:** 1
**Example Request:**
```bash
curl -X POST http://localhost:3000/api/upload \
-H "X-API-Key: bnt_your_project_key_here" \
-F "file=@image.png" \
-F 'metadata={"description":"Product photo","tags":["demo","test"]}'
```
**Success Response (200):**
```json
{
"success": true,
"message": "File uploaded successfully",
"data": {
"filename": "image-1728561234567-a1b2c3.png",
"originalName": "image.png",
"path": "org-slug/project-slug/uploads/image-1728561234567-a1b2c3.png",
"url": "http://localhost:3000/api/images/org-slug/project-slug/uploads/image-1728561234567-a1b2c3.png",
"size": 123456,
"contentType": "image/png",
"uploadedAt": "2025-10-10T12:00:00.000Z"
}
}
```
**Error Response (400 - No file):**
```json
{
"success": false,
"message": "File upload failed",
"error": "No file provided"
}
```
**Error Response (400 - Invalid file type):**
```json
{
"success": false,
"message": "File validation failed",
"error": "Unsupported file type: image/gif. Allowed: PNG, JPEG, WebP"
}
```
**Error Response (400 - File too large):**
```json
{
"success": false,
"message": "File upload failed",
"error": "File too large. Maximum size: 5MB"
}
```
**Storage Details:**
- Files are stored in MinIO under: `{orgSlug}/{projectSlug}/uploads/`
- Filenames are automatically made unique with timestamp and random suffix
- Original filename is preserved in response
- Uploaded files can be accessed via the returned URL
---
### Enhance Prompt
#### `POST /api/enhance`
Enhance and optimize text prompts for better image generation results.
**Authentication:** API key required (master or project)
**Rate Limit:** 100 requests per hour per API key
**Content-Type:** `application/json`
**Request Body:**
```json
{
"prompt": "A mountain landscape",
"options": {
"imageStyle": "photorealistic",
"aspectRatio": "landscape",
"mood": "serene and peaceful",
"lighting": "golden hour",
"cameraAngle": "wide shot",
"outputFormat": "detailed",
"negativePrompts": ["blurry", "low quality"]
}
}
```
**Parameters:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `prompt` | string | Yes | Original text prompt (1-5000 chars) |
| `options` | object | No | Enhancement configuration |
**Success Response (200):**
```json
{
"success": true,
"originalPrompt": "A mountain landscape",
"enhancedPrompt": "A breathtaking photorealistic mountain landscape during golden hour, featuring dramatic peaks and valleys with warm, soft lighting creating a serene and peaceful atmosphere, captured in a wide shot composition with rich detail and depth",
"detectedLanguage": "en",
"appliedTemplate": "scenic_landscape",
"metadata": {
"style": "photorealistic",
"aspectRatio": "landscape",
"enhancements": [
"lighting_enhancement",
"composition_improvement",
"atmosphere_addition",
"detail_specification"
]
}
}
```
**Error Response (400/500):**
```json
{
"success": false,
"originalPrompt": "A mountain landscape",
"error": "Validation failed: Prompt is required"
}
```
---
## Error Codes
| Code | Description |
|------|-------------|
| 400 | Bad Request - Invalid parameters or validation failure |
| 401 | Unauthorized - Missing, invalid, expired, or revoked API key |
| 403 | Forbidden - Insufficient permissions (e.g., master key required) |
| 404 | Not Found - Endpoint or resource does not exist |
| 429 | Too Many Requests - Rate limit exceeded |
| 500 | Internal Server Error - Server configuration or processing error |
## Common Error Messages
### Authentication Errors (401)
- `"Missing API key"` - No X-API-Key header provided
- `"Invalid API key"` - The provided API key is invalid, expired, or revoked
- **Affected endpoints:** `/api/generate`, `/api/text-to-image`, `/api/upload`, `/api/enhance`, `/api/admin/*`
### Authorization Errors (403)
- `"Master key required"` - This endpoint requires a master API key (not project key)
- `"Bootstrap not allowed"` - API keys already exist, cannot bootstrap again
- **Affected endpoints:** `/api/admin/*`, `/api/bootstrap/initial-key`
### Validation Errors (400)
- `"Prompt is required"` - Missing or empty prompt parameter
- `"Reference image validation failed"` - Invalid file format or size
- `"Validation failed"` - Parameter validation error
### Rate Limiting Errors (429)
- `"Rate limit exceeded"` - Too many requests, retry after specified time
- **Applies to:** `/api/generate`, `/api/text-to-image`, `/api/upload`, `/api/enhance`
- **Rate limit:** 100 requests per hour per API key
- **Response includes:** `Retry-After` header with seconds until reset
### Server Errors
- `"Server configuration error"` - Missing GEMINI_API_KEY or database connection
- `"Image generation failed"` - AI service error
- `"Authentication failed"` - Error during authentication process
---
## File Upload Specifications
**Supported Formats:** PNG, JPEG, JPG, WebP
**Maximum File Size:** 5MB per file
**Maximum Files:** 3 files per request
**Storage:** Temporary files in `./uploads/temp`, results in `./results`
## Request Headers
| Header | Value | Description |
|--------|-------|-------------|
| `X-API-Key` | string | API key for authentication (required for most endpoints) |
| `X-Request-ID` | string | Unique request identifier (auto-generated by server) |
## Response Headers
| Header | Description |
|--------|-------------|
| `X-Request-ID` | Request identifier for tracking |
| `X-RateLimit-Limit` | Maximum requests allowed per window |
| `X-RateLimit-Remaining` | Requests remaining in current window |
| `X-RateLimit-Reset` | When the rate limit resets (ISO 8601) |
## CORS
Cross-origin requests supported from:
- `http://localhost:3001` (Landing Page)
- `http://localhost:3002` (Studio Platform)
- `http://localhost:3003` (Admin Dashboard)
Configure additional origins via `CORS_ORIGIN` environment variable.

173
docs/api/admin.md Normal file
View File

@ -0,0 +1,173 @@
# Banatie API - Administration & Authentication
## Authentication Overview
All API endpoints (except public endpoints and bootstrap) require authentication via API key in the `X-API-Key` header.
### API Key Types
**Master Keys**
- Full administrative access
- Never expire
- Can create and revoke other API keys
- Access to all admin endpoints
**Project Keys**
- Standard access for image generation
- Expire in 90 days by default
- Scoped to specific organization and project
- Rate limited (100 requests/hour)
### Header Format
```
X-API-Key: bnt_your_key_here
```
---
## Public Endpoints
### GET /health
Health check with server status.
**Authentication:** None
**Purpose:** Monitor API availability and uptime
**Returns:** Status, timestamp, uptime, environment, version
---
### GET /api/info
API information and configuration limits.
**Authentication:** Optional (returns key info if authenticated)
**Purpose:** Discover API capabilities and limits
**Returns:** API name, version, endpoints list, file size/format limits
---
## Bootstrap Endpoint
### POST /api/bootstrap/initial-key
Create the first master API key (one-time only).
**Authentication:** None (public, works only when database is empty)
**Purpose:** Initialize the API with first master key
**Notes:**
- Only works when no API keys exist in database
- Returns master key value (save securely, shown only once)
- Subsequent calls return 403 Forbidden
---
## API Key Management
All endpoints require Master Key authentication.
### POST /api/admin/keys
Create new API key (master or project).
**Authentication:** Master Key required
**Parameters:**
- `type` - "master" or "project" (required)
- `projectId` - Project identifier (required for project keys)
- `organizationId` - Organization UUID (optional, auto-created)
- `organizationSlug` - Organization slug (optional, auto-created)
- `projectSlug` - Project slug (optional, auto-created)
- `name` - Friendly name for the key (optional)
- `expiresInDays` - Expiration days (optional, default: 90 for project keys)
**Purpose:** Generate new API keys for projects or admin users
**Notes:**
- Automatically creates organization and project if they don't exist
- Returns API key value (save securely, shown only once)
- Master keys never expire, project keys expire in 90 days by default
---
### GET /api/admin/keys
List all API keys.
**Authentication:** Master Key required
**Purpose:** View all active and inactive API keys
**Returns:** Array of all keys with metadata (no sensitive key values), includes organization and project details
**Notes:**
- Shows all keys regardless of active status
- Includes last used timestamp
- Does not return actual API key values (hashed in database)
---
### DELETE /api/admin/keys/:keyId
Revoke an API key.
**Authentication:** Master Key required
**Parameters:**
- `keyId` - UUID of the key to revoke (path parameter)
**Purpose:** Deactivate an API key (soft delete)
**Notes:**
- Soft delete via `is_active` flag
- Revoked keys cannot be reactivated
- Key remains in database for audit trail
---
## Rate Limiting
Rate limits apply per API key to protected endpoints.
**Limits:**
- **Project Keys:** 100 requests per hour
- **Master Keys:** No rate limit on admin endpoints
**Affected Endpoints:**
- All `/api/v1/generations` endpoints
- All `/api/v1/images` endpoints
- All `/api/v1/flows` endpoints
- `/api/v1/live` generation endpoint
**Response Headers:**
- `X-RateLimit-Limit` - Maximum requests per window
- `X-RateLimit-Remaining` - Requests remaining
- `X-RateLimit-Reset` - Reset timestamp (ISO 8601)
**429 Too Many Requests:**
- Returned when limit exceeded
- Includes `Retry-After` header (seconds until reset)
---
## Error Codes
| Code | Description |
|------|-------------|
| 401 | Unauthorized - Missing, invalid, expired, or revoked API key |
| 403 | Forbidden - Insufficient permissions (master key required) |
| 429 | Too Many Requests - Rate limit exceeded |
**Common Error Messages:**
- `"Missing API key"` - No X-API-Key header provided
- `"Invalid API key"` - Key is invalid, expired, or revoked
- `"Master key required"` - Endpoint requires master key, project key insufficient
- `"Bootstrap not allowed"` - Keys already exist, cannot bootstrap again
- `"Rate limit exceeded"` - Too many requests, retry after specified time

View File

@ -0,0 +1,422 @@
# Banatie API - Image Generation (v1)
All endpoints require Project Key authentication via `X-API-Key` header and are rate-limited to 100 requests/hour.
---
## Generations
### POST /api/v1/generations
Create new image generation with optional reference images and flow support.
**Authentication:** Project Key required
**Parameters:**
- `prompt` - Text description for image (required)
- `referenceImages` - Array of image references (aliases or image IDs)
- `aspectRatio` - Image aspect ratio (e.g., "16:9", "1:1")
- `flowId` - Associate generation with a flow (UUID)
- `assignAlias` - Assign project-level alias to output image
- `assignFlowAlias` - Assign flow-level alias to output image
- `autoEnhance` - Enable prompt enhancement (boolean)
- `meta` - Custom metadata (JSON object)
**Purpose:** Generate AI images with reference support and automatic alias assignment
// TODO: change assignAlias to alias, assignFlowAlias to flowAlias
---
### GET /api/v1/generations
List generations with filtering and pagination.
**Authentication:** Project Key required
**Query Parameters:**
- `flowId` - Filter by flow (UUID)
- `status` - Filter by status (pending/processing/success/failed)
- `limit` - Results per page (default: 20, max: 100)
- `offset` - Pagination offset (default: 0)
- `includeDeleted` - Include soft-deleted records (boolean)
**Purpose:** Browse generation history with optional filters
---
### GET /api/v1/generations/:id
Get single generation with full details.
**Authentication:** Project Key required
**Parameters:**
- `id` - Generation UUID (path parameter)
**Purpose:** View complete generation details including output and reference images
---
### POST /api/v1/generations/:id/retry
Retry a failed generation.
// TODO: the main purpose of this to regenerate an image, e.g. refresh, or reflect some shared project settings like styles or aliases. It's not for generating failed generations. Not sure we need to allow alter prompt or aspectRatio
**Authentication:** Project Key required
**Parameters:**
- `id` - Generation UUID (path parameter)
- `prompt` - Override original prompt (optional)
- `aspectRatio` - Override aspect ratio (optional)
**Purpose:** Recreate a failed generation with optional parameter overrides
---
### DELETE /api/v1/generations/:id
Delete generation and its output image.
**Authentication:** Project Key required
**Parameters:**
- `id` - Generation UUID (path parameter)
**Purpose:** Remove generation record and associated output image (soft delete)
---
## Flows
Flows organize related generations into chains and support flow-scoped aliases.
### POST /api/v1/flows
Create new flow.
// TODO: each generation without flowId specified should start a new flow. We don't need a separate create flow endpoint
**Authentication:** Project Key required
**Parameters:**
- `meta` - Custom metadata (JSON object, optional)
**Purpose:** Initialize a new generation chain/workflow
---
### GET /api/v1/flows
List all flows with pagination.
**Authentication:** Project Key required
**Query Parameters:**
- `limit` - Results per page (default: 20, max: 100)
- `offset` - Pagination offset (default: 0)
**Purpose:** Browse all flows with computed generation and image counts
---
### GET /api/v1/flows/:id
Get single flow with details.
**Authentication:** Project Key required
**Parameters:**
- `id` - Flow UUID (path parameter)
**Purpose:** View flow metadata, aliases, and computed counts
---
### GET /api/v1/flows/:id/generations
List all generations in a flow.
**Authentication:** Project Key required
**Parameters:**
- `id` - Flow UUID (path parameter)
**Query Parameters:**
- `limit` - Results per page (default: 20, max: 100)
- `offset` - Pagination offset (default: 0)
**Purpose:** View all generations associated with this flow
---
### GET /api/v1/flows/:id/images
List all images in a flow.
**Authentication:** Project Key required
**Parameters:**
- `id` - Flow UUID (path parameter)
**Query Parameters:**
- `limit` - Results per page (default: 20, max: 100)
- `offset` - Pagination offset (default: 0)
**Purpose:** View all images (generated and uploaded) associated with this flow
---
### PUT /api/v1/flows/:id/aliases
Update flow aliases.
**Authentication:** Project Key required
**Parameters:**
- `id` - Flow UUID (path parameter)
- `aliases` - Object mapping alias names to image IDs (request body)
**Purpose:** Add or update flow-scoped aliases for image referencing
**Notes:**
- Merges with existing aliases
- Aliases must map to valid image IDs
---
### DELETE /api/v1/flows/:id/aliases/:alias
Remove specific flow alias.
**Authentication:** Project Key required
**Parameters:**
- `id` - Flow UUID (path parameter)
- `alias` - Alias name to remove (path parameter)
**Purpose:** Delete a single alias from flow's alias map
---
### DELETE /api/v1/flows/:id
Delete flow.
**Authentication:** Project Key required
**Parameters:**
- `id` - Flow UUID (path parameter)
**Purpose:** Remove flow (hard delete, generations and images remain)
---
## Images
Database-tracked image management with upload, listing, and metadata updates.
### POST /api/v1/images/upload
Upload image file with database tracking.
**Authentication:** Project Key required
**Form Parameters:**
- `file` - Image file (required, max 5MB, PNG/JPEG/WebP)
- `alias` - Project-level alias (optional)
- `flowId` - Associate with flow (UUID, optional)
- `meta` - Custom metadata (JSON object, optional)
**Purpose:** Upload image with automatic database record creation and storage
**Notes:**
- Creates both MinIO storage file and database entry
- Supports PNG, JPEG, JPG, WebP formats
- Maximum file size: 5MB
// TODO: need to add flowAlias param
---
### GET /api/v1/images
List images with filtering and pagination.
**Authentication:** Project Key required
**Query Parameters:**
- `flowId` - Filter by flow (UUID)
- `source` - Filter by source (generated/uploaded)
- `alias` - Filter by project alias
- `limit` - Results per page (default: 20, max: 100)
- `offset` - Pagination offset (default: 0)
- `includeDeleted` - Include soft-deleted records (boolean)
**Purpose:** Browse image library with optional filters
---
### GET /api/v1/images/resolve/:alias
Resolve alias to image using 3-tier precedence.
**Authentication:** Project Key required
**Parameters:**
- `alias` - Alias to resolve (path parameter)
**Query Parameters:**
- `flowId` - Flow context for resolution (UUID, optional)
**Purpose:** Lookup image by alias with technical → flow → project precedence
**Notes:**
- Technical aliases: @last, @first, @upload (computed)
- Flow aliases: Scoped to specific flow
- Project aliases: Global within project
- Returns image record and resolution metadata (scope, flowId)
---
### GET /api/v1/images/:id
Get single image by ID.
**Authentication:** Project Key required
**Parameters:**
- `id` - Image UUID (path parameter)
**Purpose:** View complete image metadata and details
---
### PUT /api/v1/images/:id
Update image metadata.
**Authentication:** Project Key required
**Parameters:**
- `id` - Image UUID (path parameter)
- `alias` - Update project alias (optional)
- `focalPoint` - Update focal point coordinates (object: {x, y}, optional)
- `meta` - Update custom metadata (JSON object, optional)
**Purpose:** Modify image metadata fields
// TODO: should be a way to remove alias from an image
---
### PUT /api/v1/images/:id/alias
Assign or update project-scoped alias.
**Authentication:** Project Key required
**Parameters:**
- `id` - Image UUID (path parameter)
- `alias` - Alias name (string, required in request body)
**Purpose:** Set project-level alias for image referencing
**Notes:**
- Validates alias format and reserved names
- Checks for conflicts with existing aliases
// TODO: why we need this if we can do it with `PUT /api/v1/images/:id`?
---
### DELETE /api/v1/images/:id
Soft delete image.
**Authentication:** Project Key required
**Parameters:**
- `id` - Image UUID (path parameter)
**Purpose:** Mark image as deleted without removing from storage
**Notes:**
- Sets deletedAt timestamp
- Image remains in storage
- Excluded from default queries
// TODO: why "soft" delete? did we discuss "soft" way and how to actually delete the image then?
---
## Live Generation
### GET /api/v1/live
Generate image with prompt-based caching.
**Authentication:** Project Key required
**Query Parameters:**
- `prompt` - Text description for image (required)
- `aspectRatio` - Image aspect ratio (optional)
**Purpose:** Generate images with intelligent caching based on prompt hash
**Response Format:** Raw image bytes (not JSON)
**Response Headers:**
- `Content-Type` - image/jpeg (or appropriate MIME type)
- `X-Cache-Status` - HIT or MISS
- `X-Image-Id` - Image database UUID
- `X-Generation-Id` - Generation UUID (on cache MISS)
- `X-Cache-Hit-Count` - Number of cache hits (on cache HIT)
- `Cache-Control` - public, max-age=31536000
**Caching Behavior:**
- **Cache HIT:** Returns existing cached image from storage
- **Cache MISS:** Generates new image, caches it, returns bytes
- Cache key: SHA-256 hash of prompt
- Cache lookup scoped to project
// TODO: we can't pass apikey in query param because it's assumed those images are public available on the generated pages. So we need another way to protect this endpoint and also to protect clients from using their credits
---
## Alias System
The v1 API supports a 3-tier alias resolution system:
**Technical Aliases** (Computed)
- `@last` - Most recently generated image in project
- `@first` - First generated image in project
- `@upload` - Most recently uploaded image in project
**Flow Aliases** (Flow-scoped)
- Stored in flow's aliases JSON field
- Only accessible within flow context
- Set via `PUT /api/v1/flows/:id/aliases`
**Project Aliases** (Global)
- Unique within project
- Accessible across all flows
- Set via `PUT /api/v1/images/:id/alias` or generation parameters
**Resolution Order:**
1. Technical aliases (if matches @last, @first, @upload)
2. Flow aliases (if flowId provided in context)
3. Project aliases (global lookup)
---
## Error Codes
| Code | Description |
|------|-------------|
| 400 | Bad Request - Invalid parameters or validation failure |
| 401 | Unauthorized - Missing, invalid, expired, or revoked API key |
| 404 | Not Found - Resource does not exist |
| 429 | Too Many Requests - Rate limit exceeded |
| 500 | Internal Server Error - Processing or generation failure |
**Common Error Messages:**
- `"Prompt is required"` - Missing prompt parameter
- `"Flow not found"` - Invalid flowId
- `"Image not found"` - Invalid image ID or alias
- `"Alias already exists"` - Alias conflict in project
- `"Invalid aspect ratio"` - Unsupported aspect ratio format
- `"File too large"` - Upload exceeds 5MB limit