doc: new api

This commit is contained in:
Oleg Proskurin 2025-11-28 10:49:01 +07:00
parent e70610e00d
commit 1e080bd87c
4 changed files with 1493 additions and 752 deletions

View File

@ -0,0 +1,449 @@
# Advanced Image Generation
Advanced generation features: reference images, aliases, flows, and regeneration. For basic generation, see [image-generation.md](image-generation.md).
All endpoints require Project Key authentication via `X-API-Key` header.
---
## Reference Images
Use existing images as style or content references for generation.
### Using References
Add `referenceImages` array to your generation request:
```json
{
"prompt": "A product photo with the logo in the corner",
"referenceImages": ["@brand-logo", "@product-style"]
}
```
References can be:
- **Project aliases**: `@logo`, `@brand-style`
- **Flow aliases**: `@hero` (with flowId context)
- **Technical aliases**: `@last`, `@first`, `@upload`
- **Image UUIDs**: `550e8400-e29b-41d4-a716-446655440000`
### Auto-Detection from Prompt
Aliases in the prompt are automatically detected and used as references:
```json
{
"prompt": "Create a banner using @brand-logo with blue background"
}
// @brand-logo is auto-detected and added to referenceImages
```
### Reference Limits
| Constraint | Limit |
|------------|-------|
| Max references | 3 images |
| Max file size | 5MB per image |
| Supported formats | PNG, JPEG, WebP |
### Response with References
```json
{
"data": {
"id": "550e8400-...",
"prompt": "Create a banner using @brand-logo",
"referencedImages": [
{ "imageId": "7c4ccf47-...", "alias": "@brand-logo" }
],
"referenceImages": [
{
"id": "7c4ccf47-...",
"storageUrl": "http://...",
"alias": "@brand-logo"
}
]
}
}
```
---
## Alias Assignment
Assign aliases to generated images for easy referencing.
### Project-Scoped Alias
Use `alias` parameter to assign a project-wide alias:
```json
{
"prompt": "A hero banner image",
"alias": "@hero-banner"
}
```
The output image will be accessible via `@hero-banner` anywhere in the project.
### Flow-Scoped Alias
Use `flowAlias` parameter to assign a flow-specific alias:
```json
{
"prompt": "A hero image variation",
"flowId": "550e8400-...",
"flowAlias": "@best"
}
```
The alias `@best` is only accessible within this flow's context.
### Alias Format
| Rule | Description |
|------|-------------|
| Prefix | Must start with `@` |
| Characters | Alphanumeric, underscore, hyphen |
| Pattern | `@[a-zA-Z0-9_-]+` |
| Max length | 50 characters |
| Examples | `@logo`, `@hero-bg`, `@image_1` |
### Reserved Aliases
These aliases are computed automatically and cannot be assigned:
| Alias | Description |
|-------|-------------|
| `@last` | Most recently generated image in flow |
| `@first` | First generated image in flow |
| `@upload` | Most recently uploaded image in flow |
### Override Behavior
When assigning an alias that already exists:
- The **new image gets the alias**
- The **old image loses the alias** (alias set to null)
- The old image is **not deleted**, just unlinked
---
## 3-Tier Alias Resolution
Aliases are resolved in this order of precedence:
### 1. Technical Aliases (Highest Priority)
Computed on-the-fly, require flow context:
```
GET /api/v1/images/@last?flowId=550e8400-...
```
| Alias | Returns |
|-------|---------|
| `@last` | Last generated image in flow |
| `@first` | First generated image in flow |
| `@upload` | Last uploaded image in flow |
### 2. Flow Aliases
Stored in flow's `aliases` JSONB field:
```
GET /api/v1/images/@hero?flowId=550e8400-...
```
Different flows can have the same alias pointing to different images.
### 3. Project Aliases (Lowest Priority)
Stored in image's `alias` column:
```
GET /api/v1/images/@logo
```
Global across the project, unique per project.
### Resolution Example
```
// Request with flowId
GET /api/v1/images/@hero?flowId=abc-123
// Resolution order:
// 1. Is "@hero" a technical alias? No
// 2. Does flow abc-123 have "@hero" in aliases? Check flows.aliases JSONB
// 3. Does any image have alias = "@hero"? Check images.alias column
```
---
## Flow Integration
Flows organize related generations into chains.
### Lazy Flow Creation
When `flowId` is not provided, a pending flow ID is generated:
```json
// Request
{
"prompt": "A red car"
// No flowId
}
// Response
{
"data": {
"id": "gen-123",
"flowId": "flow-456" // Auto-generated, flow record not created yet
}
}
```
The flow record is created when:
- A second generation uses the same `flowId`
- A `flowAlias` is assigned to any generation in the flow
### Eager Flow Creation
When `flowAlias` is provided, the flow is created immediately:
```json
{
"prompt": "A hero banner",
"flowAlias": "@hero-flow"
}
```
### No Flow Association
To explicitly create without flow association:
```json
{
"prompt": "A standalone image",
"flowId": null
}
```
### flowId Behavior Summary
| Value | Behavior |
|-------|----------|
| `undefined` (not provided) | Auto-generate pendingFlowId, lazy creation |
| `null` (explicitly null) | No flow association |
| `"uuid-string"` | Use provided ID, create flow if doesn't exist |
---
## Regeneration
### Regenerate Generation
Recreate an image using the exact same parameters:
```
POST /api/v1/generations/:id/regenerate
```
**Behavior:**
- Uses exact same prompt, aspect ratio, references
- **Preserves** output image ID and URL
- Works regardless of current status
- No request body needed
**Response:** Same as original generation with new image
### Update and Regenerate
Use PUT to modify parameters with smart regeneration:
```
PUT /api/v1/generations/:id
```
```json
{
"prompt": "A blue car instead",
"aspectRatio": "1:1"
}
```
**Smart Behavior:**
| Changed Field | Triggers Regeneration |
|---------------|----------------------|
| `prompt` | Yes |
| `aspectRatio` | Yes |
| `flowId` | No (metadata only) |
| `meta` | No (metadata only) |
### Flow Regenerate
Regenerate the most recent generation in a flow:
```
POST /api/v1/flows/:id/regenerate
```
**Behavior:**
- Finds the most recent generation in flow
- Regenerates with exact same parameters
- Returns error if flow has no generations
---
## Flow Management
### List Flows
```
GET /api/v1/flows
```
**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `limit` | number | `20` | Results per page (max: 100) |
| `offset` | number | `0` | Pagination offset |
**Response:**
```json
{
"data": [
{
"id": "flow-456",
"projectId": "project-123",
"aliases": { "@hero": "img-789", "@best": "img-abc" },
"generationCount": 5,
"imageCount": 7,
"createdAt": "2025-11-28T10:00:00.000Z"
}
],
"pagination": { "limit": 20, "offset": 0, "total": 3, "hasMore": false }
}
```
### Get Flow
```
GET /api/v1/flows/:id
```
Returns flow with computed counts and aliases.
### List Flow Generations
```
GET /api/v1/flows/:id/generations
```
Returns all generations in the flow, ordered by creation date (newest first).
### List Flow Images
```
GET /api/v1/flows/:id/images
```
Returns all images in the flow (generated and uploaded).
### Update Flow Aliases
```
PUT /api/v1/flows/:id/aliases
```
```json
{
"aliases": {
"@hero": "image-id-123",
"@best": "image-id-456"
}
}
```
**Behavior:** Merges with existing aliases (does not replace all).
### Remove Flow Alias
```
DELETE /api/v1/flows/:id/aliases/:alias
```
Example: `DELETE /api/v1/flows/flow-456/aliases/@hero`
### Delete Flow
```
DELETE /api/v1/flows/:id
```
**Cascade Behavior:**
- Flow record is **hard deleted**
- All generations in flow are **hard deleted**
- Images **without** project alias: **hard deleted** with MinIO cleanup
- Images **with** project alias: **kept**, but `flowId` set to null
---
## Full Request Example
```json
// POST /api/v1/generations
{
"prompt": "A professional product photo using @brand-style and @product-template",
"aspectRatio": "1:1",
"autoEnhance": true,
"enhancementOptions": { "template": "product" },
"flowId": "campaign-flow-123",
"alias": "@latest-product",
"flowAlias": "@hero",
"meta": { "campaign": "summer-2025" }
}
```
**What happens:**
1. `@brand-style` and `@product-template` resolved and used as references
2. Prompt enhanced using "product" template
3. Generation created in flow `campaign-flow-123`
4. Output image assigned project alias `@latest-product`
5. Output image assigned flow alias `@hero` in the flow
6. Custom metadata stored
---
## Response Fields (Additional)
| Field | Type | Description |
|-------|------|-------------|
| `flowId` | string | Associated flow UUID |
| `alias` | string | Project-scoped alias (on outputImage) |
| `referencedImages` | array | Resolved references: `[{ imageId, alias }]` |
| `referenceImages` | array | Full image details of references |
---
## Error Codes
| HTTP Status | Code | Description |
|-------------|------|-------------|
| 400 | `ALIAS_FORMAT_CHECK` | Alias must start with @ |
| 400 | `RESERVED_ALIAS` | Cannot use technical alias |
| 404 | `ALIAS_NOT_FOUND` | Referenced alias doesn't exist |
| 404 | `FLOW_NOT_FOUND` | Flow does not exist |
---
## See Also
- [Basic Generation](image-generation.md) - Simple generation
- [Image Upload](images-upload.md) - Upload with aliases
- [Live URLs](live-url.md) - CDN and live generation

File diff suppressed because it is too large Load Diff

374
docs/api/images-upload.md Normal file
View File

@ -0,0 +1,374 @@
# Image Upload & Management API
Upload images and manage your image library. For generation, see [image-generation.md](image-generation.md).
All endpoints require Project Key authentication via `X-API-Key` header.
---
## Upload Image
```
POST /api/v1/images/upload
```
Upload an image file with optional alias and flow association.
**Content-Type:** `multipart/form-data`
**Form Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `file` | file | Yes | Image file (PNG, JPEG, WebP) |
| `alias` | string | No | Project-scoped alias (e.g., `@logo`) |
| `flowId` | string | No | Flow UUID to associate with |
| `flowAlias` | string | No | Flow-scoped alias (requires flowId) |
| `meta` | string | No | JSON string with custom metadata |
**File Constraints:**
| Constraint | Limit |
|------------|-------|
| Max file size | 5MB |
| Supported formats | PNG, JPEG, JPG, WebP |
| MIME types | `image/png`, `image/jpeg`, `image/webp` |
**Example Request (curl):**
```bash
curl -X POST http://localhost:3000/api/v1/images/upload \
-H "X-API-Key: YOUR_PROJECT_KEY" \
-F "file=@logo.png" \
-F "alias=@brand-logo" \
-F 'meta={"tags": ["logo", "brand"]}'
```
**Response:** `201 Created`
```json
{
"success": true,
"data": {
"id": "7c4ccf47-41ce-4718-afbc-8c553b2c631a",
"projectId": "57c7f7f4-47de-4d70-9ebd-3807a0b63746",
"flowId": null,
"storageKey": "default/project-id/uploads/2025-11/logo.png",
"storageUrl": "http://localhost:9000/banatie/default/project-id/uploads/logo.png",
"mimeType": "image/png",
"fileSize": 45678,
"width": 512,
"height": 512,
"source": "uploaded",
"alias": "@brand-logo",
"focalPoint": null,
"meta": { "tags": ["logo", "brand"] },
"createdAt": "2025-11-28T10:00:00.000Z"
}
}
```
### flowId Behavior
| Value | Behavior |
|-------|----------|
| Not provided | Auto-generate `pendingFlowId`, lazy flow creation |
| `null` | No flow association |
| `"uuid"` | Associate with specified flow |
### Upload with Flow
```bash
# Associate with existing flow
curl -X POST .../images/upload \
-F "file=@reference.png" \
-F "flowId=flow-123" \
-F "flowAlias=@reference"
```
---
## List Images
```
GET /api/v1/images
```
List all images with filtering and pagination.
**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `flowId` | string | - | Filter by flow UUID |
| `source` | string | - | Filter by source: `generated`, `uploaded` |
| `alias` | string | - | Filter by exact alias match |
| `limit` | number | `20` | Results per page (max: 100) |
| `offset` | number | `0` | Pagination offset |
| `includeDeleted` | boolean | `false` | Include soft-deleted records |
**Example:**
```
GET /api/v1/images?source=uploaded&limit=10
```
**Response:**
```json
{
"success": true,
"data": [
{
"id": "7c4ccf47-...",
"storageUrl": "http://...",
"source": "uploaded",
"alias": "@brand-logo",
"width": 512,
"height": 512,
"createdAt": "2025-11-28T10:00:00.000Z"
}
],
"pagination": {
"limit": 10,
"offset": 0,
"total": 25,
"hasMore": true
}
}
```
---
## Get Image
```
GET /api/v1/images/:id_or_alias
```
Get a single image by UUID or alias.
**Path Parameter:**
- `id_or_alias` - Image UUID or `@alias`
**Query Parameters:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `flowId` | string | Flow context for alias resolution |
**Examples:**
```
# By UUID
GET /api/v1/images/7c4ccf47-41ce-4718-afbc-8c553b2c631a
# By project alias
GET /api/v1/images/@brand-logo
# By technical alias (requires flowId)
GET /api/v1/images/@last?flowId=flow-123
# By flow alias
GET /api/v1/images/@hero?flowId=flow-123
```
**Response:**
```json
{
"success": true,
"data": {
"id": "7c4ccf47-41ce-4718-afbc-8c553b2c631a",
"projectId": "57c7f7f4-47de-4d70-9ebd-3807a0b63746",
"flowId": null,
"storageKey": "default/project-id/uploads/2025-11/logo.png",
"storageUrl": "http://localhost:9000/banatie/.../logo.png",
"mimeType": "image/png",
"fileSize": 45678,
"width": 512,
"height": 512,
"source": "uploaded",
"alias": "@brand-logo",
"focalPoint": null,
"fileHash": null,
"generationId": null,
"meta": { "tags": ["logo", "brand"] },
"createdAt": "2025-11-28T10:00:00.000Z",
"updatedAt": "2025-11-28T10:00:00.000Z",
"deletedAt": null
}
}
```
---
## Update Image Metadata
```
PUT /api/v1/images/:id_or_alias
```
Update image metadata (focal point, custom metadata).
**Request Body:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `focalPoint` | object | Focal point: `{ x: 0.0-1.0, y: 0.0-1.0 }` |
| `meta` | object | Custom metadata |
**Example:**
```json
// PUT /api/v1/images/@brand-logo
{
"focalPoint": { "x": 0.5, "y": 0.3 },
"meta": {
"description": "Updated brand logo",
"tags": ["logo", "brand", "2025"]
}
}
```
**Response:** Updated image object.
> **Note:** Alias assignment has its own dedicated endpoint.
---
## Assign Alias
```
PUT /api/v1/images/:id_or_alias/alias
```
Assign or remove a project-scoped alias.
**Request Body:**
```json
// Assign alias
{ "alias": "@new-logo" }
// Remove alias
{ "alias": null }
```
**Override Behavior:**
- If another image has this alias, it loses the alias
- The new image gets the alias
- Old image is preserved, just unlinked
**Example:**
```bash
curl -X PUT http://localhost:3000/api/v1/images/7c4ccf47-.../alias \
-H "X-API-Key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"alias": "@primary-logo"}'
```
---
## Delete Image
```
DELETE /api/v1/images/:id_or_alias
```
Permanently delete an image and its storage file.
**Behavior:**
- **Hard delete** - image record permanently removed
- Storage file deleted from MinIO
- Cascading updates:
- Related generations: `outputImageId` set to null
- Flow aliases: image removed from flow's aliases
- Referenced images: removed from generation's referencedImages
**Response:** `200 OK`
```json
{
"success": true,
"message": "Image deleted"
}
```
> **Warning:** This cannot be undone. The image file is permanently removed.
---
## Image Response Fields
| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Image UUID |
| `projectId` | string | Project UUID |
| `flowId` | string | Associated flow UUID (null if none) |
| `storageKey` | string | Internal storage path |
| `storageUrl` | string | **Direct URL to access image** |
| `mimeType` | string | Image MIME type |
| `fileSize` | number | File size in bytes |
| `width` | number | Image width in pixels |
| `height` | number | Image height in pixels |
| `source` | string | `"generated"` or `"uploaded"` |
| `alias` | string | Project-scoped alias (null if none) |
| `focalPoint` | object | `{ x, y }` coordinates (0.0-1.0) |
| `fileHash` | string | SHA-256 hash for deduplication |
| `generationId` | string | Source generation UUID (if generated) |
| `meta` | object | Custom metadata |
| `createdAt` | string | ISO timestamp |
| `updatedAt` | string | ISO timestamp |
| `deletedAt` | string | Soft delete timestamp (null if active) |
### Accessing Images
Use `storageUrl` for direct image access:
```html
<img src="http://localhost:9000/banatie/.../image.png" />
```
For public CDN access, see [Live URLs](live-url.md).
---
## Storage Organization
Images are organized in MinIO storage:
```
bucket/
{orgId}/
{projectId}/
uploads/ # Uploaded images
2025-11/
image.png
generated/ # AI-generated images
2025-11/
gen_abc123.png
```
---
## Error Codes
| HTTP Status | Code | Description |
|-------------|------|-------------|
| 400 | `VALIDATION_ERROR` | Invalid parameters |
| 400 | `FILE_TOO_LARGE` | File exceeds 5MB limit |
| 400 | `UNSUPPORTED_FILE_TYPE` | Not PNG, JPEG, or WebP |
| 400 | `ALIAS_FORMAT_CHECK` | Alias must start with @ |
| 401 | `UNAUTHORIZED` | Missing or invalid API key |
| 404 | `IMAGE_NOT_FOUND` | Image or alias doesn't exist |
| 404 | `ALIAS_NOT_FOUND` | Alias doesn't resolve to any image |
---
## See Also
- [Basic Generation](image-generation.md) - Generate images
- [Advanced Generation](image-generation-advanced.md) - References, aliases, flows
- [Live URLs](live-url.md) - CDN and public access

380
docs/api/live-url.md Normal file
View File

@ -0,0 +1,380 @@
# Live URL & CDN API
Public CDN endpoints for image serving and live URL generation. For authenticated API, see [image-generation.md](image-generation.md).
---
## CDN Image Serving
```
GET /cdn/:orgSlug/:projectSlug/img/:filenameOrAlias
```
**Authentication:** None - Public endpoint
Serve images by filename or project-scoped alias.
**Path Parameters:**
| Parameter | Description |
|-----------|-------------|
| `orgSlug` | Organization identifier |
| `projectSlug` | Project identifier |
| `filenameOrAlias` | Filename or `@alias` |
**Examples:**
```
# By filename
GET /cdn/acme/website/img/hero-background.jpg
# By alias
GET /cdn/acme/website/img/@hero
```
**Response:** Raw image bytes (not JSON)
**Response Headers:**
| Header | Value |
|--------|-------|
| `Content-Type` | `image/jpeg`, `image/png`, etc. |
| `Content-Length` | File size in bytes |
| `Cache-Control` | `public, max-age=31536000` (1 year) |
| `X-Image-Id` | Image UUID |
---
## Live URL Generation
```
GET /cdn/:orgSlug/:projectSlug/live/:scope
```
**Authentication:** None - Public endpoint
Generate images on-demand via URL parameters with automatic caching.
**Path Parameters:**
| Parameter | Description |
|-----------|-------------|
| `orgSlug` | Organization identifier |
| `projectSlug` | Project identifier |
| `scope` | Scope identifier (alphanumeric, hyphens, underscores) |
**Query Parameters:**
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `prompt` | string | Yes | - | Image description |
| `aspectRatio` | string | No | `"1:1"` | Aspect ratio |
| `autoEnhance` | boolean | No | `true` | Enable prompt enhancement |
| `template` | string | No | `"general"` | Enhancement template |
**Example:**
```
GET /cdn/acme/website/live/hero-section?prompt=mountain+landscape&aspectRatio=16:9
```
**Response:** Raw image bytes
### Cache Behavior
**Cache HIT** - Image exists in cache:
- Returns instantly
- No rate limit check
- Headers include `X-Cache-Status: HIT`
**Cache MISS** - New generation:
- Generates image using AI
- Stores in cache
- Counts toward rate limit
- Headers include `X-Cache-Status: MISS`
**Cache Key:** Computed from `projectId + scope + prompt + aspectRatio + autoEnhance + template`
### Response Headers
**Cache HIT:**
| Header | Value |
|--------|-------|
| `Content-Type` | `image/jpeg` |
| `Cache-Control` | `public, max-age=31536000` |
| `X-Cache-Status` | `HIT` |
| `X-Scope` | Scope identifier |
| `X-Image-Id` | Image UUID |
**Cache MISS:**
| Header | Value |
|--------|-------|
| `Content-Type` | `image/jpeg` |
| `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 |
---
## IP Rate Limiting
Live URLs are rate limited by IP address:
| Limit | Value |
|-------|-------|
| New generations | 10 per hour per IP |
| Cache hits | Unlimited |
**Note:** Only cache MISS (new generations) count toward the limit. Cache HIT requests are not limited.
Rate limit headers are included on MISS responses:
- `X-RateLimit-Limit`: Maximum requests (10)
- `X-RateLimit-Remaining`: Remaining requests
- `X-RateLimit-Reset`: Seconds until reset
---
## Scope Management
Scopes organize live URL generation budgets. All scope endpoints require Project Key authentication.
### Create Scope
```
POST /api/v1/live/scopes
```
**Request Body:**
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `slug` | string | Yes | - | Unique identifier |
| `allowNewGenerations` | boolean | No | `true` | Allow new generations |
| `newGenerationsLimit` | number | No | `30` | Max generations in scope |
| `meta` | object | No | `{}` | Custom metadata |
**Example:**
```json
{
"slug": "hero-section",
"allowNewGenerations": true,
"newGenerationsLimit": 50,
"meta": { "description": "Hero section images" }
}
```
**Response:** `201 Created`
```json
{
"success": true,
"data": {
"id": "scope-123",
"projectId": "project-456",
"slug": "hero-section",
"allowNewGenerations": true,
"newGenerationsLimit": 50,
"currentGenerations": 0,
"lastGeneratedAt": null,
"meta": { "description": "Hero section images" },
"createdAt": "2025-11-28T10:00:00.000Z"
}
}
```
### Lazy Scope Creation
Scopes are auto-created on first live URL request if `project.allowNewLiveScopes = true`:
```
GET /cdn/acme/website/live/new-scope?prompt=...
// Creates "new-scope" with default settings
```
### List Scopes
```
GET /api/v1/live/scopes
```
**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `slug` | string | - | Filter by exact slug |
| `limit` | number | `20` | Results per page (max: 100) |
| `offset` | number | `0` | Pagination offset |
**Response:**
```json
{
"success": true,
"data": [
{
"id": "scope-123",
"slug": "hero-section",
"allowNewGenerations": true,
"newGenerationsLimit": 50,
"currentGenerations": 12,
"lastGeneratedAt": "2025-11-28T09:30:00.000Z"
}
],
"pagination": { "limit": 20, "offset": 0, "total": 3, "hasMore": false }
}
```
### Get Scope
```
GET /api/v1/live/scopes/:slug
```
Returns scope with statistics (currentGenerations, lastGeneratedAt).
### Update Scope
```
PUT /api/v1/live/scopes/:slug
```
```json
{
"allowNewGenerations": false,
"newGenerationsLimit": 100,
"meta": { "description": "Updated" }
}
```
Changes take effect immediately for new requests.
### Regenerate Scope Images
```
POST /api/v1/live/scopes/:slug/regenerate
```
**Request Body:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `imageId` | string | Specific image UUID (optional) |
**Behavior:**
- If `imageId` provided: Regenerate only that image
- If `imageId` omitted: Regenerate all images in scope
Images are regenerated with exact same parameters. IDs and URLs are preserved.
### Delete Scope
```
DELETE /api/v1/live/scopes/:slug
```
**Cascade Behavior:**
- Scope record is **hard deleted**
- All images in scope are **hard deleted** (with MinIO cleanup)
- Follows alias protection rules (aliased images may be kept)
> **Warning:** This permanently deletes all cached images in the scope.
---
## Scope Settings
| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `slug` | string | - | Unique identifier within project |
| `allowNewGenerations` | boolean | `true` | Whether new generations are allowed |
| `newGenerationsLimit` | number | `30` | Maximum generations in scope |
When `allowNewGenerations: false`:
- Cache HITs still work
- New prompts return 403 error
When `newGenerationsLimit` reached:
- Cache HITs still work
- New prompts return 429 error
---
## Authenticated Live Endpoint
```
GET /api/v1/live?prompt=...
```
**Authentication:** Project Key required
Alternative to CDN endpoint with prompt caching by hash.
**Query Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `prompt` | string | Yes | Image description |
**Cache Behavior:**
- Cache key: SHA-256 hash of prompt
- Cache stored in `prompt_url_cache` table
- Tracks hit count and last access
**Response Headers:**
- `X-Cache-Status`: `HIT` or `MISS`
- `X-Cache-Hit-Count`: Number of cache hits (on HIT)
---
## Error Codes
| HTTP Status | Code | Description |
|-------------|------|-------------|
| 400 | `SCOPE_INVALID_FORMAT` | Invalid scope slug format |
| 403 | `SCOPE_CREATION_DISABLED` | New scope creation not allowed |
| 404 | `ORG_NOT_FOUND` | Organization not found |
| 404 | `PROJECT_NOT_FOUND` | Project not found |
| 404 | `SCOPE_NOT_FOUND` | Scope does not exist |
| 409 | `SCOPE_ALREADY_EXISTS` | Scope slug already in use |
| 429 | `IP_RATE_LIMIT_EXCEEDED` | IP rate limit (10/hour) exceeded |
| 429 | `SCOPE_GENERATION_LIMIT_EXCEEDED` | Scope limit reached |
---
## Use Cases
### Dynamic Hero Images
```html
<img src="/cdn/acme/website/live/hero?prompt=professional+office+workspace&aspectRatio=16:9" />
```
First load generates, subsequent loads are cached.
### Product Placeholders
```html
<img src="/cdn/acme/store/live/products?prompt=product+placeholder+gray+box&aspectRatio=1:1" />
```
### Blog Post Images
```html
<img src="/cdn/acme/blog/live/posts?prompt=abstract+technology+background&aspectRatio=16:9&template=illustration" />
```
---
## See Also
- [Basic Generation](image-generation.md) - API-based generation
- [Advanced Generation](image-generation-advanced.md) - References, aliases, flows
- [Image Upload](images-upload.md) - Upload and manage images