banatie-service/docs/api/image-generation.md

806 lines
24 KiB
Markdown

# 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, aliases, and auto-enhancement.
**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", "3:2", "9:16", default: "1:1")
- `flowId` - Associate generation with a flow (UUID)
- `alias` - Assign project-scoped alias to output image (@custom-name)
- `flowAlias` - Assign flow-scoped alias to output image (requires flowId)
- `autoEnhance` - Enable prompt enhancement (boolean, default: true)
- `enhancementOptions` - Enhancement configuration (object, optional)
- `template` - Enhancement template: "photorealistic", "illustration", "minimalist", "sticker", "product", "comic", "general"
- `meta` - Custom metadata (JSON object)
**Purpose:** Generate AI images with reference support and automatic alias assignment
**Response:** 201 Created with generation details, status, and output image
---
### 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, default: false)
**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 image, reference images, flow association, and timestamps
---
### PUT /api/v1/generations/:id
Update generation parameters with automatic regeneration.
**Authentication:** Project Key required
**Parameters:**
- `id` - Generation UUID (path parameter)
- `prompt` - New prompt (triggers regeneration)
- `aspectRatio` - New aspect ratio (triggers regeneration)
- `flowId` - Change flow association (null to detach, no regeneration)
- `meta` - Update custom metadata (no regeneration)
**Purpose:** Update generation settings with intelligent regeneration behavior
**Notes:**
- Changing `prompt` or `aspectRatio` triggers automatic regeneration
- Changing `flowId` or `meta` updates metadata only (no regeneration)
- Regeneration replaces existing output image (preserves ID and URLs)
---
### POST /api/v1/generations/:id/regenerate
Regenerate existing generation with exact same parameters.
**Authentication:** Project Key required
**Parameters:**
- `id` - Generation UUID (path parameter)
**Purpose:** Recreate image using original parameters (prompt, aspect ratio, references)
**Notes:**
- Uses exact same parameters as original generation
- Works regardless of current status (success, failed, pending)
- Replaces existing output image (preserves ID and URLs)
- No parameter modifications allowed (use PUT for changes)
- Useful for refreshing stale images or recovering from failures
---
### POST /api/v1/generations/:id/retry
**DEPRECATED:** Use POST /api/v1/generations/:id/regenerate instead
Legacy endpoint maintained for backward compatibility. Delegates to /regenerate endpoint.
---
### 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
**Notes:**
- Soft delete generation record (sets deletedAt timestamp)
- Hard delete output image if no project/flow aliases exist
- Soft delete output image if aliases exist (preserves for CDN access)
- Cascades to remove generation-image relationships
---
## Flows
Flows organize related generations into chains and support flow-scoped aliases. Flows are created automatically when generations or uploads specify a flowId.
### 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
**Notes:**
- Flows are created automatically when:
- A generation/upload specifies a flowId
- A generation/upload provides a flowAlias (eager creation)
---
### 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 (generationCount, imageCount)
---
### 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, ordered by creation date (newest first)
---
### 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, ordered by creation date (newest first)
---
### 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 (does not replace all)
- Aliases must map to valid image IDs
- Aliases are stored in JSONB field for efficient lookups
---
### 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, e.g., "@hero")
**Purpose:** Delete a single alias from flow's alias map, other aliases remain unchanged
---
### POST /api/v1/flows/:id/regenerate
Regenerate the most recent generation in a flow.
**Authentication:** Project Key required
**Parameters:**
- `id` - Flow UUID (path parameter)
**Purpose:** Regenerate the latest generation in the flow
**Notes:**
- Identifies the most recent generation (ordered by creation date)
- Uses exact same parameters from original generation
- Returns error if flow has no generations
- Replaces existing output image (preserves ID and URLs)
---
### DELETE /api/v1/flows/:id
Delete flow.
**Authentication:** Project Key required
**Parameters:**
- `id` - Flow UUID (path parameter)
**Purpose:** Remove flow (hard delete)
**Notes:**
- Flow record is hard deleted (no soft delete)
- Generations remain intact (not cascaded)
- Images remain intact (not cascaded)
- Flow-scoped aliases are removed with flow
- Generations and images lose their flow association but remain accessible
---
## Images
Database-tracked image management with upload, listing, metadata updates, and deletion.
### POST /api/v1/images/upload
Upload image file with database tracking.
**Authentication:** Project Key required
**Form Parameters (multipart/form-data):**
- `file` - Image file (required, max 5MB, PNG/JPEG/WebP)
- `alias` - Project-scoped alias (optional, e.g., "@logo")
- `flowId` - Associate with flow (UUID, optional)
- `flowAlias` - Flow-scoped alias (optional, requires flowId, triggers eager creation)
- `meta` - Custom metadata (JSON string, optional)
**Purpose:** Upload image with automatic database record creation and storage
**FlowId Behavior:**
- `undefined` (not provided) → generates new UUID for automatic flow creation
- `null` (explicitly null) → no flow association
- `string` (specific value) → uses provided flow ID
**Notes:**
- Creates both MinIO storage file and database entry
- Supports PNG, JPEG, JPG, WebP formats
- Maximum file size: 5MB
- Eager flow creation when flowAlias is provided
---
### 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 (exact match)
- `limit` - Results per page (default: 20, max: 100)
- `offset` - Pagination offset (default: 0)
- `includeDeleted` - Include soft-deleted records (boolean, default: false)
**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, e.g., "@hero", "@last")
**Query Parameters:**
- `flowId` - Flow context for resolution (UUID, optional)
**Purpose:** Lookup image by alias with technical → flow → project precedence
**Resolution Order:**
1. Technical aliases (if matches @last, @first, @upload) - computed on-the-fly
2. Flow aliases (if flowId provided) - looked up in flow's JSONB aliases field
3. Project aliases (global) - looked up in images.alias column
**Returns:** Image record with resolution metadata (imageId, scope, flowId, image details)
---
### 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 including storage URLs, project/flow associations, alias, source, file metadata, focal point, and custom metadata
---
### PUT /api/v1/images/:id
Update image metadata.
**Authentication:** Project Key required
**Parameters:**
- `id` - Image UUID (path parameter)
- `focalPoint` - Update focal point coordinates (object: {x: 0.0-1.0, y: 0.0-1.0}, optional)
- `meta` - Update custom metadata (JSON object, optional)
**Purpose:** Modify non-generative image properties
**Notes:**
- Alias assignment moved to separate endpoint PUT /images/:id/alias
- Focal point used for image cropping
---
### 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, e.g., "@hero-bg")
**Purpose:** Set project-level alias for image referencing
**Notes:**
- Alias must start with @ symbol
- Must be unique within the project
- Validates alias format and reserved names
- Checks for conflicts with existing aliases
- Replaces existing alias if image already has one
---
### DELETE /api/v1/images/:id
Delete image with storage cleanup.
**Authentication:** Project Key required
**Parameters:**
- `id` - Image UUID (path parameter)
**Purpose:** Permanently remove image and its storage file
**Notes:**
- Hard delete of image record (no soft delete)
- Removes file from MinIO storage permanently
- Cascades to delete generation-image relationships
- Removes image from flow aliases (if present)
- Cannot be undone - use with caution
---
## CDN Endpoints
Public endpoints for serving images and live URL generation without authentication.
### GET /cdn/:orgSlug/:projectSlug/img/:filenameOrAlias
Serve images by filename or project-scoped alias via public CDN.
**Authentication:** None - Public endpoint
**Parameters:**
- `orgSlug` - Organization slug (path parameter)
- `projectSlug` - Project slug (path parameter)
- `filenameOrAlias` - Filename or @alias (path parameter)
**Purpose:** Public image serving for websites and applications
**Response Format:** Raw image bytes (not JSON)
**Response Headers:**
- `Content-Type` - image/jpeg (or appropriate MIME type)
- `Content-Length` - Actual byte length
- `Cache-Control` - public, max-age=31536000 (1 year)
- `X-Image-Id` - Image database UUID
**Access Methods:**
- Filename: `GET /cdn/acme/website/img/hero-background.jpg`
- Alias: `GET /cdn/acme/website/img/@hero`
---
### GET /cdn/:orgSlug/:projectSlug/live/:scope
Live URL generation with automatic caching and scope management.
**Authentication:** None - Public endpoint
**Rate Limit:** 10 new generations per hour per IP (cache hits excluded)
**Parameters:**
- `orgSlug` - Organization slug (path parameter)
- `projectSlug` - Project slug (path parameter)
- `scope` - Scope identifier (path parameter, alphanumeric + hyphens + underscores)
**Query Parameters:**
- `prompt` - Image description (required)
- `aspectRatio` - Image aspect ratio (optional, default: "1:1")
- `autoEnhance` - Enable prompt enhancement (boolean, optional)
- `template` - Enhancement template (optional): photorealistic, illustration, minimalist, sticker, product, comic, general
**Purpose:** On-demand image generation via URL parameters for dynamic content
**Response Format:** Raw image bytes (not JSON)
**Response Headers (Cache HIT):**
- `Content-Type` - image/jpeg
- `Content-Length` - Actual byte length
- `Cache-Control` - public, max-age=31536000
- `X-Cache-Status` - HIT
- `X-Scope` - Scope identifier
- `X-Image-Id` - Image UUID
**Response Headers (Cache MISS):**
- `Content-Type` - image/jpeg
- `Content-Length` - Actual byte length
- `Cache-Control` - public, max-age=31536000
- `X-Cache-Status` - MISS
- `X-Scope` - Scope identifier
- `X-Generation-Id` - Generation UUID
- `X-Image-Id` - Image UUID
- `X-RateLimit-Limit` - 10
- `X-RateLimit-Remaining` - Remaining requests
- `X-RateLimit-Reset` - Seconds until reset
**Caching Behavior:**
- **Cache HIT:** Returns existing image instantly, no rate limit check
- **Cache MISS:** Generates new image, counts toward IP rate limit
- Cache key computed from: prompt + aspectRatio + autoEnhance + template
- Cached images stored with meta.isLiveUrl = true
**Scope Management:**
- Scopes separate generation budgets (e.g., "hero-section", "gallery")
- Auto-created on first use if allowNewLiveScopes = true
- Generation limits per scope (default: 30)
- Scope stats tracked (currentGenerations, lastGeneratedAt)
**IP Rate Limiting:**
- 10 new generations per hour per IP address
- Separate from API key rate limits
- Cache hits do NOT count toward limit
- Only new generations (cache MISS) count
- Supports X-Forwarded-For header for proxy setups
**Example:**
```
GET /cdn/acme/website/live/hero-section?prompt=mountain+landscape&aspectRatio=16:9
```
---
## Live Scopes Management
Authenticated endpoints for managing live URL scopes. All require Project Key authentication.
### POST /api/v1/live/scopes
Create new live scope manually with settings.
**Authentication:** Project Key required
**Parameters:**
- `slug` - Unique scope identifier (required, alphanumeric + hyphens + underscores)
- `allowNewGenerations` - Allow new generations in scope (boolean, default: true)
- `newGenerationsLimit` - Maximum generations allowed (number, default: 30)
- `meta` - Custom metadata (JSON object, optional)
**Purpose:** Pre-configure scope with specific settings before first use
**Notes:**
- Scopes are typically auto-created via live URLs
- Slug must be unique within the project
- Slug format: alphanumeric + hyphens + underscores only
---
### GET /api/v1/live/scopes
List all live scopes with pagination and statistics.
**Authentication:** Project Key required
**Query Parameters:**
- `slug` - Filter by exact slug match (optional)
- `limit` - Results per page (default: 20, max: 100)
- `offset` - Pagination offset (default: 0)
**Purpose:** Browse all scopes (both auto-created and manually created)
**Returns:** Scopes with currentGenerations count, lastGeneratedAt, settings, and metadata
---
### GET /api/v1/live/scopes/:slug
Get single live scope by slug with complete statistics.
**Authentication:** Project Key required
**Parameters:**
- `slug` - Scope slug identifier (path parameter)
**Purpose:** View detailed scope information including generation count, last generation timestamp, settings, and metadata
---
### PUT /api/v1/live/scopes/:slug
Update live scope settings and metadata.
**Authentication:** Project Key required
**Parameters:**
- `slug` - Scope slug identifier (path parameter)
- `allowNewGenerations` - Allow/disallow new generations (boolean, optional)
- `newGenerationsLimit` - Update generation limit (number, optional)
- `meta` - Update custom metadata (JSON object, optional)
**Purpose:** Modify scope configuration
**Notes:**
- Changes take effect immediately for new live URL requests
---
### POST /api/v1/live/scopes/:slug/regenerate
Regenerate images in a live scope.
**Authentication:** Project Key required
**Parameters:**
- `slug` - Scope slug identifier (path parameter)
- `imageId` - Specific image to regenerate (UUID, optional in request body)
**Purpose:** Regenerate either a specific image or all images in the scope
**Behavior:**
- If `imageId` provided: Regenerates specific image only
- If `imageId` omitted: Regenerates all images in scope
- Uses exact same parameters (prompt, aspect ratio, etc.)
- Updates existing images (preserves IDs and URLs)
- Verifies image belongs to scope before regenerating
**Notes:**
- Useful for refreshing stale cached images or recovering from failures
---
### DELETE /api/v1/live/scopes/:slug
Delete live scope with cascading image deletion.
**Authentication:** Project Key required
**Parameters:**
- `slug` - Scope slug identifier (path parameter)
**Purpose:** Permanently remove scope and all cached live URL images
**Notes:**
- Hard deletes all images in scope (MinIO + database)
- Follows alias protection rules for each image
- Hard deletes scope record (no soft delete)
- Cannot be undone - use with caution
---
## Alias System
The v1 API supports a 3-tier alias resolution system for referencing images.
**Alias Format Requirements:**
- All aliases MUST start with `@` symbol
- Pattern: `@[a-zA-Z0-9_-]+` (alphanumeric, underscore, hyphen)
- Maximum length: 50 characters
- Examples: `@hero`, `@product-main`, `@image_1`
**Technical Aliases** (Computed, Reserved)
- `@last` - Most recently generated image in project
- `@first` - First generated image in project
- `@upload` - Most recently uploaded image in project
**Reserved Aliases** (Cannot be used)
- Technical aliases: `@last`, `@first`, `@upload`
- Future reserved: `@all`, `@latest`, `@oldest`, `@random`, `@next`, `@prev`, `@previous`
**Flow Aliases** (Flow-scoped)
- Stored in flow's aliases JSONB field
- Only accessible within flow context
- Set via `PUT /api/v1/flows/:id/aliases`
- Example: `@hero` in flow A is different from `@hero` in flow B
**Project Aliases** (Global)
- Unique within project
- Accessible across all flows
- Set via `PUT /api/v1/images/:id/alias` or generation/upload parameters
- Example: `@logo` is the same image across entire project
**Resolution Order:**
1. Technical aliases (if matches @last, @first, @upload)
2. Flow aliases (if flowId provided in context)
3. Project aliases (global lookup)
---
## Response Formats
### Generation Response
Generation responses include fields for prompt enhancement tracking:
```json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"projectId": "57c7f7f4d-47de-4d70-9ebd-3807a0b63746",
"prompt": "A photorealistic establishing shot of a luxurious motor yacht...",
"originalPrompt": "шикарная моторная яхта движется по живописному озеру...",
"autoEnhance": true,
"aspectRatio": "16:9",
"status": "success",
"outputImageId": "7c4ccf47-41ce-4718-afbc-8c553b2c631a",
"outputImage": { ... },
"referenceImages": [],
"flowId": null,
"processingTimeMs": 8980,
"cost": null,
"retryCount": 0,
"errorMessage": null,
"meta": {},
"createdAt": "2025-11-23T13:47:00.127Z",
"updatedAt": "2025-11-23T13:47:09.107Z"
}
```
**Prompt Enhancement Fields:**
- `prompt` - The actual prompt used for generation (enhanced if `autoEnhance: true`, original if `autoEnhance: false`)
- `originalPrompt` - The user's original input prompt (always populated for transparency)
- `autoEnhance` - Boolean indicating if prompt enhancement was applied
**Semantics:**
- When `autoEnhance: true`:
- `originalPrompt` = user's original input
- `prompt` = AI-enhanced version used for generation
- Example: Original "a cat" → Enhanced "A photorealistic close-up portrait of a cat..."
- When `autoEnhance: false`:
- `originalPrompt` = user's original input
- `prompt` = same as originalPrompt (no enhancement)
- Both fields contain identical values
**Default Behavior:** `autoEnhance` defaults to `true` if not explicitly set to `false`.
---
### Image Response
Image responses include actual dimensions and storage access:
```json
{
"id": "7c4ccf47-41ce-4718-afbc-8c553b2c631a",
"projectId": "57c7f7f4d-47de-4d70-9ebd-3807a0b63746",
"flowId": null,
"storageKey": "default/57c7f7f4d-47de-4d70-9ebd-3807a0b63746/generated/2025-11/gen_fd14839b.png",
"storageUrl": "http://localhost:9000/banatie/default/57c7f7f4d-47de-4d70-9ebd-3807a0b63746/generated/gen_fd14839b.png",
"mimeType": "image/jpeg",
"fileSize": 1909246,
"width": 1792,
"height": 1024,
"source": "generated",
"alias": null,
"focalPoint": null,
"fileHash": null,
"generationId": "fd14839b-d42e-4be9-93b3-e2fb67f7af0d",
"apiKeyId": "988cb71e-0021-4217-a536-734b097a87b3",
"meta": {},
"createdAt": "2025-11-23T13:47:00.127Z",
"updatedAt": "2025-11-23T13:47:00.127Z",
"deletedAt": null
}
```
**Key Fields:**
- `width` / `height` - Actual image dimensions in pixels (automatically extracted from generated images)
- `storageUrl` - Direct URL to access the image file (use this for image display)
- `storageKey` - Internal MinIO storage path
- `source` - Image origin: "generated" (AI-generated) or "uploaded" (user upload)
- `alias` - Project-scoped alias (e.g., "@logo"), null if not assigned
- `focalPoint` - Cropping focal point {x: 0.0-1.0, y: 0.0-1.0}, null if not set
**Image Access:**
To display an image, use the `storageUrl` field which provides direct access to the image file in MinIO storage. For public CDN access, use the `/cdn/:orgSlug/:projectSlug/img/:alias` endpoint.
**Note:** Previous versions included a `url` field that pointed to a non-existent `/download` endpoint. This field has been removed. Always use `storageUrl` for direct image access.
---
## Error Codes
| Code | Description |
|------|-------------|
| 400 | Bad Request - Invalid parameters or validation failure |
| 401 | Unauthorized - Missing, invalid, expired, or revoked API key |
| 403 | Forbidden - Scope creation disabled or insufficient permissions |
| 404 | Not Found - Resource does not exist |
| 409 | Conflict - Alias or slug already exists |
| 429 | Too Many Requests - Rate limit or scope generation limit exceeded |
| 500 | Internal Server Error - Processing or generation failure |
**Common Error Codes:**
- `VALIDATION_ERROR` - Invalid parameters or missing required fields
- `GENERATION_NOT_FOUND` - Generation does not exist
- `FLOW_NOT_FOUND` - Flow does not exist
- `IMAGE_NOT_FOUND` - Image or alias not found
- `ALIAS_CONFLICT` - Alias already exists in project
- `ALIAS_NOT_FOUND` - Alias does not exist in any scope
- `SCOPE_INVALID_FORMAT` - Invalid scope slug format
- `SCOPE_ALREADY_EXISTS` - Scope slug already in use
- `SCOPE_NOT_FOUND` - Scope does not exist
- `SCOPE_CREATION_DISABLED` - New scope creation not allowed
- `SCOPE_GENERATION_LIMIT_EXCEEDED` - Scope generation limit reached
- `IP_RATE_LIMIT_EXCEEDED` - IP rate limit exceeded for live URLs
- `ORG_NOT_FOUND` - Organization not found
- `PROJECT_NOT_FOUND` - Project not found
- `IMAGE_NOT_IN_SCOPE` - Image doesn't belong to specified scope
**Common Error Messages:**
- `"Prompt is required"` - Missing prompt parameter
- `"Alias already exists"` - Alias conflict in project
- `"Invalid aspect ratio"` - Unsupported aspect ratio format
- `"File too large"` - Upload exceeds 5MB limit
- `"alias_format_check"` - Alias must start with @ symbol (e.g., @hero not hero)
- `"Rate limit exceeded. Try again in N seconds"` - IP rate limit for live URLs