API responses now include file_url and thumbnail_url fields. When S3_PUBLIC_BASE_URL is configured, these point to the CDN domain; when unset, they fall back to the existing API proxy paths so local dev requires no additional setup. UI updated to use response URL fields directly instead of constructing proxy URLs client-side. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2.7 KiB
2.7 KiB
Contract: Image Metadata Response
Version: 2.0 (adds file_url, thumbnail_url)
Endpoints affected: GET /api/v1/images, GET /api/v1/images/{id}, POST /api/v1/images, PATCH /api/v1/images/{id}/tags
Response Schema
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"filename": "reaction.gif",
"mime_type": "image/gif",
"size_bytes": 204800,
"width": 480,
"height": 270,
"storage_key": "e3b0c44298fc1c149afbf4c8996fb924",
"thumbnail_key": "e3b0c44298fc1c149afbf4c8996fb924.thumb",
"file_url": "https://cdn.reactbin.juggalol.com/e3b0c44298fc1c149afbf4c8996fb924",
"thumbnail_url": "https://cdn.reactbin.juggalol.com/e3b0c44298fc1c149afbf4c8996fb924.thumb",
"created_at": "2026-05-08T12:00:00.000000",
"tags": ["funny", "reaction"]
}
Field Descriptions
| Field | Type | Nullable | Notes |
|---|---|---|---|
id |
string (UUID) | No | Stable image identifier |
hash |
string (hex) | No | SHA-256 of file content; deduplication key |
filename |
string | No | Original upload filename |
mime_type |
string | No | One of: image/jpeg, image/png, image/gif, image/webp |
size_bytes |
integer | No | File size in bytes |
width |
integer | No | Image width in pixels |
height |
integer | No | Image height in pixels |
storage_key |
string | No | Object storage key (retained for backward compat) |
thumbnail_key |
string | Yes | Thumbnail object storage key; null if generation failed |
file_url |
string | No | Full URL to fetch the image file — CDN URL in production, API proxy path in local dev |
thumbnail_url |
string | Yes | Full URL to fetch the thumbnail — CDN URL in production, API proxy path in local dev; null if no thumbnail |
created_at |
string (ISO 8601) | No | Upload timestamp |
tags |
string[] | No | Lowercase normalised tag list |
duplicate |
boolean | Yes | Present only on upload responses; true if hash matched an existing image |
URL Behaviour
| Configuration | file_url example |
thumbnail_url example |
|---|---|---|
S3_PUBLIC_BASE_URL set |
https://cdn.reactbin.juggalol.com/{storage_key} |
https://cdn.reactbin.juggalol.com/{thumbnail_key} |
S3_PUBLIC_BASE_URL not set |
/api/v1/images/{id}/file |
/api/v1/images/{id}/thumbnail |
UI Contract
The UI MUST use file_url and thumbnail_url from the response to render images. The UI MUST NOT construct image URLs from id, storage_key, or thumbnail_key directly. The UI MUST treat thumbnail_url: null as "no thumbnail available" and fall back to file_url for display.