Merge branch 'docs-v1'

This commit is contained in:
Oleg Proskurin 2025-12-31 20:28:27 +07:00
commit 33b01c03a8
56 changed files with 3556 additions and 811 deletions

View File

@ -6,9 +6,11 @@ import { ApiKeyProvider } from '@/components/shared/ApiKeyWidget/apikey-context'
import { PageProvider } from '@/contexts/page-context';
const navItems = [
{ label: 'Text to Image', href: '/demo/tti' },
{ label: 'Upload', href: '/demo/upload' },
{ label: 'Gallery', href: '/demo/gallery' },
{ label: 'API', href: '/docs' },
{ label: 'SDK', href: '#', disabled: true },
{ label: 'MCP', href: '#', disabled: true },
{ label: 'CLI', href: '#', disabled: true },
{ label: 'Lab', href: '/demo/tti' },
];
export default function DemoLayout({ children }: { children: React.ReactNode }) {

View File

@ -0,0 +1,334 @@
'use client';
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,
ResponseBlock,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'overview', text: 'Overview', level: 2 },
{ id: 'list-flows', text: 'List Flows', level: 2 },
{ id: 'get-flow', text: 'Get Flow', level: 2 },
{ id: 'list-flow-generations', text: 'List Flow Generations', level: 2 },
{ id: 'list-flow-images', text: 'List Flow Images', level: 2 },
{ id: 'update-flow-aliases', text: 'Update Flow Aliases', level: 2 },
{ id: 'remove-flow-alias', text: 'Remove Flow Alias', level: 2 },
{ id: 'regenerate-flow', text: 'Regenerate Flow', level: 2 },
{ id: 'delete-flow', text: 'Delete Flow', level: 2 },
{ id: 'next-steps', text: 'Next Steps', level: 2 },
];
export default function FlowsAPIPage() {
return (
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'API Reference', href: '/docs/api' },
{ label: 'Flows' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/generation',
title: 'Image Generation Guide',
description: 'Learn about chaining generations with flows.',
accent: 'primary',
},
{
href: '/docs/api/generations',
title: 'Generations API',
description: 'Create generations within flows.',
accent: 'secondary',
},
],
}}
>
<Hero
title="Flows API"
subtitle="Manage generation chains and flow-scoped aliases."
/>
<section id="overview" className="mb-12">
<SectionHeader level={2} id="overview">
Overview
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
Flows group related generations together. They're created automatically when you chain generations using the same flowId.
</p>
<p className="text-gray-300 leading-relaxed">
Flows also support flow-scoped aliases named references to images that are unique within a flow but don't conflict with project-level aliases.
</p>
</section>
<section id="list-flows" className="mb-12">
<SectionHeader level={2} id="list-flows">
List Flows
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Retrieve all flows for your project with computed counts.
</p>
<EndpointCard
method="GET"
endpoint="/api/v1/flows"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Query Parameters</h4>
<Table
headers={['Parameter', 'Type', 'Description']}
rows={[
[<InlineCode key="p">limit</InlineCode>, 'number', 'Results per page (default: 20, max: 100)'],
[<InlineCode key="p">offset</InlineCode>, 'number', 'Number of results to skip'],
]}
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl "https://api.banatie.app/api/v1/flows?limit=10" \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Response</h4>
<ResponseBlock
status="success"
statusCode={200}
statusLabel="200 OK"
content={`{
"success": true,
"data": [
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"aliases": {"@hero": "img-uuid-1", "@background": "img-uuid-2"},
"generationCount": 5,
"imageCount": 5,
"createdAt": "2025-01-15T10:00:00Z",
"updatedAt": "2025-01-15T10:30:00Z"
}
],
"pagination": {
"total": 1,
"limit": 10,
"offset": 0,
"hasMore": false
}
}`}
/>
</div>
</section>
<section id="get-flow" className="mb-12">
<SectionHeader level={2} id="get-flow">
Get Flow
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Retrieve a single flow with detailed statistics.
</p>
<EndpointCard
method="GET"
endpoint="/api/v1/flows/:id"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl https://api.banatie.app/api/v1/flows/770e8400-e29b-41d4-a716-446655440002 \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="list-flow-generations" className="mb-12">
<SectionHeader level={2} id="list-flow-generations">
List Flow Generations
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Retrieve all generations in a specific flow.
</p>
<EndpointCard
method="GET"
endpoint="/api/v1/flows/:id/generations"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl "https://api.banatie.app/api/v1/flows/770e8400-e29b-41d4-a716-446655440002/generations?limit=20" \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="list-flow-images" className="mb-12">
<SectionHeader level={2} id="list-flow-images">
List Flow Images
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Retrieve all images (generated and uploaded) in a flow.
</p>
<EndpointCard
method="GET"
endpoint="/api/v1/flows/:id/images"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl "https://api.banatie.app/api/v1/flows/770e8400-e29b-41d4-a716-446655440002/images" \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="update-flow-aliases" className="mb-12">
<SectionHeader level={2} id="update-flow-aliases">
Update Flow Aliases
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Add or update flow-scoped aliases. Aliases are merged with existing ones.
</p>
<EndpointCard
method="PUT"
endpoint="/api/v1/flows/:id/aliases"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Request Body</h4>
<Table
headers={['Parameter', 'Type', 'Description']}
rows={[
[<InlineCode key="p">aliases</InlineCode>, 'object', 'Key-value pairs of aliases to add/update'],
]}
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl -X PUT https://api.banatie.app/api/v1/flows/770e8400-e29b-41d4-a716-446655440002/aliases \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"aliases": {
"@hero": "image-id-123",
"@background": "image-id-456"
}
}'`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="remove-flow-alias" className="mb-12">
<SectionHeader level={2} id="remove-flow-alias">
Remove Flow Alias
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Remove a specific alias from a flow.
</p>
<EndpointCard
method="DELETE"
endpoint="/api/v1/flows/:id/aliases/:alias"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl -X DELETE https://api.banatie.app/api/v1/flows/770e8400-e29b-41d4-a716-446655440002/aliases/@hero \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="regenerate-flow" className="mb-12">
<SectionHeader level={2} id="regenerate-flow">
Regenerate Flow
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Regenerate the most recent generation in the flow.
</p>
<EndpointCard
method="POST"
endpoint="/api/v1/flows/:id/regenerate"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl -X POST https://api.banatie.app/api/v1/flows/770e8400-e29b-41d4-a716-446655440002/regenerate \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="delete-flow" className="mb-12">
<SectionHeader level={2} id="delete-flow">
Delete Flow
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Delete a flow with cascade deletion. Images with project aliases are preserved.
</p>
<EndpointCard
method="DELETE"
endpoint="/api/v1/flows/:id"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl -X DELETE https://api.banatie.app/api/v1/flows/770e8400-e29b-41d4-a716-446655440002 \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
<div className="mt-6">
<TipBox variant="compact" type="warning">
Deleting a flow removes all generations and images in it. Images with project aliases are preserved (unlinked from the flow).
</TipBox>
</div>
</section>
</DocPage>
);
}

View File

@ -0,0 +1,326 @@
'use client';
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,
ResponseBlock,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'create-generation', text: 'Create Generation', level: 2 },
{ id: 'list-generations', text: 'List Generations', level: 2 },
{ id: 'get-generation', text: 'Get Generation', level: 2 },
{ id: 'update-generation', text: 'Update Generation', level: 2 },
{ id: 'regenerate', text: 'Regenerate', level: 2 },
{ id: 'delete-generation', text: 'Delete Generation', level: 2 },
{ id: 'next-steps', text: 'Next Steps', level: 2 },
];
export default function GenerationsAPIPage() {
return (
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'API Reference', href: '/docs/api' },
{ label: 'Generations' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/generation',
title: 'Image Generation Guide',
description: 'Concepts and examples for image generation.',
accent: 'primary',
},
{
href: '/docs/api/images',
title: 'Images API',
description: 'Upload and manage images.',
accent: 'secondary',
},
],
}}
>
<Hero
title="Generations API"
subtitle="Create and manage AI image generations."
/>
<section id="create-generation" className="mb-12">
<SectionHeader level={2} id="create-generation">
Create Generation
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Generate a new image from a text prompt.
</p>
<EndpointCard
method="POST"
endpoint="/api/v1/generations"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Request Body</h4>
<Table
headers={['Parameter', 'Type', 'Required', 'Description']}
rows={[
[
<InlineCode key="p">prompt</InlineCode>,
<span key="t" className="text-cyan-400">string</span>,
<span key="r" className="text-green-400">Yes</span>,
'Text description of the image to generate',
],
[
<InlineCode key="p">aspectRatio</InlineCode>,
<span key="t" className="text-cyan-400">string</span>,
<span key="r" className="text-gray-500">No</span>,
'1:1, 16:9, 9:16, 3:2, 21:9 (default: 1:1)',
],
[
<InlineCode key="p">referenceImages</InlineCode>,
<span key="t" className="text-cyan-400">string[]</span>,
<span key="r" className="text-gray-500">No</span>,
'Array of image IDs or @aliases to use as references',
],
[
<InlineCode key="p">flowId</InlineCode>,
<span key="t" className="text-cyan-400">string</span>,
<span key="r" className="text-gray-500">No</span>,
'Associate with existing flow',
],
[
<InlineCode key="p">alias</InlineCode>,
<span key="t" className="text-cyan-400">string</span>,
<span key="r" className="text-gray-500">No</span>,
'Project-scoped alias (@custom-name)',
],
[
<InlineCode key="p">autoEnhance</InlineCode>,
<span key="t" className="text-cyan-400">boolean</span>,
<span key="r" className="text-gray-500">No</span>,
'Enable prompt enhancement (default: true)',
],
[
<InlineCode key="p">meta</InlineCode>,
<span key="t" className="text-cyan-400">object</span>,
<span key="r" className="text-gray-500">No</span>,
'Custom metadata',
],
]}
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl -X POST https://api.banatie.app/api/v1/generations \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"prompt": "a serene mountain landscape at sunset",
"aspectRatio": "16:9"
}'`}
language="bash"
filename="Request"
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Response</h4>
<ResponseBlock
status="success"
statusCode={201}
statusLabel="201 Created"
content={`{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "success",
"prompt": "a serene mountain landscape at sunset",
"aspectRatio": "16:9",
"outputImage": {
"id": "8a3b2c1d-4e5f-6789-abcd-ef0123456789",
"storageUrl": "https://cdn.banatie.app/my-org/my-project/img/8a3b2c1d-4e5f-6789-abcd-ef0123456789",
"width": 1792,
"height": 1008
},
"flowId": "770e8400-e29b-41d4-a716-446655440002",
"createdAt": "2025-01-15T10:30:00Z"
}
}`}
/>
</div>
</section>
<section id="list-generations" className="mb-12">
<SectionHeader level={2} id="list-generations">
List Generations
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Retrieve all generations for your project with optional filtering.
</p>
<EndpointCard
method="GET"
endpoint="/api/v1/generations"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Query Parameters</h4>
<Table
headers={['Parameter', 'Type', 'Description']}
rows={[
[<InlineCode key="p">flowId</InlineCode>, 'string', 'Filter by flow ID'],
[<InlineCode key="p">status</InlineCode>, 'string', 'Filter by status: pending, processing, success, failed'],
[<InlineCode key="p">limit</InlineCode>, 'number', 'Results per page (default: 20, max: 100)'],
[<InlineCode key="p">offset</InlineCode>, 'number', 'Number of results to skip'],
]}
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl "https://api.banatie.app/api/v1/generations?limit=10&status=success" \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="get-generation" className="mb-12">
<SectionHeader level={2} id="get-generation">
Get Generation
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Retrieve a single generation by ID.
</p>
<EndpointCard
method="GET"
endpoint="/api/v1/generations/:id"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl https://api.banatie.app/api/v1/generations/550e8400-e29b-41d4-a716-446655440000 \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="update-generation" className="mb-12">
<SectionHeader level={2} id="update-generation">
Update Generation
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Update generation parameters. Changing prompt or aspectRatio triggers automatic regeneration.
</p>
<EndpointCard
method="PUT"
endpoint="/api/v1/generations/:id"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Request Body</h4>
<Table
headers={['Parameter', 'Type', 'Description']}
rows={[
[<InlineCode key="p">prompt</InlineCode>, 'string', 'New prompt (triggers regeneration)'],
[<InlineCode key="p">aspectRatio</InlineCode>, 'string', 'New aspect ratio (triggers regeneration)'],
[<InlineCode key="p">flowId</InlineCode>, 'string | null', 'Change flow association'],
[<InlineCode key="p">meta</InlineCode>, 'object', 'Update custom metadata'],
]}
/>
</div>
<div className="mt-6">
<TipBox variant="compact" type="info">
Changing <InlineCode>prompt</InlineCode> or <InlineCode>aspectRatio</InlineCode> triggers a new generation. The image ID and URL remain the same only the content changes.
</TipBox>
</div>
</section>
<section id="regenerate" className="mb-12">
<SectionHeader level={2} id="regenerate">
Regenerate
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Create a new image using the exact same parameters. Useful for getting a different result or recovering from failures.
</p>
<EndpointCard
method="POST"
endpoint="/api/v1/generations/:id/regenerate"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl -X POST https://api.banatie.app/api/v1/generations/550e8400-e29b-41d4-a716-446655440000/regenerate \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="delete-generation" className="mb-12">
<SectionHeader level={2} id="delete-generation">
Delete Generation
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Delete a generation and its output image. Images with project aliases are preserved.
</p>
<EndpointCard
method="DELETE"
endpoint="/api/v1/generations/:id"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl -X DELETE https://api.banatie.app/api/v1/generations/550e8400-e29b-41d4-a716-446655440000 \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Response</h4>
<ResponseBlock
status="success"
statusCode={200}
statusLabel="200 OK"
content={`{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000"
}
}`}
/>
</div>
</section>
</DocPage>
);
}

View File

@ -0,0 +1,361 @@
'use client';
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,
ResponseBlock,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'upload-image', text: 'Upload Image', level: 2 },
{ id: 'list-images', text: 'List Images', level: 2 },
{ id: 'get-image', text: 'Get Image', level: 2 },
{ id: 'update-image', text: 'Update Image', level: 2 },
{ id: 'assign-alias', text: 'Assign Alias', level: 2 },
{ id: 'delete-image', text: 'Delete Image', level: 2 },
{ id: 'cdn-endpoints', text: 'CDN Endpoints', level: 2 },
{ id: 'next-steps', text: 'Next Steps', level: 2 },
];
export default function ImagesAPIPage() {
return (
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'API Reference', href: '/docs/api' },
{ label: 'Images' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/images',
title: 'Working with Images Guide',
description: 'Concepts and examples for image management.',
accent: 'primary',
},
{
href: '/docs/api/generations',
title: 'Generations API',
description: 'Create AI-generated images.',
accent: 'secondary',
},
],
}}
>
<Hero
title="Images API"
subtitle="Upload and manage images for your project."
/>
<section id="upload-image" className="mb-12">
<SectionHeader level={2} id="upload-image">
Upload Image
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Upload an image file to your project storage.
</p>
<EndpointCard
method="POST"
endpoint="/api/v1/images/upload"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Form Data</h4>
<Table
headers={['Parameter', 'Type', 'Required', 'Description']}
rows={[
[
<InlineCode key="p">file</InlineCode>,
<span key="t" className="text-cyan-400">file</span>,
<span key="r" className="text-green-400">Yes</span>,
'Image file (max 5MB, JPEG/PNG/WebP)',
],
[
<InlineCode key="p">alias</InlineCode>,
<span key="t" className="text-cyan-400">string</span>,
<span key="r" className="text-gray-500">No</span>,
'Project-scoped alias (@custom-name)',
],
[
<InlineCode key="p">flowId</InlineCode>,
<span key="t" className="text-cyan-400">string</span>,
<span key="r" className="text-gray-500">No</span>,
'Associate with flow',
],
[
<InlineCode key="p">meta</InlineCode>,
<span key="t" className="text-cyan-400">string</span>,
<span key="r" className="text-gray-500">No</span>,
'Custom metadata (JSON string)',
],
]}
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl -X POST https://api.banatie.app/api/v1/images/upload \\
-H "X-API-Key: YOUR_API_KEY" \\
-F "file=@your-image.png" \\
-F "alias=@brand-logo"`}
language="bash"
filename="Request"
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Response</h4>
<ResponseBlock
status="success"
statusCode={201}
statusLabel="201 Created"
content={`{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"storageUrl": "https://cdn.banatie.app/my-org/my-project/img/550e8400-e29b-41d4-a716-446655440000",
"alias": "@brand-logo",
"source": "uploaded",
"width": 512,
"height": 512,
"mimeType": "image/png",
"fileSize": 24576,
"createdAt": "2025-01-15T10:30:00Z"
}
}`}
/>
</div>
</section>
<section id="list-images" className="mb-12">
<SectionHeader level={2} id="list-images">
List Images
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Retrieve all images in your project with optional filtering.
</p>
<EndpointCard
method="GET"
endpoint="/api/v1/images"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Query Parameters</h4>
<Table
headers={['Parameter', 'Type', 'Description']}
rows={[
[<InlineCode key="p">flowId</InlineCode>, 'string', 'Filter by flow ID'],
[<InlineCode key="p">source</InlineCode>, 'string', 'Filter by source: generated, uploaded'],
[<InlineCode key="p">alias</InlineCode>, 'string', 'Filter by exact alias match'],
[<InlineCode key="p">limit</InlineCode>, 'number', 'Results per page (default: 20, max: 100)'],
[<InlineCode key="p">offset</InlineCode>, 'number', 'Number of results to skip'],
]}
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl "https://api.banatie.app/api/v1/images?source=uploaded&limit=20" \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="get-image" className="mb-12">
<SectionHeader level={2} id="get-image">
Get Image
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Retrieve a single image by ID or alias.
</p>
<EndpointCard
method="GET"
endpoint="/api/v1/images/:id_or_alias"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Requests</h4>
<CodeBlock
code={`# By UUID
curl https://api.banatie.app/api/v1/images/550e8400-e29b-41d4-a716-446655440000 \\
-H "X-API-Key: YOUR_API_KEY"
# By alias
curl https://api.banatie.app/api/v1/images/@brand-logo \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="update-image" className="mb-12">
<SectionHeader level={2} id="update-image">
Update Image
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Update image metadata (focal point and custom metadata).
</p>
<EndpointCard
method="PUT"
endpoint="/api/v1/images/:id_or_alias"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Request Body</h4>
<Table
headers={['Parameter', 'Type', 'Description']}
rows={[
[<InlineCode key="p">focalPoint</InlineCode>, 'object', 'Focal point for cropping {x: 0-1, y: 0-1}'],
[<InlineCode key="p">meta</InlineCode>, 'object', 'Custom metadata'],
]}
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl -X PUT https://api.banatie.app/api/v1/images/550e8400-e29b-41d4-a716-446655440000 \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"focalPoint": {"x": 0.5, "y": 0.3},
"meta": {"category": "hero"}
}'`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="assign-alias" className="mb-12">
<SectionHeader level={2} id="assign-alias">
Assign Alias
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Assign or remove a project-scoped alias from an image.
</p>
<EndpointCard
method="PUT"
endpoint="/api/v1/images/:id_or_alias/alias"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Request Body</h4>
<Table
headers={['Parameter', 'Type', 'Description']}
rows={[
[<InlineCode key="p">alias</InlineCode>, 'string | null', 'Alias to assign (@name) or null to remove'],
]}
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Requests</h4>
<CodeBlock
code={`# Assign alias
curl -X PUT https://api.banatie.app/api/v1/images/550e8400-e29b-41d4-a716-446655440000/alias \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{"alias": "@hero-background"}'
# Remove alias
curl -X PUT https://api.banatie.app/api/v1/images/550e8400-e29b-41d4-a716-446655440000/alias \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{"alias": null}'`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="delete-image" className="mb-12">
<SectionHeader level={2} id="delete-image">
Delete Image
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Permanently delete an image from storage.
</p>
<EndpointCard
method="DELETE"
endpoint="/api/v1/images/:id_or_alias"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl -X DELETE https://api.banatie.app/api/v1/images/550e8400-e29b-41d4-a716-446655440000 \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
<div className="mt-6">
<TipBox variant="compact" type="warning">
Deletion is permanent. The image file and all references are removed from storage.
</TipBox>
</div>
</section>
<section id="cdn-endpoints" className="mb-12">
<SectionHeader level={2} id="cdn-endpoints">
CDN Endpoints
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Access images directly via CDN (public, no authentication required):
</p>
<div className="space-y-6">
<div>
<h4 className="text-sm font-semibold text-white mb-3">By Image ID</h4>
<CodeBlock
code={`GET https://cdn.banatie.app/{org}/{project}/img/{imageId}`}
language="text"
filename="CDN by ID"
/>
</div>
<div>
<h4 className="text-sm font-semibold text-white mb-3">By Alias</h4>
<CodeBlock
code={`GET https://cdn.banatie.app/{org}/{project}/img/@{alias}`}
language="text"
filename="CDN by Alias"
/>
</div>
</div>
<div className="mt-6">
<TipBox variant="compact" type="info">
CDN URLs are public and don't require authentication. They return image bytes directly with appropriate caching headers.
</TipBox>
</div>
</section>
</DocPage>
);
}

View File

@ -0,0 +1,419 @@
'use client';
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,
ResponseBlock,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'overview', text: 'Overview', level: 2 },
{ id: 'create-scope', text: 'Create Scope', level: 2 },
{ id: 'list-scopes', text: 'List Scopes', level: 2 },
{ id: 'get-scope', text: 'Get Scope', level: 2 },
{ id: 'update-scope', text: 'Update Scope', level: 2 },
{ id: 'regenerate-scope', text: 'Regenerate Scope', level: 2 },
{ id: 'delete-scope', text: 'Delete Scope', level: 2 },
{ id: 'cdn-live-endpoint', text: 'CDN Live Endpoint', level: 2 },
{ id: 'next-steps', text: 'Next Steps', level: 2 },
];
export default function LiveScopesAPIPage() {
return (
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'API Reference', href: '/docs/api' },
{ label: 'Live Scopes' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/live-urls',
title: 'Live URLs Guide',
description: 'Learn about live URL generation.',
accent: 'primary',
},
{
href: '/docs/api/generations',
title: 'Generations API',
description: 'Full control via the generations API.',
accent: 'secondary',
},
],
}}
>
<Hero
title="Live Scopes API"
subtitle="Manage scopes for live URL generation."
/>
<section id="overview" className="mb-12">
<SectionHeader level={2} id="overview">
Overview
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
Live scopes organize live URL generations. Each scope has its own generation limit and can be configured independently.
</p>
<p className="text-gray-300 leading-relaxed">
Scopes are auto-created on first use, but you can pre-configure them via this API to set custom limits.
</p>
</section>
<section id="create-scope" className="mb-12">
<SectionHeader level={2} id="create-scope">
Create Scope
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Create a new live scope with custom settings.
</p>
<EndpointCard
method="POST"
endpoint="/api/v1/live/scopes"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Request Body</h4>
<Table
headers={['Parameter', 'Type', 'Required', 'Description']}
rows={[
[
<InlineCode key="p">slug</InlineCode>,
<span key="t" className="text-cyan-400">string</span>,
<span key="r" className="text-green-400">Yes</span>,
'Unique scope identifier (alphanumeric + hyphens + underscores)',
],
[
<InlineCode key="p">allowNewGenerations</InlineCode>,
<span key="t" className="text-cyan-400">boolean</span>,
<span key="r" className="text-gray-500">No</span>,
'Allow new generations (default: true)',
],
[
<InlineCode key="p">newGenerationsLimit</InlineCode>,
<span key="t" className="text-cyan-400">number</span>,
<span key="r" className="text-gray-500">No</span>,
'Maximum generations allowed (default: 30)',
],
[
<InlineCode key="p">meta</InlineCode>,
<span key="t" className="text-cyan-400">object</span>,
<span key="r" className="text-gray-500">No</span>,
'Custom metadata',
],
]}
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl -X POST https://api.banatie.app/api/v1/live/scopes \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"slug": "hero-section",
"allowNewGenerations": true,
"newGenerationsLimit": 50,
"meta": {"description": "Hero section images"}
}'`}
language="bash"
filename="Request"
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Response</h4>
<ResponseBlock
status="success"
statusCode={201}
statusLabel="201 Created"
content={`{
"success": true,
"data": {
"id": "880e8400-e29b-41d4-a716-446655440003",
"slug": "hero-section",
"allowNewGenerations": true,
"newGenerationsLimit": 50,
"currentGenerations": 0,
"lastGeneratedAt": null,
"meta": {"description": "Hero section images"},
"createdAt": "2025-01-15T10:30:00Z"
}
}`}
/>
</div>
</section>
<section id="list-scopes" className="mb-12">
<SectionHeader level={2} id="list-scopes">
List Scopes
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Retrieve all live scopes for your project.
</p>
<EndpointCard
method="GET"
endpoint="/api/v1/live/scopes"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Query Parameters</h4>
<Table
headers={['Parameter', 'Type', 'Description']}
rows={[
[<InlineCode key="p">slug</InlineCode>, 'string', 'Filter by exact slug match'],
[<InlineCode key="p">limit</InlineCode>, 'number', 'Results per page (default: 20, max: 100)'],
[<InlineCode key="p">offset</InlineCode>, 'number', 'Number of results to skip'],
]}
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl "https://api.banatie.app/api/v1/live/scopes?limit=20" \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="get-scope" className="mb-12">
<SectionHeader level={2} id="get-scope">
Get Scope
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Retrieve a single scope with statistics.
</p>
<EndpointCard
method="GET"
endpoint="/api/v1/live/scopes/:slug"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl https://api.banatie.app/api/v1/live/scopes/hero-section \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="update-scope" className="mb-12">
<SectionHeader level={2} id="update-scope">
Update Scope
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Update scope settings. Changes take effect immediately.
</p>
<EndpointCard
method="PUT"
endpoint="/api/v1/live/scopes/:slug"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Request Body</h4>
<Table
headers={['Parameter', 'Type', 'Description']}
rows={[
[<InlineCode key="p">allowNewGenerations</InlineCode>, 'boolean', 'Allow/disallow new generations'],
[<InlineCode key="p">newGenerationsLimit</InlineCode>, 'number', 'Update generation limit'],
[<InlineCode key="p">meta</InlineCode>, 'object', 'Update custom metadata'],
]}
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl -X PUT https://api.banatie.app/api/v1/live/scopes/hero-section \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"allowNewGenerations": false,
"newGenerationsLimit": 100
}'`}
language="bash"
filename="Request"
/>
</div>
</section>
<section id="regenerate-scope" className="mb-12">
<SectionHeader level={2} id="regenerate-scope">
Regenerate Scope
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Regenerate images in a scope. Can regenerate a specific image or all images.
</p>
<EndpointCard
method="POST"
endpoint="/api/v1/live/scopes/:slug/regenerate"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Request Body</h4>
<Table
headers={['Parameter', 'Type', 'Description']}
rows={[
[<InlineCode key="p">imageId</InlineCode>, 'string', 'Specific image to regenerate (omit for all)'],
]}
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Requests</h4>
<CodeBlock
code={`# Regenerate specific image
curl -X POST https://api.banatie.app/api/v1/live/scopes/hero-section/regenerate \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{"imageId": "550e8400-e29b-41d4-a716-446655440000"}'
# Regenerate all images in scope
curl -X POST https://api.banatie.app/api/v1/live/scopes/hero-section/regenerate \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{}'`}
language="bash"
filename="Request"
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Response</h4>
<ResponseBlock
status="success"
statusCode={200}
statusLabel="200 OK"
content={`{
"success": true,
"data": {
"regenerated": 3,
"images": [...]
}
}`}
/>
</div>
</section>
<section id="delete-scope" className="mb-12">
<SectionHeader level={2} id="delete-scope">
Delete Scope
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Delete a scope and all its cached images.
</p>
<EndpointCard
method="DELETE"
endpoint="/api/v1/live/scopes/:slug"
baseUrl="https://api.banatie.app"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example Request</h4>
<CodeBlock
code={`curl -X DELETE https://api.banatie.app/api/v1/live/scopes/hero-section \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Request"
/>
</div>
<div className="mt-6">
<TipBox variant="compact" type="warning">
Deleting a scope permanently removes all cached images in it. This cannot be undone.
</TipBox>
</div>
</section>
<section id="cdn-live-endpoint" className="mb-12">
<SectionHeader level={2} id="cdn-live-endpoint">
CDN Live Endpoint
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Public endpoint for live URL generation (no authentication required):
</p>
<CodeBlock
code={`GET https://cdn.banatie.app/{org}/{project}/live/{scope}?prompt=...`}
language="text"
filename="Live URL Format"
/>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Query Parameters</h4>
<Table
headers={['Parameter', 'Required', 'Description']}
rows={[
[
<InlineCode key="p">prompt</InlineCode>,
<span key="r" className="text-green-400">Yes</span>,
'Text description of the image to generate',
],
[
<InlineCode key="p">aspectRatio</InlineCode>,
<span key="r" className="text-gray-500">No</span>,
'Image ratio (default: 1:1)',
],
[
<InlineCode key="p">autoEnhance</InlineCode>,
<span key="r" className="text-gray-500">No</span>,
'Enable prompt enhancement',
],
[
<InlineCode key="p">template</InlineCode>,
<span key="r" className="text-gray-500">No</span>,
'Enhancement template to use',
],
]}
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Example</h4>
<CodeBlock
code={`https://cdn.banatie.app/my-org/my-project/live/hero-section?prompt=mountain+landscape&aspectRatio=16:9`}
language="text"
filename="Live URL Example"
/>
</div>
<div className="mt-6">
<h4 className="text-sm font-semibold text-white mb-4">Response Headers</h4>
<Table
headers={['Header', 'Description']}
rows={[
[<InlineCode key="h">X-Cache-Status</InlineCode>, 'HIT (cached) or MISS (generated)'],
[<InlineCode key="h">X-Scope</InlineCode>, 'Scope identifier'],
[<InlineCode key="h">X-Image-Id</InlineCode>, 'Image UUID'],
[<InlineCode key="h">X-RateLimit-Remaining</InlineCode>, 'Remaining IP rate limit (on MISS)'],
]}
/>
</div>
</section>
</DocPage>
);
}

View File

@ -0,0 +1,239 @@
'use client';
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,
LinkCard,
LinkCardGrid,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'base-url', text: 'Base URL', level: 2 },
{ id: 'authentication', text: 'Authentication', level: 2 },
{ id: 'response-format', text: 'Response Format', level: 2 },
{ id: 'error-codes', text: 'Common Error Codes', level: 2 },
{ id: 'rate-limits', text: 'Rate Limits', level: 2 },
{ id: 'endpoints', text: 'Endpoints', level: 2 },
{ id: 'next-steps', text: 'Next Steps', level: 2 },
];
export default function APIOverviewPage() {
return (
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'API Reference' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/api/generations',
title: 'Generations API',
description: 'Create and manage image generations.',
accent: 'primary',
},
{
href: '/docs/api/images',
title: 'Images API',
description: 'Upload and organize images.',
accent: 'secondary',
},
],
}}
>
<Hero
title="API Reference"
subtitle="Complete REST API reference for Banatie. All endpoints, parameters, and response formats."
/>
<section id="base-url" className="mb-12">
<SectionHeader level={2} id="base-url">
Base URL
</SectionHeader>
<CodeBlock
code={`https://api.banatie.app`}
language="text"
filename="Base URL"
/>
</section>
<section id="authentication" className="mb-12">
<SectionHeader level={2} id="authentication">
Authentication
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
All endpoints require the <InlineCode>X-API-Key</InlineCode> header:
</p>
<CodeBlock
code={`X-API-Key: your_api_key_here`}
language="text"
filename="Header"
/>
<p className="text-gray-300 leading-relaxed mt-6">
See <a href="/docs/authentication" className="text-purple-400 hover:underline">Authentication</a> for details on obtaining and using API keys.
</p>
</section>
<section id="response-format" className="mb-12">
<SectionHeader level={2} id="response-format">
Response Format
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
All responses follow a consistent JSON structure:
</p>
<div className="space-y-6">
<div>
<p className="text-sm font-medium text-gray-300 mb-3">Success Response:</p>
<CodeBlock
code={`{
"success": true,
"data": { ... }
}`}
language="json"
filename="Success"
/>
</div>
<div>
<p className="text-sm font-medium text-gray-300 mb-3">Error Response:</p>
<CodeBlock
code={`{
"success": false,
"error": {
"message": "Error description",
"code": "ERROR_CODE"
}
}`}
language="json"
filename="Error"
/>
</div>
<div>
<p className="text-sm font-medium text-gray-300 mb-3">Paginated Response:</p>
<CodeBlock
code={`{
"success": true,
"data": [ ... ],
"pagination": {
"total": 100,
"limit": 20,
"offset": 0,
"hasMore": true
}
}`}
language="json"
filename="Paginated"
/>
</div>
</div>
</section>
<section id="error-codes" className="mb-12">
<SectionHeader level={2} id="error-codes">
Common Error Codes
</SectionHeader>
<Table
headers={['Status', 'Code', 'Description']}
rows={[
[
<InlineCode key="s" color="error">400</InlineCode>,
'VALIDATION_ERROR',
'Missing or invalid parameters',
],
[
<InlineCode key="s" color="error">401</InlineCode>,
'UNAUTHORIZED',
'Missing or invalid API key',
],
[
<InlineCode key="s" color="error">404</InlineCode>,
'*_NOT_FOUND',
'Requested resource not found',
],
[
<InlineCode key="s" color="error">409</InlineCode>,
'ALIAS_CONFLICT',
'Alias already exists',
],
[
<InlineCode key="s" color="error">429</InlineCode>,
'RATE_LIMIT_EXCEEDED',
'Too many requests',
],
[
<InlineCode key="s" color="error">500</InlineCode>,
'INTERNAL_ERROR',
'Server error',
],
]}
/>
</section>
<section id="rate-limits" className="mb-12">
<SectionHeader level={2} id="rate-limits">
Rate Limits
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
API requests are rate limited to 100 requests per hour per API key.
</p>
<p className="text-gray-300 leading-relaxed mb-6">
Rate limit headers are included in every response:
</p>
<Table
headers={['Header', 'Description']}
rows={[
[<InlineCode key="h">X-RateLimit-Limit</InlineCode>, 'Maximum requests per hour'],
[<InlineCode key="h">X-RateLimit-Remaining</InlineCode>, 'Requests remaining in current window'],
[<InlineCode key="h">X-RateLimit-Reset</InlineCode>, 'Unix timestamp when limit resets'],
]}
/>
</section>
<section id="endpoints" className="mb-12">
<SectionHeader level={2} id="endpoints">
Endpoints
</SectionHeader>
<LinkCardGrid columns={2}>
<LinkCard
href="/docs/api/generations"
title="Generations"
description="Create and manage AI image generations"
accent="primary"
/>
<LinkCard
href="/docs/api/images"
title="Images"
description="Upload and organize images"
accent="secondary"
/>
<LinkCard
href="/docs/api/flows"
title="Flows"
description="Manage generation chains"
accent="primary"
/>
<LinkCard
href="/docs/api/live-scopes"
title="Live Scopes"
description="Control live URL generation"
accent="secondary"
/>
</LinkCardGrid>
</section>
</DocPage>
);
}

View File

@ -0,0 +1,124 @@
'use client';
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,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'early-access', text: 'Early Access', level: 2 },
{ id: 'using-your-api-key', text: 'Using Your API Key', level: 2 },
{ id: 'key-types', text: 'Key Types', level: 2 },
{ id: 'next-steps', text: 'Next Steps', level: 2 },
];
export default function AuthenticationPage() {
return (
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'Authentication' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/generation',
title: 'Start Generating',
description: 'Create your first AI-generated image.',
accent: 'primary',
},
{
href: '/docs/api',
title: 'API Reference',
description: 'Full endpoint documentation.',
accent: 'secondary',
},
],
}}
>
<Hero
title="Authentication"
subtitle="How to authenticate with Banatie API using API keys."
/>
<section id="early-access" className="mb-12">
<SectionHeader level={2} id="early-access">
Early Access
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
We're currently in early access phase. API keys are issued personally via email.
</p>
<p className="text-gray-300 leading-relaxed mb-6">
<strong className="text-white">To request access:</strong> Sign up at <a href="https://banatie.app" className="text-purple-400 hover:underline">banatie.app</a>. We'll send your API key within 24 hours.
</p>
</section>
<section id="using-your-api-key" className="mb-12">
<SectionHeader level={2} id="using-your-api-key">
Using Your API Key
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
All API requests require the <InlineCode>X-API-Key</InlineCode> header:
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.app/api/v1/generations \\
-H "X-API-Key: your_key_here" \\
-H "Content-Type: application/json" \\
-d '{"prompt": "a sunset over the ocean"}'`}
language="bash"
filename="Authenticated Request"
/>
<div className="mt-6">
<TipBox variant="prominent" type="warning">
<strong className="text-amber-300">Keep your API key secure.</strong> Don't commit it to version control or expose it in client-side code. Use environment variables in your applications.
</TipBox>
</div>
</section>
<section id="key-types" className="mb-12">
<SectionHeader level={2} id="key-types">
Key Types
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Banatie uses two types of API keys:
</p>
<Table
headers={['Type', 'Permissions', 'Expiration', 'Use Case']}
rows={[
[
<InlineCode key="t">Project Key</InlineCode>,
'Image generation, uploads, images',
<span key="e" className="text-amber-400">90 days</span>,
'Your application integration',
],
[
<InlineCode key="t">Master Key</InlineCode>,
'Full admin access, key management',
<span key="e" className="text-green-400">Never expires</span>,
'Server-side admin operations',
],
]}
/>
<p className="text-gray-300 leading-relaxed mt-6">
You'll receive a Project Key for your application. Master Keys are for administrative operations — you probably don't need one.
</p>
<div className="mt-6">
<TipBox variant="compact" type="info">
API key management dashboard coming soon. For now, contact us if you need to rotate your key.
</TipBox>
</div>
</section>
</DocPage>
);
}

View File

@ -0,0 +1,263 @@
'use client';
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,
ResponseBlock,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'basic-generation', text: 'Basic Generation', level: 2 },
{ id: 'aspect-ratios', text: 'Aspect Ratios', level: 2 },
{ id: 'prompt-templates', text: 'Prompt Templates', level: 2 },
{ id: 'reference-images', text: 'Using Reference Images', level: 2 },
{ id: 'continuing-generation', text: 'Continuing Generation', level: 2 },
{ id: 'regeneration', text: 'Regeneration', level: 2 },
{ id: 'next-steps', text: 'Next Steps', level: 2 },
];
export default function GenerationPage() {
return (
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'Image Generation' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/api/generations',
title: 'API Reference: Generations',
description: 'Full endpoint documentation for generations.',
accent: 'primary',
},
{
href: '/docs/images',
title: 'Working with Images',
description: 'Upload your own images and organize with aliases.',
accent: 'secondary',
},
],
}}
>
<Hero
title="Image Generation"
subtitle="Generate AI images from text prompts with support for references, templates, and chaining."
/>
<section id="basic-generation" className="mb-12">
<SectionHeader level={2} id="basic-generation">
Basic Generation
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Generate an image by sending a text prompt to the generations endpoint:
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.app/api/v1/generations \\
-H "Content-Type: application/json" \\
-H "X-API-Key: YOUR_API_KEY" \\
-d '{
"prompt": "a serene mountain landscape at sunset",
"aspectRatio": "16:9"
}'`}
language="bash"
filename="Create Generation"
/>
<p className="text-gray-300 leading-relaxed mt-6 mb-4">
The response contains your generated image immediately:
</p>
<ResponseBlock
status="success"
statusCode={201}
statusLabel="201 Created"
content={`{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "success",
"prompt": "a serene mountain landscape at sunset",
"aspectRatio": "16:9",
"outputImage": {
"id": "8a3b2c1d-4e5f-6789-abcd-ef0123456789",
"storageUrl": "https://cdn.banatie.app/my-org/my-project/img/8a3b2c1d-4e5f-6789-abcd-ef0123456789",
"width": 1792,
"height": 1008
},
"flowId": "770e8400-e29b-41d4-a716-446655440002"
}
}`}
/>
<p className="text-gray-300 leading-relaxed mt-6">
One request, one result. The <InlineCode>storageUrl</InlineCode> is your production-ready image, served via CDN.
</p>
</section>
<section id="aspect-ratios" className="mb-12">
<SectionHeader level={2} id="aspect-ratios">
Aspect Ratios
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Choose the aspect ratio that fits your use case:
</p>
<Table
headers={['Ratio', 'Dimensions', 'Best For']}
rows={[
[
<InlineCode key="ratio">1:1</InlineCode>,
'1024 x 1024',
'Social media posts, profile pictures, thumbnails',
],
[
<InlineCode key="ratio">16:9</InlineCode>,
'1792 x 1008',
'Blog headers, presentations, video thumbnails',
],
[
<InlineCode key="ratio">9:16</InlineCode>,
'1008 x 1792',
'Stories, mobile backgrounds, vertical banners',
],
[
<InlineCode key="ratio">3:2</InlineCode>,
'1536 x 1024',
'Photography-style images, print layouts',
],
[
<InlineCode key="ratio">21:9</InlineCode>,
'2016 x 864',
'Ultra-wide banners, cinematic headers',
],
]}
/>
<p className="text-gray-300 leading-relaxed mt-6">
Default is <InlineCode>1:1</InlineCode> if not specified.
</p>
</section>
<section id="prompt-templates" className="mb-12">
<SectionHeader level={2} id="prompt-templates">
Prompt Templates
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Templates improve your prompt for specific styles. Available templates:
</p>
<Table
headers={['Template', 'Description']}
rows={[
[<InlineCode key="t">general</InlineCode>, 'Balanced style for most use cases'],
[<InlineCode key="t">photorealistic</InlineCode>, 'Photo-like realism with natural lighting'],
[<InlineCode key="t">illustration</InlineCode>, 'Artistic illustration style'],
[<InlineCode key="t">minimalist</InlineCode>, 'Clean, simple compositions'],
[<InlineCode key="t">sticker</InlineCode>, 'Sticker-style with clear edges'],
[<InlineCode key="t">product</InlineCode>, 'E-commerce product photography'],
[<InlineCode key="t">comic</InlineCode>, 'Comic book visual style'],
]}
/>
<div className="mt-6">
<TipBox variant="compact" type="info">
Template selection coming soon. Currently uses general style for all generations.
</TipBox>
</div>
</section>
<section id="reference-images" className="mb-12">
<SectionHeader level={2} id="reference-images">
Using Reference Images
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Add reference images for style guidance or context. Pass image IDs or aliases in the <InlineCode>referenceImages</InlineCode> array:
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.app/api/v1/generations \\
-H "Content-Type: application/json" \\
-H "X-API-Key: YOUR_API_KEY" \\
-d '{
"prompt": "product photo in this style",
"referenceImages": ["@brand-style", "@product-template"],
"aspectRatio": "1:1"
}'`}
language="bash"
filename="With References"
/>
<div className="mt-6">
<TipBox variant="compact" type="info">
<strong>Pro Tip:</strong> Use aliases like <InlineCode>@logo</InlineCode> instead of UUIDs. See <a href="/docs/images" className="text-purple-400 hover:underline">Working with Images</a> to learn about aliases.
</TipBox>
</div>
<p className="text-gray-300 leading-relaxed mt-6">
You can also mention aliases directly in your prompt text they're auto-detected:
</p>
<CodeBlock
code={`{
"prompt": "create a banner using @brand-colors and @logo style"
}`}
language="json"
filename="Auto-detected aliases"
/>
</section>
<section id="continuing-generation" className="mb-12">
<SectionHeader level={2} id="continuing-generation">
Continuing Generation
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Chain multiple generations together by passing the same <InlineCode>flowId</InlineCode>:
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.app/api/v1/generations \\
-H "Content-Type: application/json" \\
-H "X-API-Key: YOUR_API_KEY" \\
-d '{
"prompt": "same scene but at night",
"flowId": "770e8400-e29b-41d4-a716-446655440002"
}'`}
language="bash"
filename="Continue in Flow"
/>
<p className="text-gray-300 leading-relaxed mt-6">
Each response includes a <InlineCode>flowId</InlineCode> you can use to continue the sequence. Flows help organize related generations together.
</p>
</section>
<section id="regeneration" className="mb-12">
<SectionHeader level={2} id="regeneration">
Regeneration
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Want a different result with the same parameters? Regenerate an existing generation:
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.app/api/v1/generations/550e8400-e29b-41d4-a716-446655440000/regenerate \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Regenerate"
/>
<p className="text-gray-300 leading-relaxed mt-6">
Same prompt, new image. The generation ID and URL stay the same the image content is replaced.
</p>
</section>
</DocPage>
);
}

View File

@ -0,0 +1,214 @@
'use client';
import { TipBox } from '@/components/docs/shared/TipBox';
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
import { DocPage } from '@/components/docs/layout/DocPage';
import {
Hero,
SectionHeader,
InlineCode,
ResponseBlock,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'image-urls', text: 'Image URLs', level: 2 },
{ id: 'uploading-images', text: 'Uploading Images', level: 2 },
{ id: 'listing-images', text: 'Listing & Getting Images', level: 2 },
{ id: 'aliases', text: 'Aliases', level: 2 },
{ id: 'deleting-images', text: 'Deleting Images', level: 2 },
{ id: 'next-steps', text: 'Next Steps', level: 2 },
];
export default function ImagesPage() {
return (
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'Working with Images' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/api/images',
title: 'API Reference: Images',
description: 'Full endpoint documentation for images.',
accent: 'primary',
},
{
href: '/docs/generation',
title: 'Image Generation',
description: 'Use your images as references in generations.',
accent: 'secondary',
},
],
}}
>
<Hero
title="Working with Images"
subtitle="Upload, manage, and organize your images. CDN delivery, aliases, and image management."
/>
<section id="image-urls" className="mb-12">
<SectionHeader level={2} id="image-urls">
Image URLs
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
All images are served via CDN with this URL structure:
</p>
<CodeBlock
code={`https://cdn.banatie.app/{org}/{project}/img/{imageId}`}
language="text"
filename="CDN URL Format"
/>
<p className="text-gray-300 leading-relaxed mt-6">
URLs are permanent, fast, and cached globally. Use them directly in your applications.
</p>
</section>
<section id="uploading-images" className="mb-12">
<SectionHeader level={2} id="uploading-images">
Uploading Images
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Upload your own images for use as brand assets, references, or logos:
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.app/api/v1/images/upload \\
-H "X-API-Key: YOUR_API_KEY" \\
-F "file=@your-image.png" \\
-F "alias=@brand-logo"`}
language="bash"
filename="Upload Image"
/>
<p className="text-gray-300 leading-relaxed mt-6 mb-4">
Response includes the CDN URL and image details:
</p>
<ResponseBlock
status="success"
statusCode={201}
statusLabel="201 Created"
content={`{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"storageUrl": "https://cdn.banatie.app/my-org/my-project/img/550e8400-e29b-41d4-a716-446655440000",
"alias": "@brand-logo",
"source": "uploaded",
"width": 512,
"height": 512,
"mimeType": "image/png",
"fileSize": 24576
}
}`}
/>
</section>
<section id="listing-images" className="mb-12">
<SectionHeader level={2} id="listing-images">
Listing & Getting Images
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
List all images in your project:
</p>
<CodeBlock
code={`curl https://api.banatie.app/api/v1/images \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="List Images"
/>
<p className="text-gray-300 leading-relaxed mt-6 mb-6">
Get a specific image by ID or alias:
</p>
<CodeBlock
code={`# By UUID
curl https://api.banatie.app/api/v1/images/550e8400-e29b-41d4-a716-446655440000 \\
-H "X-API-Key: YOUR_API_KEY"
# By alias
curl https://api.banatie.app/api/v1/images/@brand-logo \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Get Image"
/>
</section>
<section id="aliases" className="mb-12">
<SectionHeader level={2} id="aliases">
Aliases
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Assign memorable names to images. Aliases start with <InlineCode>@</InlineCode> and make it easy to reference images without remembering UUIDs.
</p>
<CodeBlock
code={`curl -X PUT https://api.banatie.app/api/v1/images/550e8400-e29b-41d4-a716-446655440000/alias \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{"alias": "@hero-background"}'`}
language="bash"
filename="Assign Alias"
/>
<p className="text-gray-300 leading-relaxed mt-6 mb-6">
Access images via CDN using their alias:
</p>
<CodeBlock
code={`https://cdn.banatie.app/my-org/my-project/img/@hero-background`}
language="text"
filename="CDN Alias URL"
/>
<div className="mt-6">
<TipBox variant="compact" type="info">
<strong>Pro Tip:</strong> Use aliases for brand assets like <InlineCode>@logo</InlineCode>, <InlineCode>@brand-colors</InlineCode>. Reference them in generations without remembering UUIDs.
</TipBox>
</div>
<p className="text-gray-300 leading-relaxed mt-6 mb-4">
Remove an alias by setting it to null:
</p>
<CodeBlock
code={`curl -X PUT https://api.banatie.app/api/v1/images/550e8400-e29b-41d4-a716-446655440000/alias \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{"alias": null}'`}
language="bash"
filename="Remove Alias"
/>
</section>
<section id="deleting-images" className="mb-12">
<SectionHeader level={2} id="deleting-images">
Deleting Images
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Delete an image by ID or alias. This permanently removes the image from storage.
</p>
<CodeBlock
code={`curl -X DELETE https://api.banatie.app/api/v1/images/550e8400-e29b-41d4-a716-446655440000 \\
-H "X-API-Key: YOUR_API_KEY"`}
language="bash"
filename="Delete Image"
/>
<div className="mt-6">
<TipBox variant="compact" type="warning">
Deletion is permanent. The image file and all references are removed.
</TipBox>
</div>
</section>
</DocPage>
);
}

View File

@ -8,9 +8,11 @@ import { ApiKeyProvider } from '@/components/shared/ApiKeyWidget/apikey-context'
import { PageProvider } from '@/contexts/page-context';
const navItems = [
{ label: 'Documentation', href: '/docs' },
{ label: 'Demo', href: '/demo' },
{ label: 'Examples', href: '/docs/examples' },
{ label: 'API', href: '/docs' },
{ label: 'SDK', href: '#', disabled: true },
{ label: 'MCP', href: '#', disabled: true },
{ label: 'CLI', href: '#', disabled: true },
{ label: 'Lab', href: '#', disabled: true },
];
export default function DocsRootLayout({ children }: { children: React.ReactNode }) {

View File

@ -0,0 +1,258 @@
'use client';
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,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'the-concept', text: 'The Concept', level: 2 },
{ id: 'url-format', text: 'URL Format', level: 2 },
{ id: 'try-it', text: 'Try It', level: 2 },
{ id: 'caching-behavior', text: 'Caching Behavior', level: 2 },
{ id: 'scopes', text: 'Scopes', level: 2 },
{ id: 'rate-limits', text: 'Rate Limits', level: 2 },
{ id: 'use-cases', text: 'Use Cases', level: 2 },
{ id: 'next-steps', text: 'Next Steps', level: 2 },
];
export default function LiveUrlsPage() {
return (
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'Live URLs' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/api/live-scopes',
title: 'API Reference: Live Scopes',
description: 'Manage scopes and generation limits.',
accent: 'primary',
},
{
href: '/docs/generation',
title: 'Image Generation',
description: 'Full control via the generations API.',
accent: 'secondary',
},
],
}}
>
<Hero
title="Live URLs"
subtitle="Generate images directly from URL parameters. No API calls needed — just use the URL in your HTML."
/>
<section id="the-concept" className="mb-12">
<SectionHeader level={2} id="the-concept">
The Concept
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
Put your prompt in a URL. Use it directly in an <InlineCode>&lt;img src="..."&gt;</InlineCode> tag.
</p>
<p className="text-gray-300 leading-relaxed">
First request generates the image. All subsequent requests serve it from cache instantly.
</p>
</section>
<section id="url-format" className="mb-12">
<SectionHeader level={2} id="url-format">
URL Format
</SectionHeader>
<CodeBlock
code={`https://cdn.banatie.app/{org}/{project}/live/{scope}?prompt=...&aspectRatio=...`}
language="text"
filename="Live URL Format"
/>
<p className="text-gray-300 leading-relaxed mt-6 mb-4">
Query parameters:
</p>
<Table
headers={['Parameter', 'Required', 'Description']}
rows={[
[
<InlineCode key="p">prompt</InlineCode>,
<span key="r" className="text-green-400">Yes</span>,
'Text description of the image to generate',
],
[
<InlineCode key="p">aspectRatio</InlineCode>,
<span key="r" className="text-gray-500">No</span>,
'Image ratio: 1:1, 16:9, 9:16, 3:2 (default: 1:1)',
],
[
<InlineCode key="p">autoEnhance</InlineCode>,
<span key="r" className="text-gray-500">No</span>,
'Enable prompt enhancement (default: false)',
],
[
<InlineCode key="p">template</InlineCode>,
<span key="r" className="text-gray-500">No</span>,
'Enhancement template to use',
],
]}
/>
</section>
<section id="try-it" className="mb-12">
<SectionHeader level={2} id="try-it">
Try It
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Open this URL in your browser:
</p>
<CodeBlock
code={`https://cdn.banatie.app/my-org/my-project/live/demo?prompt=a+friendly+robot+waving+hello&aspectRatio=16:9`}
language="text"
filename="Example Live URL"
/>
<p className="text-gray-300 leading-relaxed mt-6 mb-4">
Or use it directly in HTML:
</p>
<CodeBlock
code={`<img
src="https://cdn.banatie.app/my-org/my-project/live/hero?prompt=mountain+landscape+at+sunset&aspectRatio=16:9"
alt="Mountain landscape"
/>`}
language="html"
filename="HTML Usage"
/>
</section>
<section id="caching-behavior" className="mb-12">
<SectionHeader level={2} id="caching-behavior">
Caching Behavior
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
The response includes an <InlineCode>X-Cache-Status</InlineCode> header:
</p>
<Table
headers={['Status', 'Meaning', 'Response Time']}
rows={[
[
<InlineCode key="s" color="success">HIT</InlineCode>,
'Image served from cache',
'Instant (milliseconds)',
],
[
<InlineCode key="s">MISS</InlineCode>,
'New image generated',
'A few seconds',
],
]}
/>
<p className="text-gray-300 leading-relaxed mt-6">
Cache hits are unlimited and don't count toward rate limits. Only new generations (cache MISS) are rate limited.
</p>
</section>
<section id="scopes" className="mb-12">
<SectionHeader level={2} id="scopes">
Scopes
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Scopes organize your live generations. Each scope has its own generation limit.
</p>
<CodeBlock
code={`# Different scopes for different purposes
https://cdn.banatie.app/my-org/my-project/live/hero-section?prompt=...
https://cdn.banatie.app/my-org/my-project/live/product-gallery?prompt=...
https://cdn.banatie.app/my-org/my-project/live/blog-images?prompt=...`}
language="text"
filename="Scope Examples"
/>
<p className="text-gray-300 leading-relaxed mt-6">
Scopes are auto-created on first use. You can also pre-configure them via the API to set custom limits.
</p>
</section>
<section id="rate-limits" className="mb-12">
<SectionHeader level={2} id="rate-limits">
Rate Limits
</SectionHeader>
<Table
headers={['Limit Type', 'Value', 'Notes']}
rows={[
[
'Per IP',
<span key="v" className="text-amber-400">10 new generations/hour</span>,
'Only applies to cache MISS',
],
[
'Per Scope',
<span key="v" className="text-amber-400">30 generations</span>,
'Configurable via API',
],
[
'Cache Hits',
<span key="v" className="text-green-400">Unlimited</span>,
'No limits on cached images',
],
]}
/>
<div className="mt-6">
<TipBox variant="compact" type="info">
Rate limits protect the service from abuse. For high-volume needs, use the generations API directly.
</TipBox>
</div>
</section>
<section id="use-cases" className="mb-12">
<SectionHeader level={2} id="use-cases">
Use Cases
</SectionHeader>
<ul className="space-y-4 text-gray-300">
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<div>
<strong className="text-white">Dynamic placeholders</strong>
<p className="text-gray-400 text-sm mt-1">Generate placeholder images during development that match your design intent.</p>
</div>
</li>
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<div>
<strong className="text-white">Personalized content</strong>
<p className="text-gray-400 text-sm mt-1">Create unique images based on user data or preferences.</p>
</div>
</li>
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<div>
<strong className="text-white">Rapid prototyping</strong>
<p className="text-gray-400 text-sm mt-1">Test different visuals without writing backend code.</p>
</div>
</li>
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<div>
<strong className="text-white">HTML emails</strong>
<p className="text-gray-400 text-sm mt-1">Include dynamic images in email templates with just a URL.</p>
</div>
</li>
</ul>
</section>
</DocPage>
);
}

View File

@ -0,0 +1,195 @@
'use client';
import { TipBox } from '@/components/docs/shared/TipBox';
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
import { DocPage } from '@/components/docs/layout/DocPage';
import {
Hero,
SectionHeader,
ResponseBlock,
LinkCard,
LinkCardGrid,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'what-is-banatie', text: 'What is Banatie?', level: 2 },
{ id: 'your-first-image', text: 'Your First Image', level: 2 },
{ id: 'production-ready', text: 'Production Ready', level: 2 },
{ id: 'live-urls', text: 'Live URLs', level: 2 },
{ id: 'get-your-api-key', text: 'Get Your API Key', level: 2 },
{ id: 'next-steps', text: 'Next Steps', level: 2 },
];
export default function GettingStartedPage() {
return (
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'Getting Started' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/generation',
title: 'Image Generation',
description: 'Aspect ratios, prompt templates, using references.',
accent: 'primary',
},
{
href: '/docs/images',
title: 'Working with Images',
description: 'Upload your own, organize with aliases.',
accent: 'secondary',
},
{
href: '/docs/live-urls',
title: 'Live URLs',
description: 'Generate images directly from URL parameters.',
accent: 'primary',
},
{
href: '/docs/api',
title: 'API Reference',
description: 'Full endpoint documentation.',
accent: 'secondary',
},
],
}}
>
<Hero
title="Get Started"
subtitle="Generate your first AI image in a few simple steps."
/>
<section id="what-is-banatie" className="mb-12">
<SectionHeader level={2} id="what-is-banatie">
What is Banatie?
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
Banatie is an image generation API for developers. Send a text prompt, get a production-ready image delivered via CDN.
</p>
<p className="text-gray-300 leading-relaxed">
Simple REST API. Optimized AI models that deliver consistent results. Images ready for production use immediately.
</p>
</section>
<section id="your-first-image" className="mb-12">
<SectionHeader level={2} id="your-first-image">
Your First Image
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Once you have your API key, generate an image with a single request:
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.app/api/v1/generations \\
-H "Content-Type: application/json" \\
-H "X-API-Key: YOUR_API_KEY" \\
-d '{"prompt": "a friendly robot waving hello"}'`}
language="bash"
filename="Generate Image"
/>
<p className="text-gray-300 leading-relaxed mt-6 mb-4">
That's it. The response contains your image:
</p>
<ResponseBlock
status="success"
statusCode={200}
statusLabel="200 OK"
content={`{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "success",
"outputImage": {
"storageUrl": "https://cdn.banatie.app/my-org/my-project/img/8a3b2c1d-4e5f-6789-abcd-ef0123456789",
"width": 1792,
"height": 1008
}
}
}`}
/>
<p className="text-gray-300 leading-relaxed mt-6">
Open <code className="text-purple-400">storageUrl</code> in your browser there's your robot.
</p>
</section>
<section id="production-ready" className="mb-12">
<SectionHeader level={2} id="production-ready">
Production Ready
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
The image URL is permanent and served via global CDN. What this means for you:
</p>
<ul className="space-y-3 text-gray-300">
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<span><strong className="text-white">Fast access</strong> images load in milliseconds</span>
</li>
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<span><strong className="text-white">Edge cached</strong> served from locations closest to your users</span>
</li>
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<span><strong className="text-white">Global distribution</strong> works fast everywhere in the world</span>
</li>
</ul>
<p className="text-gray-300 leading-relaxed mt-6">
One request. Production-ready result. Drop the URL into your app and ship.
</p>
</section>
<section id="live-urls" className="mb-12">
<SectionHeader level={2} id="live-urls">
Live URLs
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Want to skip the API call entirely? Generate images directly from a URL:
</p>
<CodeBlock
code={`https://cdn.banatie.app/my-org/my-project/live/demo?prompt=a+friendly+robot+waving+hello`}
language="text"
filename="Live URL"
/>
<p className="text-gray-300 leading-relaxed mt-6 mb-6">
Put this in an <code className="text-purple-400">&lt;img src="..."&gt;</code> tag. First request generates the image, all subsequent requests serve it from cache instantly.
</p>
<TipBox variant="compact" type="info">
Perfect for placeholders, dynamic content, and rapid prototyping.
</TipBox>
<p className="text-gray-300 leading-relaxed mt-6">
<a href="/docs/live-urls" className="text-purple-400 hover:underline">Learn more about Live URLs </a>
</p>
</section>
<section id="get-your-api-key" className="mb-12">
<SectionHeader level={2} id="get-your-api-key">
Get Your API Key
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
We're currently in early access. API keys are issued personally.
</p>
<div className="space-y-3 text-gray-300 mb-6">
<p><strong className="text-white">To request access:</strong></p>
<ol className="list-decimal list-inside space-y-2 pl-4">
<li>Go to <a href="https://banatie.app" className="text-purple-400 hover:underline">banatie.app</a></li>
<li>Enter your email in the signup form</li>
<li>We'll send your API key within 24 hours</li>
</ol>
</div>
</section>
</DocPage>
);
}

View File

@ -0,0 +1,38 @@
import Image from 'next/image';
import { Footer } from '@/components/shared/Footer';
export default function AppsLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<>
{/* Scrollable Header (NOT sticky) */}
<header className="z-10 bg-slate-900/80 backdrop-blur-md border-b border-white/5">
<nav className="max-w-7xl mx-auto px-4 sm:px-6 py-2 sm:py-3 flex justify-between items-center h-12 sm:h-14 md:h-16">
<a href="/" className="h-full flex items-center">
<Image
src="/banatie-logo-horisontal.png"
alt="Banatie Logo"
width={150}
height={40}
priority
className="h-8 sm:h-10 md:h-full w-auto object-contain"
/>
</a>
<a
href="/#get-access"
className="text-xs sm:text-sm text-gray-300 hover:text-white transition-colors"
>
Get Access
</a>
</nav>
</header>
{children}
<Footer />
</>
);
}

View File

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View File

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 103 KiB

View File

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 172 KiB

View File

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

View File

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View File

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

View File

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 126 KiB

View File

Before

Width:  |  Height:  |  Size: 169 KiB

After

Width:  |  Height:  |  Size: 169 KiB

View File

Before

Width:  |  Height:  |  Size: 195 KiB

After

Width:  |  Height:  |  Size: 195 KiB

View File

Before

Width:  |  Height:  |  Size: 377 KiB

After

Width:  |  Height:  |  Size: 377 KiB

View File

@ -0,0 +1,38 @@
import Image from 'next/image';
import { Footer } from '@/components/shared/Footer';
export default function LandingsLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<>
{/* Sticky Header */}
<header className="sticky top-0 z-10 bg-slate-900/80 backdrop-blur-md border-b border-white/5">
<nav className="max-w-7xl mx-auto px-4 sm:px-6 py-2 sm:py-3 flex justify-between items-center h-12 sm:h-14 md:h-16">
<a href="/" className="h-full flex items-center">
<Image
src="/banatie-logo-horisontal.png"
alt="Banatie Logo"
width={150}
height={40}
priority
className="h-8 sm:h-10 md:h-full w-auto object-contain"
/>
</a>
<a
href="#get-access"
className="text-xs sm:text-sm text-gray-300 hover:text-white transition-colors"
>
Get Access
</a>
</nav>
</header>
{children}
<Footer />
</>
);
}

View File

@ -1,226 +0,0 @@
'use client';
/**
* API Reference: Text to Image
*
* Refactored to use DocPage component for consistent layout
* Layout handles SubsectionNav and Left Sidebar
* DocPage handles Breadcrumb, Article structure, Next Steps, and TOC
* This page provides only the content (Hero + 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 { InteractiveAPIWidget } from '@/components/docs/blocks/InteractiveAPIWidget';
import {
Hero,
SectionHeader,
InlineCode,
EndpointCard,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'overview', text: 'Overview', level: 2 },
{ id: 'endpoint', text: 'Endpoint', level: 2 },
{ id: 'parameters', text: 'Parameters', level: 2 },
{ id: 'response', text: 'Response', level: 2 },
{ id: 'error-codes', text: 'Error Codes', level: 2 },
{ id: 'interactive', text: 'Try It Live', level: 2 },
{ id: 'next-steps', text: 'Next Steps', level: 2 },
];
const parameters = [
{ name: 'prompt', type: 'string', required: true, description: 'Text description of the image to generate' },
{ name: 'filename', type: 'string', required: false, description: 'Output filename (without extension)' },
{ name: 'aspectRatio', type: 'string', required: false, description: 'Image aspect ratio: "1:1", "16:9", "9:16", "4:3"' },
{ name: 'autoEnhance', type: 'boolean', required: false, description: 'Enable AI prompt enhancement for better results' },
];
export default function TextToImageAPIPage() {
return (
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'API Reference', href: '/docs/api' },
{ label: 'Text to Image' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/api/upload',
title: 'Upload API',
description: 'Learn how to upload reference images for image-to-image generation.',
accent: 'primary',
},
{
href: '/docs/guides/error-handling',
title: 'Error Handling',
description: 'Best practices for handling errors and retries in production.',
accent: 'secondary',
},
],
}}
>
{/* Hero Section */}
<Hero
title="Text to Image"
subtitle="Generate high-quality images from text prompts using AI-powered models."
/>
{/* Overview */}
<section id="overview" className="mb-12">
<SectionHeader level={2} id="overview">
Overview
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
The Text to Image endpoint allows you to generate images from natural language descriptions.
Powered by Google Gemini 2.5 Flash and Imagen 4.0, it produces photorealistic images
optimized for your specified requirements.
</p>
<TipBox variant="compact" type="info">
<strong>Tip:</strong> Enable <InlineCode>autoEnhance</InlineCode>
to let AI improve your prompts for better image quality.
</TipBox>
</section>
{/* Endpoint */}
<section id="endpoint" className="mb-12">
<SectionHeader level={2} id="endpoint">
Endpoint
</SectionHeader>
<EndpointCard
method="POST"
endpoint="/api/text-to-image"
baseUrl="https://api.banatie.com"
/>
</section>
{/* Parameters */}
<section id="parameters" className="mb-12">
<SectionHeader level={2} id="parameters" className="mb-6">
Parameters
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
All parameters should be sent in the request body as JSON.
</p>
<Table
headers={['Parameter', 'Type', 'Required', 'Description']}
rows={parameters.map((param) => [
<InlineCode key="name">{param.name}</InlineCode>,
<span key="type" className="text-cyan-400">{param.type}</span>,
<span key="required" className={param.required ? 'text-green-400' : 'text-gray-500'}>
{param.required ? 'Yes' : 'No'}
</span>,
param.description,
])}
/>
<div className="mt-6">
<TipBox variant="compact" type="info">
<strong>Default Values:</strong> If not specified, <InlineCode>filename</InlineCode> is
auto-generated, <InlineCode>aspectRatio</InlineCode> defaults
to "1:1", and <InlineCode>autoEnhance</InlineCode> is false.
</TipBox>
</div>
</section>
{/* Response */}
<section id="response" className="mb-12">
<SectionHeader level={2} id="response" className="mb-4">
Response
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
On success, the API returns a JSON object containing the generated image URL and metadata.
</p>
<CodeBlock
code={`{
"success": true,
"data": {
"url": "https://cdn.banatie.com/org/project/generated/2025-01/image.png",
"filepath": "org/project/generated/2025-01/image.png",
"width": 1024,
"height": 1024,
"promptEnhancement": {
"enhancedPrompt": "A highly detailed, photorealistic...",
"wasEnhanced": true
}
},
"metadata": {
"generationTime": 3.42,
"model": "imagen-4.0"
}
}`}
language="json"
filename="Success Response"
/>
</section>
{/* Error Codes */}
<section id="error-codes" className="mb-12">
<SectionHeader level={2} id="error-codes" className="mb-6">
Error Codes
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
The API uses standard HTTP status codes and returns descriptive error messages.
</p>
<Table
headers={['Status Code', 'Error Type', 'Description']}
rows={[
[
<InlineCode key="code" color="error">400</InlineCode>,
'Bad Request',
'Missing or invalid parameters in the request body',
],
[
<InlineCode key="code" color="error">401</InlineCode>,
'Unauthorized',
'Missing or invalid API key in X-API-Key header',
],
[
<InlineCode key="code" color="error">429</InlineCode>,
'Rate Limit',
'Too many requests. Check rate limit headers for retry timing',
],
[
<InlineCode key="code" color="error">500</InlineCode>,
'Server Error',
'Internal server error. Contact support if persists',
],
]}
/>
<div className="mt-6">
<TipBox variant="compact" type="warning">
<strong>Rate Limits:</strong> Project API keys are limited to 100 requests per hour.
Upgrade your plan for higher limits.
</TipBox>
</div>
</section>
{/* Interactive Widget */}
<section id="interactive" className="mb-12">
<SectionHeader level={2} id="interactive" className="mb-4">
Try It Live
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Test the API directly from this page. Enter your API key and customize the parameters below.
</p>
<InteractiveAPIWidget
endpoint="/api/text-to-image"
method="POST"
description="Generate an image from a text prompt"
parameters={parameters}
/>
</section>
</DocPage>
);
}

View File

@ -1,313 +0,0 @@
'use client';
/**
* Authentication Guide
*
* Refactored to use DocPage component for consistent layout
* Layout handles SubsectionNav and Left Sidebar
* DocPage handles Breadcrumb, Article structure, Next Steps, and TOC
* This page provides only the content (Hero + 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,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'overview', text: 'Overview', level: 2 },
{ id: 'api-keys', text: 'API Keys', level: 2 },
{ id: 'key-types', text: 'Key Types', level: 3 },
{ id: 'creating-keys', text: 'Creating Keys', level: 3 },
{ id: 'using-keys', text: 'Using API Keys', level: 2 },
{ id: 'rate-limits', text: 'Rate Limits', level: 2 },
{ id: 'security', text: 'Security Best Practices', level: 2 },
{ id: 'next-steps', text: 'Next Steps', level: 2 },
];
export default function AuthenticationGuidePage() {
return (
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'Guides', href: '/docs/guides' },
{ label: 'Authentication' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/api/text-to-image',
title: 'Start Generating Images',
description: 'Explore the Text to Image API and start building your integration.',
accent: 'primary',
},
{
href: '/docs/guides/error-handling',
title: 'Error Handling Guide',
description: 'Learn how to handle authentication errors and implement retry logic.',
accent: 'secondary',
},
],
}}
>
{/* Hero Section */}
<Hero
title="Authentication"
subtitle="Learn how to authenticate with the Banatie API using API keys, manage rate limits, and implement security best practices."
/>
{/* Overview */}
<section id="overview" className="mb-12">
<SectionHeader level={2} id="overview" className="mb-4">
Overview
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Banatie uses API keys to authenticate requests. All API endpoints require authentication
via the <InlineCode>X-API-Key</InlineCode> header.
API keys are tied to organizations and projects, providing fine-grained access control.
</p>
<TipBox variant="compact" type="info">
<strong>Quick Start:</strong> New to API authentication? Check out our{' '}
<a href="/docs" className="text-purple-400 hover:underline">
Getting Started guide
</a>{' '}
for a step-by-step walkthrough.
</TipBox>
</section>
{/* API Keys */}
<section id="api-keys" className="mb-12">
<SectionHeader level={2} id="api-keys" className="mb-6">
API Keys
</SectionHeader>
<div id="key-types" className="mb-8">
<SectionHeader level={3} id="key-types" className="mb-4">
Key Types
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Banatie supports two types of API keys, each with different permissions and use cases:
</p>
<Table
headers={['Key Type', 'Permissions', 'Expiration', 'Use Case']}
rows={[
[
<InlineCode key="type">Master Key</InlineCode>,
'Full admin access, can create/revoke keys',
<span key="exp" className="text-green-400">Never expires</span>,
'Server-side admin operations, key management',
],
[
<InlineCode key="type" color="success">Project Key</InlineCode>,
'Image generation only',
<span key="exp" className="text-amber-400">90 days</span>,
'Application integration, API requests',
],
]}
/>
<div className="mt-6">
<TipBox variant="prominent" type="warning">
<strong className="text-amber-300">Master Key Security:</strong> Master keys have full
administrative access and never expire. Store them securely in encrypted vaults or
secret managers. Never expose master keys in client-side code, logs, or version control.
Use project keys for application integration whenever possible.
</TipBox>
</div>
</div>
<div id="creating-keys" className="mb-8">
<SectionHeader level={3} id="creating-keys" className="mb-4">
Creating Keys
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
For first-time setup, use the bootstrap endpoint to create your initial master key:
</p>
<CodeBlock
code={`# Bootstrap your first master key (one-time only)
curl -X POST https://api.banatie.com/api/bootstrap/initial-key
# Response
{
"success": true,
"data": {
"key": "bnt_master_abc123...",
"type": "master"
}
}`}
language="bash"
filename="Bootstrap Master Key"
/>
<div className="mt-6">
<p className="text-gray-300 leading-relaxed mb-4">
Once you have a master key, you can create project keys for your applications:
</p>
<CodeBlock
code={`# Create a project key with master key authentication
curl -X POST https://api.banatie.com/api/admin/keys \\
-H "X-API-Key: YOUR_MASTER_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"type": "project",
"projectId": "my-app",
"name": "Production API Key"
}'
# Response
{
"success": true,
"data": {
"key": "bnt_project_xyz789...",
"type": "project",
"expiresAt": "2025-04-14T00:00:00Z"
}
}`}
language="bash"
filename="Create Project Key"
/>
</div>
</div>
</section>
{/* Using API Keys */}
<section id="using-keys" className="mb-12">
<SectionHeader level={2} id="using-keys" className="mb-4">
Using API Keys
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
Include your API key in the <InlineCode>X-API-Key</InlineCode> header
with every request:
</p>
<CodeBlock
code={`# Example: Generate an image with project key
curl -X POST https://api.banatie.com/api/text-to-image \\
-H "X-API-Key: bnt_project_xyz789..." \\
-H "Content-Type: application/json" \\
-d '{
"prompt": "a sunset over the ocean",
"aspectRatio": "16:9"
}'`}
language="bash"
filename="Authenticated Request"
/>
<div className="mt-6">
<TipBox variant="compact" type="info">
<strong>Environment Variables:</strong> Store API keys in environment variables, not
hardcoded in your application. Example:{' '}
<InlineCode>BANATIE_API_KEY</InlineCode>
</TipBox>
</div>
</section>
{/* Rate Limits */}
<section id="rate-limits" className="mb-12">
<SectionHeader level={2} id="rate-limits" className="mb-6">
Rate Limits
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
API keys are subject to rate limits to ensure fair usage and system stability. Limits
vary by key type and plan tier:
</p>
<Table
headers={['Key Type', 'Rate Limit', 'Reset Window', 'Upgrade Available']}
rows={[
[
<InlineCode key="type">Master Key</InlineCode>,
<span key="limit" className="text-green-400">Unlimited</span>,
'N/A',
'N/A',
],
[
<InlineCode key="type" color="success">Project Key (Free)</InlineCode>,
<span key="limit" className="text-amber-400">100 requests/hour</span>,
'1 hour rolling',
<a key="upgrade" href="/pricing" className="text-purple-400 hover:underline">Yes</a>,
],
[
<InlineCode key="type" color="success">Project Key (Pro)</InlineCode>,
<span key="limit" className="text-green-400">1,000 requests/hour</span>,
'1 hour rolling',
<a key="upgrade" href="/pricing" className="text-purple-400 hover:underline">Yes</a>,
],
]}
/>
<div className="mt-6">
<p className="text-gray-300 leading-relaxed mb-4">
When you exceed rate limits, the API returns a <InlineCode color="error">429 Too Many Requests</InlineCode> status.
Check the response headers for retry timing:
</p>
<CodeBlock
code={`# Rate limit response headers
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1704153600
# Error response body
{
"error": "Rate limit exceeded",
"retryAfter": 3600
}`}
language="bash"
filename="Rate Limit Response"
/>
</div>
</section>
{/* Security Best Practices */}
<section id="security" className="mb-12">
<SectionHeader level={2} id="security" className="mb-6">
Security Best Practices
</SectionHeader>
<TipBox variant="prominent" type="warning">
<strong className="text-amber-300">Critical Security Guidelines:</strong>
<ul className="mt-3 space-y-2 list-disc list-inside">
<li>Never commit API keys to version control systems (Git, SVN, etc.)</li>
<li>Store keys in environment variables or secret management services</li>
<li>Use project keys in applications, reserve master keys for admin operations</li>
<li>Rotate keys regularly, especially after team member changes</li>
<li>Implement server-side API calls for production applications</li>
<li>Monitor API key usage in your dashboard for suspicious activity</li>
</ul>
</TipBox>
<div className="mt-6">
<h3 className="text-lg font-semibold text-white mb-3">Key Rotation Example</h3>
<CodeBlock
code={`# 1. Create new project key
curl -X POST https://api.banatie.com/api/admin/keys \\
-H "X-API-Key: YOUR_MASTER_KEY" \\
-d '{"type": "project", "projectId": "my-app", "name": "New Key"}'
# 2. Update your application to use new key
export BANATIE_API_KEY="bnt_project_new..."
# 3. Revoke old key
curl -X DELETE https://api.banatie.com/api/admin/keys/OLD_KEY_ID \\
-H "X-API-Key: YOUR_MASTER_KEY"`}
language="bash"
filename="Key Rotation Process"
/>
</div>
</section>
</DocPage>
);
}

View File

@ -1,196 +0,0 @@
'use client';
/**
* Getting Started Page - Production Documentation
*
* Refactored to use DocPage component for consistent layout
* Layout handles SubsectionNav and Left Sidebar
* DocPage handles Breadcrumb, Article structure, Next Steps, and TOC
* This page provides only the content (Hero + sections)
*/
import { TipBox } from '@/components/docs/shared/TipBox';
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
import { DocPage } from '@/components/docs/layout/DocPage';
import {
Hero,
SectionHeader,
ResponseBlock,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'introduction', text: 'Introduction', level: 2 },
{ id: 'quick-start', text: 'Quick Start', level: 2 },
{ id: 'installation', text: 'Installation', level: 3 },
{ id: 'authentication', text: 'Authentication', level: 3 },
{ id: 'first-request', text: 'Your First Request', level: 2 },
{ id: 'next-steps', text: 'Next Steps', level: 2 },
];
export default function GettingStartedPage() {
return (
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'Getting Started' },
]}
tocItems={tocItems}
nextSteps={{
description:
'Now that you have generated your first image, explore these resources to build more advanced integrations:',
links: [
{
href: '/docs/api/text-to-image',
title: 'API Reference',
description: 'Explore all available endpoints, parameters, and response formats.',
accent: 'primary',
},
{
href: '/docs/guides/authentication',
title: 'Authentication Guide',
description: 'Learn about API keys, rate limits, and security best practices.',
accent: 'secondary',
},
],
}}
>
{/* Hero Section */}
<Hero
title="Getting Started"
subtitle="Welcome to the Banatie API documentation. Learn how to integrate AI-powered image generation into your applications in minutes."
/>
{/* Introduction */}
<section id="introduction" className="mb-12">
<SectionHeader level={2} id="introduction">
Introduction
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini
2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into
production-ready visuals.
</p>
<p className="text-gray-300 leading-relaxed mb-6">
Whether you are building a content creation platform, e-commerce site, or creative tool,
Banatie provides the infrastructure you need to generate high-quality images at scale.
</p>
{/* Compact Tip Box */}
<TipBox variant="compact" type="info">
<strong>New to API integration?</strong> Start with our{' '}
<a href="/docs/examples" className="text-purple-400 hover:underline">
code examples
</a>{' '}
to see common use cases in action.
</TipBox>
</section>
{/* Quick Start */}
<section id="quick-start" className="mb-12">
<SectionHeader level={2} id="quick-start" className="mb-6">
Quick Start
</SectionHeader>
<div id="installation" className="mb-8">
<SectionHeader level={3} id="installation">
Installation
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
Banatie is a REST API, so you do not need to install any libraries. However, we provide
SDKs for popular languages to make integration easier.
</p>
<CodeBlock
code={`# Using npm (JavaScript/TypeScript)
npm install @banatie/sdk
# Using pip (Python)
pip install banatie
# Using Go
go get github.com/banatie/sdk-go`}
language="bash"
filename="Installation"
/>
</div>
<div id="authentication" className="mb-8">
<SectionHeader level={3} id="authentication">
Authentication
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
All API requests require an API key. You can create an API key from your dashboard or
using the bootstrap endpoint for initial setup.
</p>
{/* Prominent Tip Box for Security Warning */}
<div className="mb-6">
<TipBox variant="prominent" type="warning">
<strong className="text-amber-300">Security Best Practice:</strong> Keep your API keys secure.
Never commit them to public repositories or expose them in client-side code. Use environment
variables and server-side implementations for production applications.
</TipBox>
</div>
<CodeBlock
code={`# Create your first API key (one-time bootstrap)
curl -X POST https://api.banatie.com/api/bootstrap/initial-key
# Save the returned key securely
export BANATIE_API_KEY="bnt_your_key_here"`}
language="bash"
filename="Get API Key"
/>
</div>
</section>
{/* First Request */}
<section id="first-request" className="mb-12">
<SectionHeader level={2} id="first-request">
Your First Request
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Let's generate your first image! This example uses curl, but you can use any HTTP client
or our SDKs.
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.com/api/text-to-image \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"prompt": "a serene mountain landscape at sunset",
"filename": "mountain_sunset",
"aspectRatio": "16:9",
"autoEnhance": true
}'`}
language="bash"
filename="Generate Image"
/>
<div className="mt-6">
<p className="text-sm font-semibold text-gray-300 mb-3">Expected Response:</p>
<ResponseBlock
status="success"
statusCode={200}
statusLabel="✓ 200 Success"
content={`{
"success": true,
"data": {
"url": "https://cdn.banatie.com/org/project/generated/2025-01/mountain_sunset.png",
"filepath": "org/project/generated/2025-01/mountain_sunset.png",
"width": 1920,
"height": 1080,
"promptEnhancement": {
"enhancedPrompt": "A breathtaking mountain landscape..."
}
}
}`}
/>
</div>
</section>
</DocPage>
);
}

View File

@ -1,9 +1,6 @@
import type { Metadata } from 'next';
import { Inter, Caveat } from 'next/font/google';
import Image from 'next/image';
import Script from 'next/script';
import { Footer } from '@/components/shared/Footer';
import banatieLogo from './_assets/banatie-logo-horisontal.png';
import './globals.css';
const inter = Inter({
@ -47,32 +44,7 @@ export default function RootLayout({
<div className="absolute bottom-1/4 -right-1/4 w-96 h-96 bg-cyan-600/10 rounded-full blur-3xl animate-pulse delay-700"></div>
</div>
{/* Header */}
<header className="sticky top-0 z-10 bg-slate-900/80 backdrop-blur-md border-b border-white/5">
<nav className="max-w-7xl mx-auto px-4 sm:px-6 py-2 sm:py-3 flex justify-between items-center h-12 sm:h-14 md:h-16">
<div className="h-full flex items-center">
<Image
src={banatieLogo}
alt="Banatie Logo"
width={150}
height={40}
priority
className="h-8 sm:h-10 md:h-full w-auto object-contain"
/>
</div>
<a
href="#get-access"
className="text-xs sm:text-sm text-gray-300 hover:text-white transition-colors"
>
Get Access
</a>
</nav>
</header>
{/* Page content */}
{children}
<Footer />
</div>
</body>
</html>

View File

@ -1,12 +1,76 @@
import { MetadataRoute } from 'next';
export default function sitemap(): MetadataRoute.Sitemap {
const baseUrl = 'https://banatie.app';
return [
{
url: 'https://banatie.app/',
url: `${baseUrl}/`,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 1,
},
// Documentation - Guides
{
url: `${baseUrl}/docs`,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.9,
},
{
url: `${baseUrl}/docs/generation`,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.8,
},
{
url: `${baseUrl}/docs/images`,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.8,
},
{
url: `${baseUrl}/docs/live-urls`,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.8,
},
{
url: `${baseUrl}/docs/authentication`,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.8,
},
// Documentation - API Reference
{
url: `${baseUrl}/docs/api`,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.8,
},
{
url: `${baseUrl}/docs/api/generations`,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.7,
},
{
url: `${baseUrl}/docs/api/images`,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.7,
},
{
url: `${baseUrl}/docs/api/flows`,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.7,
},
{
url: `${baseUrl}/docs/api/live-scopes`,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.7,
},
];
}

View File

@ -41,37 +41,38 @@ const navigationItems: NavItem[] = [
{
label: 'Getting Started',
href: '/docs',
icon: '🚀',
},
{
label: 'Image Generation',
href: '/docs/generation',
},
{
label: 'Working with Images',
href: '/docs/images',
},
{
label: 'Live URLs',
href: '/docs/live-urls',
},
{
label: 'Authentication',
href: '/docs/authentication',
},
{
label: 'API Reference',
href: '/docs/api',
icon: '📚',
children: [
{ label: 'Text to Image', href: '/docs/api/text-to-image' },
{ label: 'Upload', href: '/docs/api/upload' },
{ label: 'Overview', href: '/docs/api' },
{ label: 'Generations', href: '/docs/api/generations' },
{ label: 'Images', href: '/docs/api/images' },
{ label: 'Flows', href: '/docs/api/flows' },
{ label: 'Live Scopes', href: '/docs/api/live-scopes' },
],
},
{
label: 'Guides',
href: '/docs/guides',
icon: '📖',
children: [
{ label: 'Authentication', href: '/docs/guides/authentication' },
{ label: 'Error Handling', href: '/docs/guides/error-handling' },
{ label: 'Rate Limits', href: '/docs/guides/rate-limits' },
],
},
{
label: 'Examples',
href: '/docs/examples',
icon: '💡',
},
];
export const DocsSidebar = ({ currentPath }: DocsSidebarProps) => {
const [expandedSections, setExpandedSections] = useState<string[]>(['API Reference', 'Guides']);
const [expandedSections, setExpandedSections] = useState<string[]>(['API Reference']);
const toggleSection = (label: string) => {
setExpandedSections((prev) =>
@ -79,7 +80,11 @@ export const DocsSidebar = ({ currentPath }: DocsSidebarProps) => {
);
};
const isActive = (href: string) => currentPath === href;
// Normalize path by removing trailing slash (except for root)
const normalizePath = (path: string) => (path.length > 1 && path.endsWith('/') ? path.slice(0, -1) : path);
const normalizedCurrentPath = normalizePath(currentPath);
const isActive = (href: string) => normalizedCurrentPath === href;
const isExpanded = (label: string) => expandedSections.includes(label);
return (
@ -119,10 +124,7 @@ export const DocsSidebar = ({ currentPath }: DocsSidebarProps) => {
${active ? 'bg-purple-500/10 text-white font-medium' : 'text-gray-400 hover:text-white hover:bg-white/5'}
`}
>
<span className="flex items-center gap-2">
{item.icon && <span className="text-base">{item.icon}</span>}
<span>{item.label}</span>
</span>
<span>{item.label}</span>
{hasChildren && (
<svg
className={`w-4 h-4 transition-transform ${expanded ? 'rotate-90' : ''}`}

View File

@ -2,7 +2,6 @@
import Image from 'next/image';
import { /* footerLinks, */ footerCopyright } from '@/config/footer';
import banatieLogo from '@/app/_assets/banatie-logo-horisontal.png';
export const Footer = () => {
return (
@ -12,7 +11,7 @@ export const Footer = () => {
{/* Logo - responsive sizing */}
<div className="h-10 sm:h-12 md:h-14 lg:h-16 flex items-center">
<Image
src={banatieLogo}
src="/banatie-logo-horisontal.png"
alt="Banatie Logo"
width={200}
height={60}

View File

@ -29,6 +29,7 @@ import { ThreeColumnLayout } from '@/components/layout/ThreeColumnLayout';
interface NavItem {
label: string;
href: string;
disabled?: boolean;
}
interface SubsectionNavProps {
@ -61,16 +62,29 @@ export const SubsectionNav = ({ items, currentPath, leftSlot, rightSlot }: Subse
{items.map((item) => {
const active = isActive(item.href);
return (
<a
key={item.href}
href={item.href}
className={`
py-3 text-sm font-medium transition-colors
${active ? 'text-purple-400' : 'text-gray-400 hover:text-white'}
`}
>
{item.label}
</a>
<div key={item.label} className="relative group">
<a
href={item.disabled ? undefined : item.href}
aria-disabled={item.disabled}
className={`
py-3 text-sm font-medium transition-colors
${
item.disabled
? 'text-gray-600 cursor-not-allowed'
: active
? 'text-purple-400'
: 'text-gray-400 hover:text-white'
}
`}
>
{item.label}
</a>
{item.disabled && (
<div className="absolute left-1/2 -translate-x-1/2 top-full mt-1 opacity-0 group-hover:opacity-100 transition-opacity px-2 py-1 bg-slate-800 text-gray-300 text-xs rounded whitespace-nowrap pointer-events-none z-50">
Coming soon
</div>
)}
</div>
);
})}
</div>
@ -159,15 +173,25 @@ export const SubsectionNav = ({ items, currentPath, leftSlot, rightSlot }: Subse
const active = isActive(item.href);
return (
<a
key={item.href}
href={item.href}
onClick={() => setMobileMenuOpen(false)}
key={item.label}
href={item.disabled ? undefined : item.href}
aria-disabled={item.disabled}
onClick={item.disabled ? undefined : () => setMobileMenuOpen(false)}
className={`
block px-4 py-3 rounded-lg text-sm font-medium transition-colors
${active ? 'bg-purple-500/10 text-purple-400' : 'text-gray-400 hover:text-white hover:bg-white/5'}
${
item.disabled
? 'text-gray-600 cursor-not-allowed'
: active
? 'bg-purple-500/10 text-purple-400'
: 'text-gray-400 hover:text-white hover:bg-white/5'
}
`}
>
{item.label}
{item.disabled && (
<span className="ml-2 text-xs text-gray-500">(Coming soon)</span>
)}
</a>
);
})}

View File

@ -0,0 +1,606 @@
# Banatie Documentation — Full Specification for Claude Code
**Date:** December 30, 2025
**Purpose:** Complete specification for generating documentation pages
**Source of Truth:** `/docs/api/*.md` in banatie-service repository
**Target:** `/apps/landing/src/app/docs/`
---
## Documentation Spirit & Voice
**This is critical. Every page must follow this approach:**
### Tone
- **Technical but approachable** — developers respect precision, but don't want to read a manual
- **Confident, not arrogant** — we know our product works, no need to oversell
- **Direct** — say what you mean, no fluff, no filler phrases
- **Second person** — "you", "your", not "the user" or "one"
### Content Philosophy
- **"Easy and simple" is the vibe** — everything should feel lightweight
- **Positive statements over negatives** — say what we DO, not what we don't
- **Show, don't tell** — code examples over explanations
- **One request, one result** — emphasize simplicity of the flow
- **Production-ready** — everything we deliver is ready to ship, not a prototype
### What to Avoid
- Filler phrases ("In this section we will discuss...")
- Marketing speak ("revolutionary", "game-changing", "cutting-edge")
- Unnecessary warnings and caveats
- Over-explaining simple concepts
- Walls of text without visual breaks
### Visual Variety
Use callouts, tables, code blocks liberally. Break up text. Make pages scannable.
---
## URL Structure (Final, SEO-Critical)
```
/docs # Getting Started
/docs/generation # Image Generation (main guide)
/docs/images # Working with Images
/docs/live-urls # Live URL Generation
/docs/authentication # API Keys & Auth (after live-urls)
/docs/api # API Reference Overview
/docs/api/generations # Generations endpoints
/docs/api/images # Images endpoints
/docs/api/flows # Flows endpoints
/docs/api/live-scopes # Live Scopes endpoints
```
**10 pages total.** URLs are permanent — do not change after deployment.
---
## Sidebar Navigation
Two-level navigation:
```
Getting Started → /docs
Image Generation → /docs/generation
Working with Images → /docs/images
Live URLs → /docs/live-urls
Authentication → /docs/authentication
API Reference → /docs/api (expandable group)
├─ Overview → /docs/api
├─ Generations → /docs/api/generations
├─ Images → /docs/api/images
├─ Flows → /docs/api/flows
└─ Live Scopes → /docs/api/live-scopes
```
"API Reference" section is collapsible/expandable in sidebar.
---
## Design System
Use existing components from the landing app. Key elements:
- **Code blocks** with syntax highlighting and copy button
- **Tables** for parameters, status codes, response fields
- **Callout blocks:**
- 💡 **Tip** — helpful hints, pro tips
- ⚠️ **Warning** — important cautions
- 📝 **Note** — additional context
- 🔒 **Security** — auth/security related
- **Response blocks** with status badges
- **Card links** for navigation to related pages
- **Breadcrumbs** for orientation
**Visual variety is important** — break up walls of text with callouts, tables, code examples.
---
## Cross-Linking Strategy
Every guide page should link to corresponding API Reference section.
Every API Reference page should link back to the guide for context.
Examples:
- `/docs/generation` → "See full endpoint details in [API Reference: Generations](/docs/api/generations)"
- `/docs/api/generations` → "For concepts and examples, see [Image Generation guide](/docs/generation)"
---
## Page Specifications
---
### Page 1: `/docs` — Getting Started
**SEO Title:** "Getting Started with Banatie API | AI Image Generation"
**Meta Description:** "Generate your first AI image in a few simple steps. REST API for production-ready image assets via CDN."
**Purpose:** First-time visitor lands here. Show them the value immediately.
**CONTENT — USE EXACTLY AS WRITTEN:**
```markdown
# Get Started
Generate your first AI image in a few simple steps.
## What is Banatie?
Banatie is an image generation API for developers. Send a text prompt, get a production-ready image delivered via CDN.
Simple REST API. Optimized AI models that deliver consistent results. Images ready for production use immediately.
## Your First Image
Once you have your API key, generate an image with a single request:
```bash
curl -X POST https://api.banatie.app/api/v1/generations \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"prompt": "a friendly robot waving hello"}'
```
That's it. The response contains your image:
```json
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "success",
"outputImage": {
"storageUrl": "https://cdn.banatie.app/my-org/my-project/img/8a3b2c1d-4e5f-6789-abcd-ef0123456789",
"width": 1792,
"height": 1008
}
}
}
```
Open `storageUrl` in your browser — there's your robot.
## Production Ready
The image URL is permanent and served via global CDN. What this means for you:
- **Fast access** — images load in milliseconds
- **Edge cached** — served from locations closest to your users
- **Global distribution** — works fast everywhere in the world
One request. Production-ready result. Drop the URL into your app and ship.
## Live URLs
Want to skip the API call entirely?
Generate images directly from a URL:
```
https://cdn.banatie.app/my-org/my-project/live/demo?prompt=a+friendly+robot+waving+hello
```
Put this in an `<img src="...">` tag. First request generates the image, all subsequent requests serve it from cache instantly.
Perfect for placeholders, dynamic content, and rapid prototyping.
**[Learn more about Live URLs](/docs/live-urls)**
## Get Your API Key
We're currently in early access. API keys are issued personally.
**To request access:**
1. Go to [banatie.app](https://banatie.app)
2. Enter your email in the signup form
3. We'll send your API key within 24 hours
## Next Steps
- **[Image Generation](/docs/generation)** — Aspect ratios, prompt templates, using references
- **[Working with Images](/docs/images)** — Upload your own, organize with aliases
- **[Live URLs](/docs/live-urls)** — Generate images directly from URL parameters
- **[API Reference](/docs/api)** — Full endpoint documentation
```
---
### Page 2: `/docs/generation` — Image Generation
**SEO Title:** "Image Generation | Banatie API Docs"
**Meta Description:** "Generate AI images from text prompts. Supports references, prompt templates, and chaining."
**Sections:**
1. **Basic Generation**
- POST /api/v1/generations
- Simple example: just prompt
- Response with status, outputImage, storageUrl
- Emphasize: one request → image ready
2. **Aspect Ratios**
- Table of supported ratios with use cases
- 1:1, 16:9, 9:16, 3:2, 21:9
3. **Prompt Templates**
- Templates improve your prompt for specific styles
- Available templates: general, photorealistic, illustration, minimalist, sticker, product, comic
- Example showing how template affects the result
- **Note callout:** Template selection coming soon. Currently uses general style.
4. **Using Reference Images**
- Add referenceImages array with image IDs
- Example with UUID reference
- **Pro Tip callout:** You can also use aliases like `@logo` instead of UUIDs. See [Working with Images](/docs/images) to learn about aliases.
- Auto-detection from prompt text (if you mention @alias in prompt)
5. **Continuing Generation**
- Pass the same flowId to chain generations
- Each response includes flowId for continuation
- Keep it brief, not a major feature highlight
6. **Regeneration**
- POST /api/v1/generations/:id/regenerate
- Same params, new image, same URL
**Link to:** `/docs/api/generations` for full endpoint reference
---
### Page 3: `/docs/images` — Working with Images
**SEO Title:** "Working with Images | Banatie API Docs"
**Meta Description:** "Upload, manage, and organize your images. CDN delivery, aliases, and image management."
**Sections:**
1. **Image URLs**
- All images served via CDN: `https://cdn.banatie.app/...`
- Format: `/{org}/{project}/img/{imageId}`
- Fast, cached, globally distributed
2. **Uploading Images**
- POST /api/v1/images/upload
- Multipart form data
- Use cases: brand assets, reference images, logos
3. **Listing & Getting Images**
- GET /api/v1/images
- GET /api/v1/images/:id
4. **Aliases**
- Assign memorable names to images
- Format: @alias-name (e.g., @logo, @hero-bg)
- PUT /api/v1/images/:id with alias field
- Access via CDN: `/{org}/{project}/img/@hero`
**Pro Tip callout:** Use aliases for brand assets like `@logo`, `@brand-colors`. Reference them in generations without remembering UUIDs.
5. **Deleting Images**
- DELETE /api/v1/images/:id
**Link to:** `/docs/api/images` for full endpoint reference
---
### Page 4: `/docs/live-urls` — Live URL Generation
**SEO Title:** "Live URLs | Banatie API Docs"
**Meta Description:** "Generate images directly from URL parameters. No API calls needed — just use the URL in your HTML."
**This is a highlight feature page — make it compelling but not salesy.**
**Sections:**
1. **The Concept**
- Generate images by putting prompt in URL
- Use directly in `<img src="...">`
- First request generates, subsequent requests serve from cache
2. **URL Format**
```
https://cdn.banatie.app/{org}/{project}/live/{scope}?prompt=...&aspectRatio=...
```
3. **Try It**
- Show a complete URL example they can open in browser
4. **Caching Behavior**
- Cache HIT: instant, from CDN edge
- Cache MISS: generates new image (few seconds)
- X-Cache-Status header tells you which
5. **Scopes**
- Organize live generations by scope
- Set limits per scope
- Auto-created on first use (if enabled)
6. **Rate Limits**
- 10 new generations per hour per IP
- Cache hits are unlimited
7. **Use Cases**
- Dynamic placeholders during development
- Personalized content
- Rapid prototyping
- HTML emails with dynamic images
**Link to:** `/docs/api/live-scopes` for scope management endpoints
---
### Page 5: `/docs/authentication` — Authentication
**SEO Title:** "Authentication | Banatie API Docs"
**Meta Description:** "How to authenticate with Banatie API using API keys."
**Sections:**
1. **Early Access**
- Currently in early access phase
- API keys are issued personally via email
- To request access: sign up on [banatie.app](https://banatie.app)
2. **Using Your API Key**
- All API requests require `X-API-Key` header
- Example: `curl -H "X-API-Key: your_key_here" ...`
- Keep your key secret, don't commit to git
3. **Key Types** (brief)
- Project Key: for your application
- Master Key: for admin operations (you probably don't need this)
**Note callout:** API key management dashboard coming soon. For now, contact us if you need to rotate your key.
**Link to:** `/docs/generation` as next step
---
### Page 6: `/docs/api` — API Reference Overview
**SEO Title:** "API Reference | Banatie API Docs"
**Meta Description:** "Complete REST API reference for Banatie. All endpoints, parameters, and response formats."
**This is a hub page — brief intro then links to subsections.**
**Sections:**
1. **Base URL**
```
https://api.banatie.app
```
2. **Authentication**
- All endpoints require `X-API-Key` header
- Link to `/docs/authentication`
3. **Response Format**
- Success: `{ "success": true, "data": {...} }`
- Error: `{ "success": false, "error": {...} }`
- Pagination pattern
4. **Common Error Codes**
- Table of HTTP status codes and meanings
5. **Rate Limits**
- 100 requests per hour
- Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
6. **Endpoints**
- Card links to each subsection:
- Generations — create and manage image generations
- Images — upload and organize images
- Flows — manage generation chains
- Live Scopes — control live URL generation
---
### Page 7: `/docs/api/generations` — Generations Endpoints
**SEO Title:** "Generations API | Banatie API Reference"
**Style:** Dry, complete, scannable. This is reference material.
**Endpoints to document:**
```
POST /api/v1/generations Create generation
GET /api/v1/generations List generations
GET /api/v1/generations/:id Get generation
DELETE /api/v1/generations/:id Delete generation
POST /api/v1/generations/:id/regenerate Regenerate
PUT /api/v1/generations/:id Update generation
```
**For each endpoint:**
- Method + Path
- Description (1 line)
- Request parameters (table)
- Request body example (where applicable)
- Response example
- Notes if applicable
**Source:** Use `/docs/api/image-generation.md` and `/docs/api/image-generation-advanced.md`
**Important:** The API is synchronous. POST returns completed generation with outputImage immediately. Do NOT show polling flow.
**Link to:** `/docs/generation` for guide/context
---
### Page 8: `/docs/api/images` — Images Endpoints
**SEO Title:** "Images API | Banatie API Reference"
**Endpoints:**
```
POST /api/v1/images/upload Upload image
GET /api/v1/images List images
GET /api/v1/images/:id Get image (supports @alias)
PUT /api/v1/images/:id Update image (set alias, metadata)
DELETE /api/v1/images/:id Delete image
```
**CDN Endpoints (public, no auth):**
```
GET /cdn/{org}/{project}/img/{id} Get image by UUID
GET /cdn/{org}/{project}/img/@{alias} Get image by alias
```
**Source:** Use `/docs/api/images-upload.md`
**Link to:** `/docs/images` for guide/context
---
### Page 9: `/docs/api/flows` — Flows Endpoints
**SEO Title:** "Flows API | Banatie API Reference"
**Brief intro:** Flows group related generations together. They're created automatically when you chain generations using the same flowId.
**Endpoints:**
```
GET /api/v1/flows List flows
GET /api/v1/flows/:id Get flow
GET /api/v1/flows/:id/generations List flow generations
GET /api/v1/flows/:id/images List flow images
PUT /api/v1/flows/:id/aliases Update flow aliases
DELETE /api/v1/flows/:id/aliases/:alias Remove flow alias
DELETE /api/v1/flows/:id Delete flow
POST /api/v1/flows/:id/regenerate Regenerate last in flow
```
**Source:** Use `/docs/api/image-generation-advanced.md` section on flows
**Link to:** `/docs/generation` (section on continuing generations)
---
### Page 10: `/docs/api/live-scopes` — Live Scopes Endpoints
**SEO Title:** "Live Scopes API | Banatie API Reference"
**Endpoints:**
```
POST /api/v1/live/scopes Create scope
GET /api/v1/live/scopes List scopes
GET /api/v1/live/scopes/:slug Get scope
PUT /api/v1/live/scopes/:slug Update scope
DELETE /api/v1/live/scopes/:slug Delete scope
POST /api/v1/live/scopes/:slug/regenerate Regenerate scope images
```
**CDN Live Endpoint (public):**
```
GET /cdn/{org}/{project}/live/{scope}?prompt=... Live generation
```
Query parameters: prompt (required), aspectRatio, autoEnhance, template
**Source:** Use `/docs/api/live-url.md`
**Link to:** `/docs/live-urls` for guide/context
---
## Implementation Notes for Claude Code
1. **Use existing components** — Check `/apps/landing/src/app/docs/` for current implementation patterns
2. **Correct URLs everywhere:**
- API: `https://api.banatie.app`
- CDN: `https://cdn.banatie.app`
- NOT `.com` — always `.app`
3. **Example paths use:** `my-org/my-project` (not `default/my-project`)
4. **No SDK references** — We don't have SDK yet. Don't mention it.
5. **API is synchronous** — POST /generations returns completed result immediately. No polling.
6. **Prompt templates, not "enhancement"** — We have templates that improve prompts. Don't call it "auto-enhance" as a standalone feature.
7. **Breadcrumbs:** Every page should show path (e.g., "Docs > API Reference > Generations")
8. **Meta tags:** Each page needs proper SEO title and description as specified
9. **Mobile responsive** — Documentation must work well on mobile
10. **Code examples:** Use `bash` (curl) as primary. Show request AND response for every endpoint.
11. **Image dimensions in examples:** Use 1792 x 1008 (16:9) not 1024 x 1024
---
## File Structure Expected
```
apps/landing/src/app/docs/
├── page.tsx # /docs (Get Started)
├── generation/
│ └── page.tsx # /docs/generation
├── images/
│ └── page.tsx # /docs/images
├── live-urls/
│ └── page.tsx # /docs/live-urls
├── authentication/
│ └── page.tsx # /docs/authentication
└── api/
├── page.tsx # /docs/api (Overview)
├── generations/
│ └── page.tsx # /docs/api/generations
├── images/
│ └── page.tsx # /docs/api/images
├── flows/
│ └── page.tsx # /docs/api/flows
└── live-scopes/
└── page.tsx # /docs/api/live-scopes
```
---
## Priority Order for Implementation
1. `/docs` — Get Started (content provided above)
2. `/docs/generation` — Core feature
3. `/docs/api` — Reference hub
4. `/docs/api/generations` — Most used endpoints
5. `/docs/images` — Working with results
6. `/docs/api/images` — Image endpoints
7. `/docs/live-urls` — Highlight feature
8. `/docs/api/live-scopes` — Live management
9. `/docs/authentication` — Auth info
10. `/docs/api/flows` — Least priority (advanced users)
---
## Quality Checklist
Before marking complete, verify:
- [ ] All URLs use `banatie.app` (not `.com`)
- [ ] Example paths use `my-org/my-project`
- [ ] Image dimensions are 1792 x 1008 in examples
- [ ] All code examples are copy-paste ready
- [ ] Every endpoint shows request AND response
- [ ] Tables render correctly
- [ ] Callout blocks used for visual variety
- [ ] Cross-links between guide and reference pages
- [ ] Sidebar navigation matches URL structure
- [ ] Breadcrumbs work on all pages
- [ ] Mobile rendering is acceptable
- [ ] No references to SDK or features that don't exist
- [ ] No polling/async flow — API is synchronous
- [ ] SEO titles and descriptions set for all pages
- [ ] Tone matches "Documentation Spirit" section
---
**End of Specification**