# Banatie API Reference

Banatie is a REST API service for AI-powered image generation using the Gemini Flash Image model.

## Base URL

```
http://localhost:3000
```

## Authentication

All API endpoints (except `/health`, `/api/info`, and `/api/bootstrap/*`) require authentication via API key.

### API Key Types

1. **Master Keys** - Full admin access, never expire, can create/revoke other keys
2. **Project Keys** - Standard access for image generation, expire in 90 days

### Using API Keys

Include your API key in the `X-API-Key` header:

```bash
curl -X POST http://localhost:3000/api/generate \
  -H "X-API-Key: bnt_your_key_here" \
  -F "prompt=..." \
  -F "filename=..."
```

### Getting Your First API Key

1. **Bootstrap** - Create initial master key (one-time only):
   ```bash
   curl -X POST http://localhost:3000/api/bootstrap/initial-key
   ```

2. **Create Project Key** - Use master key to create project keys:
   ```bash
   curl -X POST http://localhost:3000/api/admin/keys \
     -H "X-API-Key: YOUR_MASTER_KEY" \
     -H "Content-Type: application/json" \
     -d '{"type": "project", "projectId": "my-project", "name": "My Project Key"}'
   ```

**Important:** Save keys securely when created - they cannot be retrieved later!

## Content Types

- **Request**: `multipart/form-data` for file uploads, `application/json` for JSON endpoints
- **Response**: `application/json`

## Rate Limits

All authenticated endpoints (those requiring API keys) are rate limited:

- **Per API Key:** 100 requests per hour
- **Applies to:**
  - `POST /api/generate`
  - `POST /api/text-to-image`
  - `POST /api/upload`
  - `POST /api/enhance`
- **Not rate limited:**
  - Public endpoints (`GET /health`, `GET /api/info`)
  - Bootstrap endpoint (`POST /api/bootstrap/initial-key`)
  - Admin endpoints (require master key, but no rate limit)
  - Image serving endpoints (`GET /api/images/:orgId/:projectId/:category/:filename`)

Rate limit information included in response headers:
- `X-RateLimit-Limit`: Maximum requests per window
- `X-RateLimit-Remaining`: Requests remaining
- `X-RateLimit-Reset`: When the limit resets (ISO 8601)

**429 Too Many Requests:** Returned when limit exceeded with `Retry-After` header

---

## Endpoints

### Overview

| Endpoint | Method | Authentication | Rate Limit | Description |
|----------|--------|----------------|------------|-------------|
| `/health` | GET | None | No | Health check |
| `/api/info` | GET | None | No | API information |
| `/api/bootstrap/initial-key` | POST | None (one-time) | No | Create first master key |
| `/api/admin/keys` | POST | Master Key | No | Create new API keys |
| `/api/admin/keys` | GET | Master Key | No | List all API keys |
| `/api/admin/keys/:keyId` | DELETE | Master Key | No | Revoke API key |
| `/api/generate` | POST | API Key | 100/hour | Generate images with files |
| `/api/text-to-image` | POST | API Key | 100/hour | Generate images (JSON only) |
| `/api/upload` | POST | API Key | 100/hour | Upload single image file |
| `/api/enhance` | POST | API Key | 100/hour | Enhance text prompts |
| `/api/images/:orgId/:projectId/:category/:filename` | GET | None | No | Serve specific image file |
| `/api/images/generated` | GET | API Key | 100/hour | List generated images |

---

### Authentication & Admin

#### `POST /api/bootstrap/initial-key`

Create the first master API key. This endpoint works only once when no keys exist.

**Authentication:** None required (public endpoint, one-time use)

**Response (201):**
```json
{
  "apiKey": "bnt_...",
  "type": "master",
  "name": "Initial Master Key",
  "expiresAt": null,
  "message": "IMPORTANT: Save this key securely. You will not see it again!"
}
```

**Error (403):**
```json
{
  "error": "Bootstrap not allowed",
  "message": "API keys already exist. Use /api/admin/keys to create new keys."
}
```

---

#### `POST /api/admin/keys`

Create a new API key (master or project).

**Authentication:** Master key required via `X-API-Key` header

**Request Body:**
```json
{
  "type": "master | project",
  "projectId": "required-for-project-keys",
  "name": "optional-friendly-name",
  "expiresInDays": 90
}
```

**Response (201):**
```json
{
  "apiKey": "bnt_...",
  "metadata": {
    "id": "uuid",
    "type": "project",
    "projectId": "my-project",
    "name": "My Project Key",
    "expiresAt": "2025-12-29T17:08:02.536Z",
    "scopes": ["generate", "read"],
    "createdAt": "2025-09-30T17:08:02.553Z"
  },
  "message": "IMPORTANT: Save this key securely. You will not see it again!"
}
```

---

#### `GET /api/admin/keys`

List all API keys.

**Authentication:** Master key required

**Response (200):**
```json
{
  "keys": [
    {
      "id": "uuid",
      "type": "master",
      "projectId": null,
      "name": "Initial Master Key",
      "scopes": ["*"],
      "isActive": true,
      "createdAt": "2025-09-30T17:01:23.456Z",
      "expiresAt": null,
      "lastUsedAt": "2025-09-30T17:08:45.123Z",
      "createdBy": null
    }
  ],
  "total": 1
}
```

---

#### `DELETE /api/admin/keys/:keyId`

Revoke an API key (soft delete).

**Authentication:** Master key required

**Response (200):**
```json
{
  "message": "API key revoked successfully",
  "keyId": "uuid"
}
```

---

### Health Check

#### `GET /health`

Health check endpoint with server status.

**Response:**
```json
{
  "status": "healthy",
  "timestamp": "2023-11-20T10:00:00.000Z",
  "uptime": 12345.67,
  "environment": "development",
  "version": "1.0.0"
}
```

---

### API Information

#### `GET /api/info`

Returns API metadata and configuration limits.

**Response:**
```json
{
  "name": "Banatie - Nano Banana Image Generation API",
  "version": "1.0.0",
  "description": "REST API service for AI-powered image generation using Gemini Flash Image model",
  "endpoints": {
    "GET /health": "Health check",
    "GET /api/info": "API information",
    "POST /api/generate": "Generate images from text prompt with optional reference images",
    "POST /api/text-to-image": "Generate images from text prompt only (JSON)",
    "POST /api/enhance": "Enhance and optimize prompts for better image generation"
  },
  "limits": {
    "maxFileSize": "5MB",
    "maxFiles": 3,
    "supportedFormats": ["PNG", "JPEG", "JPG", "WebP"]
  }
}
```

---

### Generate Image

#### `POST /api/generate`

Generate images from text prompts with optional reference images.

**Authentication:** API key required (master or project)
**Rate Limit:** 100 requests per hour per API key

**Content-Type:** `multipart/form-data`

**Parameters:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `prompt` | string | Yes | Text description of the image to generate (1-5000 chars) |
| `filename` | string | Yes | Desired filename for the generated image |
| `files` | file[] | No | Reference images (max 3 files, 5MB each) |
| `autoEnhance` | boolean | No | Enable automatic prompt enhancement |
| `enhancementOptions` | object | No | Enhancement configuration options |

**Enhancement Options:**

| Field | Type | Options | Default | Description |
|-------|------|---------|---------|-------------|
| `template` | string | `photorealistic`, `illustration`, `minimalist`, `sticker`, `product`, `comic`, `general` | `photorealistic` | Prompt engineering template to apply |

**Example Request:**
```bash
curl -X POST http://localhost:3000/api/generate \
  -H "X-API-Key: bnt_your_api_key_here" \
  -F "prompt=A majestic mountain landscape at sunset" \
  -F "filename=mountain-sunset" \
  -F "autoEnhance=true" \
  -F "files=@reference1.jpg" \
  -F "files=@reference2.png"
```

**Success Response (200):**
```json
{
  "success": true,
  "message": "Image generated successfully",
  "data": {
    "filename": "mountain-sunset-20231120-100000.png",
    "filepath": "./results/mountain-sunset-20231120-100000.png",
    "description": "Generated image description",
    "model": "gemini-1.5-flash",
    "generatedAt": "2023-11-20T10:00:00.000Z",
    "promptEnhancement": {
      "originalPrompt": "A mountain landscape",
      "enhancedPrompt": "A majestic mountain landscape at golden hour with dramatic lighting",
      "detectedLanguage": "en",
      "appliedTemplate": "scenic_landscape",
      "enhancements": ["lighting_enhancement", "composition_improvement"]
    }
  }
}
```

**Error Response (400/500):**
```json
{
  "success": false,
  "message": "Image generation failed",
  "error": "Validation failed: Prompt is required"
}
```

---

### Text-to-Image (JSON)

#### `POST /api/text-to-image`

Generate images from text prompts only using JSON payload. Simplified endpoint for text-only requests without file uploads.

**Authentication:** API key required (master or project)
**Rate Limit:** 100 requests per hour per API key

**Content-Type:** `application/json`

**Request Body:**
```json
{
  "prompt": "A beautiful sunset over mountains",
  "filename": "sunset_image",
  "aspectRatio": "16:9",
  "autoEnhance": true,
  "enhancementOptions": {
    "template": "photorealistic",
    "mood": "peaceful",
    "lighting": "golden hour"
  }
}
```

**Parameters:**

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `prompt` | string | Yes | - | Text description of the image to generate (3-2000 chars) |
| `filename` | string | Yes | - | Desired filename for the generated image (alphanumeric, underscore, hyphen only) |
| `aspectRatio` | string | No | `"1:1"` | Image aspect ratio (`"1:1"`, `"2:3"`, `"3:2"`, `"3:4"`, `"4:3"`, `"4:5"`, `"5:4"`, `"9:16"`, `"16:9"`, `"21:9"`) |
| `autoEnhance` | boolean | No | `true` | Enable automatic prompt enhancement (set to `false` to use prompt as-is) |
| `enhancementOptions` | object | No | - | Enhancement configuration options |
| `meta` | object | No | - | Metadata for request tracking |

**Enhancement Options:**

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `template` | string | No | `"photorealistic"` | Prompt engineering template: `"photorealistic"`, `"illustration"`, `"minimalist"`, `"sticker"`, `"product"`, `"comic"`, `"general"` |

**Meta Object:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `tags` | string[] | No | Array of string tags for tracking/grouping requests (not stored, only logged) |

**Example Request:**
```bash
curl -X POST http://localhost:3000/api/text-to-image \
  -H "X-API-Key: bnt_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A beautiful sunset over mountains with golden clouds",
    "filename": "test_sunset",
    "aspectRatio": "16:9",
    "autoEnhance": true,
    "enhancementOptions": {
      "template": "photorealistic"
    },
    "meta": {
      "tags": ["demo", "sunset"]
    }
  }'
```

**Success Response (200):**
```json
{
  "success": true,
  "message": "Image generated successfully",
  "data": {
    "filename": "test_sunset.png",
    "filepath": "results/test_sunset.png",
    "description": "Here's a beautiful sunset over mountains with golden clouds for you!",
    "model": "Nano Banana",
    "generatedAt": "2025-09-26T15:04:27.705Z",
    "promptEnhancement": {
      "originalPrompt": "A beautiful sunset over mountains",
      "enhancedPrompt": "A breathtaking photorealistic sunset over majestic mountains...",
      "detectedLanguage": "English",
      "appliedTemplate": "landscape",
      "enhancements": ["lighting_enhancement", "composition_improvement"]
    }
  }
}
```

**Error Response (400/500):**
```json
{
  "success": false,
  "message": "Validation failed",
  "error": "Prompt is required"
}
```

**Key Differences from /api/generate:**
- **JSON only**: No file upload support
- **Faster**: No multipart parsing overhead
- **Simpler testing**: Easy to use with curl or API clients
- **Same features**: Supports all enhancement options
- **Auto-enhance by default**: `autoEnhance` defaults to `true`, set explicitly to `false` to use prompt as-is

**Template Descriptions:**
- `photorealistic`: Photography-focused with camera angles, lens types, lighting, and fine details
- `illustration`: Art style specifications with line work, color palette, and shading techniques
- `minimalist`: Emphasis on negative space, simple composition, and subtle elements
- `sticker`: Bold outlines, kawaii style, clean design, transparent background style
- `product`: Studio lighting setups, commercial photography terms, surfaces, and angles
- `comic`: Panel style, art technique, mood, and dialogue/caption integration
- `general`: Balanced approach with clear descriptions and artistic detail

---

### Upload File

#### `POST /api/upload`

Upload a single image file to project storage.

**Authentication:** Project API key required (master keys not allowed)
**Rate Limit:** 100 requests per hour per API key

**Content-Type:** `multipart/form-data`

**Parameters:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `file` | file | Yes | Single image file (PNG, JPEG, JPG, WebP) |
| `metadata` | JSON | No | Optional metadata (description, tags) |

**File Specifications:**
- **Max file size:** 5MB
- **Supported formats:** PNG, JPEG, JPG, WebP
- **Max files per request:** 1

**Example Request:**
```bash
curl -X POST http://localhost:3000/api/upload \
  -H "X-API-Key: bnt_your_project_key_here" \
  -F "file=@image.png" \
  -F 'metadata={"description":"Product photo","tags":["demo","test"]}'
```

**Success Response (200):**
```json
{
  "success": true,
  "message": "File uploaded successfully",
  "data": {
    "filename": "image-1728561234567-a1b2c3.png",
    "originalName": "image.png",
    "path": "org-slug/project-slug/uploads/image-1728561234567-a1b2c3.png",
    "url": "http://localhost:3000/api/images/org-slug/project-slug/uploads/image-1728561234567-a1b2c3.png",
    "size": 123456,
    "contentType": "image/png",
    "uploadedAt": "2025-10-10T12:00:00.000Z"
  }
}
```

**Error Response (400 - No file):**
```json
{
  "success": false,
  "message": "File upload failed",
  "error": "No file provided"
}
```

**Error Response (400 - Invalid file type):**
```json
{
  "success": false,
  "message": "File validation failed",
  "error": "Unsupported file type: image/gif. Allowed: PNG, JPEG, WebP"
}
```

**Error Response (400 - File too large):**
```json
{
  "success": false,
  "message": "File upload failed",
  "error": "File too large. Maximum size: 5MB"
}
```

**Storage Details:**
- Files are stored in MinIO under: `{orgSlug}/{projectSlug}/uploads/`
- Filenames are automatically made unique with timestamp and random suffix
- Original filename is preserved in response
- Uploaded files can be accessed via the returned URL

---

### Enhance Prompt

#### `POST /api/enhance`

Enhance and optimize text prompts for better image generation results.

**Authentication:** API key required (master or project)
**Rate Limit:** 100 requests per hour per API key

**Content-Type:** `application/json`

**Request Body:**
```json
{
  "prompt": "A mountain landscape",
  "options": {
    "imageStyle": "photorealistic",
    "aspectRatio": "landscape",
    "mood": "serene and peaceful",
    "lighting": "golden hour",
    "cameraAngle": "wide shot",
    "outputFormat": "detailed",
    "negativePrompts": ["blurry", "low quality"]
  }
}
```

**Parameters:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `prompt` | string | Yes | Original text prompt (1-5000 chars) |
| `options` | object | No | Enhancement configuration |

**Success Response (200):**
```json
{
  "success": true,
  "originalPrompt": "A mountain landscape",
  "enhancedPrompt": "A breathtaking photorealistic mountain landscape during golden hour, featuring dramatic peaks and valleys with warm, soft lighting creating a serene and peaceful atmosphere, captured in a wide shot composition with rich detail and depth",
  "detectedLanguage": "en",
  "appliedTemplate": "scenic_landscape",
  "metadata": {
    "style": "photorealistic",
    "aspectRatio": "landscape",
    "enhancements": [
      "lighting_enhancement",
      "composition_improvement",
      "atmosphere_addition",
      "detail_specification"
    ]
  }
}
```

**Error Response (400/500):**
```json
{
  "success": false,
  "originalPrompt": "A mountain landscape",
  "error": "Validation failed: Prompt is required"
}
```

---

## Error Codes

| Code | Description |
|------|-------------|
| 400 | Bad Request - Invalid parameters or validation failure |
| 401 | Unauthorized - Missing, invalid, expired, or revoked API key |
| 403 | Forbidden - Insufficient permissions (e.g., master key required) |
| 404 | Not Found - Endpoint or resource does not exist |
| 429 | Too Many Requests - Rate limit exceeded |
| 500 | Internal Server Error - Server configuration or processing error |

## Common Error Messages

### Authentication Errors (401)
- `"Missing API key"` - No X-API-Key header provided
- `"Invalid API key"` - The provided API key is invalid, expired, or revoked
- **Affected endpoints:** `/api/generate`, `/api/text-to-image`, `/api/upload`, `/api/enhance`, `/api/admin/*`

### Authorization Errors (403)
- `"Master key required"` - This endpoint requires a master API key (not project key)
- `"Bootstrap not allowed"` - API keys already exist, cannot bootstrap again
- **Affected endpoints:** `/api/admin/*`, `/api/bootstrap/initial-key`

### Validation Errors (400)
- `"Prompt is required"` - Missing or empty prompt parameter
- `"Reference image validation failed"` - Invalid file format or size
- `"Validation failed"` - Parameter validation error

### Rate Limiting Errors (429)
- `"Rate limit exceeded"` - Too many requests, retry after specified time
- **Applies to:** `/api/generate`, `/api/text-to-image`, `/api/upload`, `/api/enhance`
- **Rate limit:** 100 requests per hour per API key
- **Response includes:** `Retry-After` header with seconds until reset

### Server Errors
- `"Server configuration error"` - Missing GEMINI_API_KEY or database connection
- `"Image generation failed"` - AI service error
- `"Authentication failed"` - Error during authentication process

---

## File Upload Specifications

**Supported Formats:** PNG, JPEG, JPG, WebP
**Maximum File Size:** 5MB per file
**Maximum Files:** 3 files per request
**Storage:** Temporary files in `./uploads/temp`, results in `./results`

## Request Headers

| Header | Value | Description |
|--------|-------|-------------|
| `X-API-Key` | string | API key for authentication (required for most endpoints) |
| `X-Request-ID` | string | Unique request identifier (auto-generated by server) |

## Response Headers

| Header | Description |
|--------|-------------|
| `X-Request-ID` | Request identifier for tracking |
| `X-RateLimit-Limit` | Maximum requests allowed per window |
| `X-RateLimit-Remaining` | Requests remaining in current window |
| `X-RateLimit-Reset` | When the rate limit resets (ISO 8601) |

## CORS

Cross-origin requests supported from:
- `http://localhost:3001` (Landing Page)
- `http://localhost:3002` (Studio Platform)
- `http://localhost:3003` (Admin Dashboard)

Configure additional origins via `CORS_ORIGIN` environment variable.