banatie-service/apps/landing/src/app/docs/api/images/page.tsx

331 lines
11 KiB
TypeScript

'use client';
/**
* API Reference: Image Management
*
* Based on docs/api/images-upload.md (CRUD sections)
*/
import { TipBox } from '@/components/docs/shared/TipBox';
import { Table } from '@/components/docs/shared/Table';
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
import { DocPage } from '@/components/docs/layout/DocPage';
import {
Hero,
SectionHeader,
InlineCode,
EndpointCard,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'overview', text: 'Overview', level: 2 },
{ id: 'list-images', text: 'List Images', level: 2 },
{ id: 'get-image', text: 'Get Image', level: 2 },
{ id: 'update-metadata', text: 'Update Metadata', level: 2 },
{ id: 'assign-alias', text: 'Assign Alias', level: 2 },
{ id: 'delete-image', text: 'Delete Image', level: 2 },
{ id: 'response-fields', text: 'Response Fields', level: 2 },
{ id: 'next-steps', text: 'Next Steps', level: 2 },
];
const listQueryParams = [
{ name: 'flowId', type: 'string', default: '-', description: 'Filter by flow UUID' },
{ name: 'source', type: 'string', default: '-', description: 'Filter by source: generated, uploaded' },
{ name: 'alias', type: 'string', default: '-', description: 'Filter by exact alias match' },
{ name: 'limit', type: 'number', default: '20', description: 'Results per page (max: 100)' },
{ name: 'offset', type: 'number', default: '0', description: 'Pagination offset' },
{ name: 'includeDeleted', type: 'boolean', default: 'false', description: 'Include soft-deleted records' },
];
const responseFields = [
['id', 'string', 'Image UUID (same as filename in storage)'],
['projectId', 'string', 'Project UUID'],
['flowId', 'string', 'Associated flow UUID (null if none)'],
['storageUrl', 'string', 'CDN URL for direct access'],
['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)'],
['meta', 'object', 'Custom metadata'],
['createdAt', 'string', 'ISO timestamp'],
['updatedAt', 'string', 'ISO timestamp'],
];
export default function ImageManagementPage() {
return (
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'API Reference', href: '/docs/api' },
{ label: 'Image Management' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/api/live',
title: 'Live URLs',
description: 'Learn about CDN access and live URL generation.',
accent: 'primary',
},
{
href: '/docs/api/advanced',
title: 'Advanced Generation',
description: 'Use aliases and references in generation workflows.',
accent: 'secondary',
},
],
}}
>
{/* Hero Section */}
<Hero
title="Image Management"
subtitle="List, retrieve, update, and delete images in your project."
/>
{/* Overview */}
<section id="overview" className="mb-12">
<SectionHeader level={2} id="overview">
Overview
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
The Image Management API provides CRUD operations for images in your project.
Access images by UUID or alias, update metadata, and manage aliases for easy reference.
</p>
<TipBox variant="compact" type="info">
<strong>Tip:</strong> Use aliases like <InlineCode>@hero</InlineCode> for human-readable
references instead of UUIDs.
</TipBox>
</section>
{/* List Images */}
<section id="list-images" className="mb-12">
<SectionHeader level={2} id="list-images">
List Images
</SectionHeader>
<EndpointCard
method="GET"
endpoint="/api/v1/images"
baseUrl="https://api.banatie.app"
/>
<SectionHeader level={3} id="list-params" className="mt-6 mb-4">
Query Parameters
</SectionHeader>
<Table
headers={['Parameter', 'Type', 'Default', 'Description']}
rows={listQueryParams.map((param) => [
<InlineCode key="name">{param.name}</InlineCode>,
<span key="type" className="text-cyan-400">{param.type}</span>,
param.default === '-' ? <span className="text-gray-500">-</span> : <InlineCode key="default">{param.default}</InlineCode>,
param.description,
])}
/>
<div className="mt-6">
<CodeBlock
code={`{
"success": true,
"data": [
{
"id": "7c4ccf47-41ce-4718-afbc-8c553b2c631a",
"storageUrl": "https://cdn.banatie.app/default/my-project/img/7c4ccf47-...",
"source": "uploaded",
"alias": "@brand-logo",
"width": 512,
"height": 512,
"createdAt": "2025-11-28T10:00:00.000Z"
}
],
"pagination": {
"limit": 20,
"offset": 0,
"total": 25,
"hasMore": true
}
}`}
language="json"
filename="Response"
/>
</div>
</section>
{/* Get Image */}
<section id="get-image" className="mb-12">
<SectionHeader level={2} id="get-image">
Get Image
</SectionHeader>
<EndpointCard
method="GET"
endpoint="/api/v1/images/:id_or_alias"
baseUrl="https://api.banatie.app"
/>
<p className="text-gray-300 leading-relaxed mt-4 mb-4">
Retrieve a single image by UUID or alias.
</p>
<CodeBlock
code={`# 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`}
language="bash"
filename="Examples"
/>
<div className="mt-6">
<TipBox variant="compact" type="info">
<strong>Alias Resolution:</strong> When using aliases with <InlineCode>flowId</InlineCode>,
the system checks flow aliases first, then falls back to project aliases.
</TipBox>
</div>
</section>
{/* Update Metadata */}
<section id="update-metadata" className="mb-12">
<SectionHeader level={2} id="update-metadata">
Update Metadata
</SectionHeader>
<EndpointCard
method="PUT"
endpoint="/api/v1/images/:id_or_alias"
baseUrl="https://api.banatie.app"
/>
<p className="text-gray-300 leading-relaxed mt-4 mb-4">
Update image metadata including focal point and custom data.
</p>
<CodeBlock
code={`{
"focalPoint": { "x": 0.5, "y": 0.3 },
"meta": {
"description": "Updated brand logo",
"tags": ["logo", "brand", "2025"]
}
}`}
language="json"
filename="Request Body"
/>
<p className="text-gray-400 text-sm mt-4">
<strong>Note:</strong> Alias assignment has its own dedicated endpoint.
</p>
</section>
{/* Assign Alias */}
<section id="assign-alias" className="mb-12">
<SectionHeader level={2} id="assign-alias">
Assign Alias
</SectionHeader>
<EndpointCard
method="PUT"
endpoint="/api/v1/images/:id_or_alias/alias"
baseUrl="https://api.banatie.app"
/>
<p className="text-gray-300 leading-relaxed mt-4 mb-4">
Assign or remove a project-scoped alias from an image.
</p>
<CodeBlock
code={`// Assign alias
{ "alias": "@new-logo" }
// Remove alias
{ "alias": null }`}
language="json"
filename="Request Body"
/>
<div className="mt-6">
<TipBox variant="compact" type="warning">
<strong>Override Behavior:</strong> If another image has the alias, it loses the alias.
The target image gets the alias. The old image is preserved, just unlinked.
</TipBox>
</div>
</section>
{/* Delete Image */}
<section id="delete-image" className="mb-12">
<SectionHeader level={2} id="delete-image">
Delete Image
</SectionHeader>
<EndpointCard
method="DELETE"
endpoint="/api/v1/images/:id_or_alias"
baseUrl="https://api.banatie.app"
/>
<p className="text-gray-300 leading-relaxed mt-4 mb-4">
Permanently delete an image and its storage file.
</p>
<CodeBlock
code={`{
"success": true,
"message": "Image deleted"
}`}
language="json"
filename="Response"
/>
<div className="mt-6">
<TipBox variant="prominent" type="warning">
<strong>Warning:</strong> This action is irreversible. The image record and storage file
are permanently deleted. Related generations will have their <InlineCode>outputImageId</InlineCode> set to null.
</TipBox>
</div>
</section>
{/* Response Fields */}
<section id="response-fields" className="mb-12">
<SectionHeader level={2} id="response-fields" className="mb-6">
Response Fields
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Complete list of fields returned in image responses:
</p>
<Table
headers={['Field', 'Type', 'Description']}
rows={responseFields.map(([field, type, description]) => [
<InlineCode key="field">{field}</InlineCode>,
<span key="type" className="text-cyan-400">{type}</span>,
description,
])}
/>
<SectionHeader level={3} id="accessing-images" className="mt-8 mb-4">
Accessing Images
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
Use <InlineCode>storageUrl</InlineCode> for direct CDN access:
</p>
<CodeBlock
code={`<!-- Direct access via UUID (fastest, cached) -->
<img src="https://cdn.banatie.app/default/my-project/img/7c4ccf47-..." />
<!-- Access via alias (requires API resolution) -->
<img src="https://cdn.banatie.app/default/my-project/img/@brand-logo" />`}
language="html"
filename="Usage Examples"
/>
<TipBox variant="compact" type="info">
<strong>Performance:</strong> UUID URLs are served directly from CDN.
Alias URLs require API resolution but enable dynamic reassignment.
</TipBox>
</section>
</DocPage>
);
}