docs: update API documentation for new CDN URL format

Update all API documentation to reflect new storage architecture:

- storageKey: {org}/{project}/img/{imageId} (UUID, no extension)
- storageUrl: https://cdn.banatie.app/{org}/{project}/img/{imageId}
- Add URL Architecture section to live-url.md
- Update all example responses with new format
- Document UUID vs alias URL routing differences
- Clarify that filename = image.id (UUID)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Oleg Proskurin 2025-12-29 00:24:25 +07:00
parent baa833cdc7
commit af8ed28cfb
3 changed files with 68 additions and 28 deletions

View File

@ -238,7 +238,8 @@ Get a single generation with full details.
"outputImageId": "7c4ccf47-41ce-4718-afbc-8c553b2c631a", "outputImageId": "7c4ccf47-41ce-4718-afbc-8c553b2c631a",
"outputImage": { "outputImage": {
"id": "7c4ccf47-41ce-4718-afbc-8c553b2c631a", "id": "7c4ccf47-41ce-4718-afbc-8c553b2c631a",
"storageUrl": "http://localhost:9000/banatie/default/project-id/generated/image.png", "storageKey": "default/my-project/img/7c4ccf47-41ce-4718-afbc-8c553b2c631a",
"storageUrl": "https://cdn.banatie.app/default/my-project/img/7c4ccf47-41ce-4718-afbc-8c553b2c631a",
"mimeType": "image/png", "mimeType": "image/png",
"width": 1792, "width": 1792,
"height": 1024, "height": 1024,
@ -305,13 +306,16 @@ Delete a generation and its output image.
| Field | Type | Description | | Field | Type | Description |
|-------|------|-------------| |-------|------|-------------|
| `id` | string | Image UUID | | `id` | string | Image UUID (same as filename in storage) |
| `storageUrl` | string | Direct URL to image file | | `storageKey` | string | Storage path: `{org}/{project}/img/{imageId}` |
| `storageUrl` | string | CDN URL: `https://cdn.banatie.app/{org}/{project}/img/{imageId}` |
| `mimeType` | string | Image MIME type | | `mimeType` | string | Image MIME type |
| `width` | number | Image width in pixels | | `width` | number | Image width in pixels |
| `height` | number | Image height in pixels | | `height` | number | Image height in pixels |
| `fileSize` | number | File size in bytes | | `fileSize` | number | File size in bytes |
> **Note:** The image filename in storage equals `image.id` (UUID). No file extension is used - Content-Type is stored in object metadata.
--- ---
## Error Codes ## Error Codes

View File

@ -53,8 +53,8 @@ curl -X POST http://localhost:3000/api/v1/images/upload \
"id": "7c4ccf47-41ce-4718-afbc-8c553b2c631a", "id": "7c4ccf47-41ce-4718-afbc-8c553b2c631a",
"projectId": "57c7f7f4-47de-4d70-9ebd-3807a0b63746", "projectId": "57c7f7f4-47de-4d70-9ebd-3807a0b63746",
"flowId": null, "flowId": null,
"storageKey": "default/project-id/uploads/2025-11/logo.png", "storageKey": "default/my-project/img/7c4ccf47-41ce-4718-afbc-8c553b2c631a",
"storageUrl": "http://localhost:9000/banatie/default/project-id/uploads/logo.png", "storageUrl": "https://cdn.banatie.app/default/my-project/img/7c4ccf47-41ce-4718-afbc-8c553b2c631a",
"mimeType": "image/png", "mimeType": "image/png",
"fileSize": 45678, "fileSize": 45678,
"width": 512, "width": 512,
@ -68,6 +68,8 @@ curl -X POST http://localhost:3000/api/v1/images/upload \
} }
``` ```
> **Note:** The `id` field equals the filename in storage (UUID). Original filename is preserved in object metadata.
### flowId Behavior ### flowId Behavior
| Value | Behavior | | Value | Behavior |
@ -182,8 +184,8 @@ GET /api/v1/images/@hero?flowId=flow-123
"id": "7c4ccf47-41ce-4718-afbc-8c553b2c631a", "id": "7c4ccf47-41ce-4718-afbc-8c553b2c631a",
"projectId": "57c7f7f4-47de-4d70-9ebd-3807a0b63746", "projectId": "57c7f7f4-47de-4d70-9ebd-3807a0b63746",
"flowId": null, "flowId": null,
"storageKey": "default/project-id/uploads/2025-11/logo.png", "storageKey": "default/my-project/img/7c4ccf47-41ce-4718-afbc-8c553b2c631a",
"storageUrl": "http://localhost:9000/banatie/.../logo.png", "storageUrl": "https://cdn.banatie.app/default/my-project/img/7c4ccf47-41ce-4718-afbc-8c553b2c631a",
"mimeType": "image/png", "mimeType": "image/png",
"fileSize": 45678, "fileSize": 45678,
"width": 512, "width": 512,
@ -304,11 +306,11 @@ Permanently delete an image and its storage file.
| Field | Type | Description | | Field | Type | Description |
|-------|------|-------------| |-------|------|-------------|
| `id` | string | Image UUID | | `id` | string | Image UUID (same as filename in storage) |
| `projectId` | string | Project UUID | | `projectId` | string | Project UUID |
| `flowId` | string | Associated flow UUID (null if none) | | `flowId` | string | Associated flow UUID (null if none) |
| `storageKey` | string | Internal storage path | | `storageKey` | string | Storage path: `{org}/{project}/img/{imageId}` |
| `storageUrl` | string | **Direct URL to access image** | | `storageUrl` | string | CDN URL: `https://cdn.banatie.app/{org}/{project}/img/{imageId}` |
| `mimeType` | string | Image MIME type | | `mimeType` | string | Image MIME type |
| `fileSize` | number | File size in bytes | | `fileSize` | number | File size in bytes |
| `width` | number | Image width in pixels | | `width` | number | Image width in pixels |
@ -325,32 +327,40 @@ Permanently delete an image and its storage file.
### Accessing Images ### Accessing Images
Use `storageUrl` for direct image access: Use `storageUrl` for direct CDN access:
```html ```html
<img src="http://localhost:9000/banatie/.../image.png" /> <!-- Direct access via UUID -->
<img src="https://cdn.banatie.app/default/my-project/img/7c4ccf47-41ce-4718-afbc-8c553b2c631a" />
<!-- Access via alias (goes through API) -->
<img src="https://cdn.banatie.app/default/my-project/img/@brand-logo" />
``` ```
For public CDN access, see [Live URLs](live-url.md). > **Note:** UUID URLs are served directly from MinIO (fast, cacheable). Alias URLs require API resolution.
--- ---
## Storage Organization ## Storage Organization
Images are organized in MinIO storage: Images are stored in MinIO with a simplified path structure:
``` ```
bucket/ bucket/
{orgId}/ {orgSlug}/
{projectId}/ {projectSlug}/
uploads/ # Uploaded images img/
2025-11/ {imageId} # UUID, no file extension
image.png {imageId} # Content-Type in object metadata
generated/ # AI-generated images ...
2025-11/
gen_abc123.png
``` ```
**Key points:**
- **Filename = Image ID (UUID)** - No file extensions
- **Content-Type** stored in MinIO object metadata
- **Original filename** preserved in metadata for reference
- **Single `img/` directory** for all images (generated + uploaded)
--- ---
## Error Codes ## Error Codes

View File

@ -4,15 +4,39 @@ Public CDN endpoints for image serving and live URL generation. For authenticate
--- ---
## URL Architecture
All images are accessible via CDN at `https://cdn.banatie.app`:
| URL Pattern | Description | Routing |
|-------------|-------------|---------|
| `/{org}/{proj}/img/{uuid}` | Direct image by UUID | Caddy → MinIO (public) |
| `/{org}/{proj}/img/@{alias}` | Image by alias | Caddy → API → MinIO |
| `/{org}/{proj}/live/{scope}?prompt=...` | Live generation | Caddy → API → MinIO |
**Key points:**
- **UUID URLs** are permanent and directly cacheable (Cloudflare edge cache)
- **Alias URLs** resolve through API (allows dynamic reassignment)
- **Live URLs** generate on-demand with prompt-based caching
**Example URLs:**
```
https://cdn.banatie.app/default/my-project/img/7c4ccf47-41ce-4718-afbc-8c553b2c631a
https://cdn.banatie.app/default/my-project/img/@hero-banner
https://cdn.banatie.app/default/my-project/live/hero?prompt=mountain+sunset
```
---
## CDN Image Serving ## CDN Image Serving
``` ```
GET /cdn/:orgSlug/:projectSlug/img/:filenameOrAlias GET /cdn/:orgSlug/:projectSlug/img/:imageIdOrAlias
``` ```
**Authentication:** None - Public endpoint **Authentication:** None - Public endpoint
Serve images by filename or project-scoped alias. Serve images by UUID (imageId) or project-scoped alias.
**Path Parameters:** **Path Parameters:**
@ -20,18 +44,20 @@ Serve images by filename or project-scoped alias.
|-----------|-------------| |-----------|-------------|
| `orgSlug` | Organization identifier | | `orgSlug` | Organization identifier |
| `projectSlug` | Project identifier | | `projectSlug` | Project identifier |
| `filenameOrAlias` | Filename or `@alias` | | `imageIdOrAlias` | Image UUID or `@alias` |
**Examples:** **Examples:**
``` ```
# By filename # By UUID (direct MinIO access, fastest)
GET /cdn/acme/website/img/hero-background.jpg GET /cdn/acme/website/img/7c4ccf47-41ce-4718-afbc-8c553b2c631a
# By alias # By alias (API resolution, then MinIO)
GET /cdn/acme/website/img/@hero GET /cdn/acme/website/img/@hero
``` ```
> **Note:** UUID requests are served directly from MinIO (Cloudflare cached). Alias requests require API resolution.
**Response:** Raw image bytes (not JSON) **Response:** Raw image bytes (not JSON)
**Response Headers:** **Response Headers:**