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:
parent
baa833cdc7
commit
af8ed28cfb
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:**
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue