Kolbo.AIKolbo.AI Docs
Developer API

Build with Lovable, Base44 & More

Ready-to-paste prompts for Lovable, Base44, Bolt, v0 and other AI app builders. Build working apps with Kolbo API integration in one prompt.

Copy any prompt below and paste it directly into your AI app builder (Lovable, Base44, Bolt, v0, etc.). Replace YOUR_API_KEY with your actual API key from the Developer Console.

Each prompt is self-contained and produces a working app with real API calls.


Full Creative Studio

Build a complete app with image, video, music, and chat generation.

Build a creative AI studio web app using the Kolbo API. The app should have a clean, modern UI with a sidebar for navigation between tools.

## API Configuration

- Base URL: `https://api.kolbo.ai/api`
- Auth: All requests need header `X-API-Key: YOUR_API_KEY`
- All generation endpoints are async: you POST to create, get back a `poll_url` and a `poll_interval_hint` (seconds), then poll `GET {BASE}{poll_url}` until `state` is `"completed"`, `"failed"` or `"cancelled"` (anything else is still `"processing"`). A failed poll carries the reason in `error`.
- NEVER hardcode or guess model names. Always fetch available models from the API first.

## Core API Helpers (use these everywhere)

```javascript
const API_KEY = "YOUR_API_KEY";
const BASE = "https://api.kolbo.ai/api";
const HEADERS = { "X-API-Key": API_KEY, "Content-Type": "application/json" };

// Step 1: On app startup, fetch available models for each type and cache them.
// The API uses SDK-friendly type names: image, image_edit, video, video_from_image, music, speech, sound, chat
let cachedModels = {};

async function fetchModels(type) {
  const res = await fetch(`${BASE}/v1/models?type=${type}`, {
    headers: { "X-API-Key": API_KEY },
  });
  const data = await res.json();
  cachedModels[type] = data.models || [];
  return cachedModels[type];
}

// Call this on app init to populate model lists for dropdowns
async function initModels() {
  await Promise.all([
    fetchModels("image"),
    fetchModels("video"),
    fetchModels("video_from_image"),
    fetchModels("music"),
    fetchModels("chat"),
  ]);
}

// Step 2: Generate and poll helper
async function generate(endpoint, body) {
  const res = await fetch(`${BASE}${endpoint}`, {
    method: "POST",
    headers: HEADERS,
    body: JSON.stringify(body),
  });
  const data = await res.json();
  if (!data.success) throw new Error(data.error);

  const waitMs = (data.poll_interval_hint || 3) * 1000;
  while (true) {
    await new Promise((r) => setTimeout(r, waitMs));
    const poll = await fetch(`${BASE}${data.poll_url}`, {
      headers: { "X-API-Key": API_KEY },
    });
    const status = await poll.json();
    if (status.state === "completed") return status.result;
    if (status.state === "failed" || status.state === "cancelled") {
      throw new Error(status.error || `Generation ${status.state}`);
    }
  }
}

// Step 3: Get credit balance
async function getCredits() {
  const res = await fetch(`${BASE}/v1/account/credits`, {
    headers: { "X-API-Key": API_KEY },
  });
  return (await res.json()).credits.total;
}
```

## Tools to Build

### 1. Image Generator
- Endpoint: `POST /v1/generate/image`
- Body: `{ "prompt": "user input", "aspect_ratio": "1:1" }`
- Optional: add `"model": "identifier"` from `cachedModels.image` — if omitted, Smart Select picks the best model
- Show a model dropdown populated from `cachedModels.image` with an "Auto (Smart Select)" option as default
- Optional: `"num_images"` (1-4, default 1), `"resolution"` (one of the model's `supported_resolutions`), and `"reference_images"` — an ARRAY of public image URLs, so users can attach several references at once; cap the picker at the selected model's `max_reference_images`
- Response result has `urls` array of image URLs — display them in a grid
- NEVER hardcode aspect ratios. Build the selector from the chosen model's `supported_aspect_ratios` (or `supported_aspect_ratios_by_type` when present), defaulting to `default_aspect_ratio`. On "Auto" leave `aspect_ratio` out (the server then uses `1:1`).

### 2. Text-to-Video Generator
- Endpoint: `POST /v1/generate/video`
- Body: `{ "prompt": "user input", "duration": 5, "aspect_ratio": "16:9" }`
- Optional: add `"model": "identifier"` from `cachedModels.video` — if omitted, Smart Select picks the best model
- Show a model dropdown populated from `cachedModels.video` with an "Auto" default
- Optional: `"resolution"` (one of the model's `supported_resolutions`) and `"sound_enabled": true|false` for models whose `sound_generation_type` is not `"none"`
- This endpoint takes at most ONE `reference_images` entry (the request is then routed to image-to-video); two or more return `400 TOO_MANY_REFERENCE_IMAGES`, and a chosen model with no image-to-video variant returns `400 REFERENCE_IMAGES_NOT_SUPPORTED`. For several reference images, videos or audio clips use `POST /v1/generate/elements` instead
- Response result has `urls` array — render as `<video>` elements (use `playback_urls[i]` as the preview `src` when present; keep `urls[i]` for download)
- NEVER hardcode durations or aspect ratios. Build both selectors from the chosen model's `supported_durations` / `supported_aspect_ratios`, defaulting to `default_duration` / `default_aspect_ratio` (if you omit them the server sends `5` seconds and `16:9`)
- Polling takes longer (30-120 seconds) — show a progress indicator

### 3. Image-to-Video Generator
- Endpoint: `POST /v1/generate/video/from-image`
- Body: `{ "prompt": "describe the motion", "image_url": "https://...", "duration": 5, "aspect_ratio": "16:9" }`
- The `image_url` is a publicly accessible URL of the source image
- Optional: add `"model": "identifier"` from `cachedModels.video_from_image` — if omitted, Smart Select picks the best model
- Show a model dropdown populated from `cachedModels.video_from_image` with an "Auto" default
- Let users upload an image or paste a URL as the source frame
- `prompt` is optional on this endpoint; `image_url` is required and takes ONE image (a missing one returns `400 image_url is required`). For multi-reference video use `POST /v1/generate/elements`
- Response result has `urls` array — render as `<video>` elements
- Same rule as above: durations and aspect ratios come from the model's `supported_durations` / `supported_aspect_ratios`

### 4. Music Generator
- Endpoint: `POST /v1/generate/music`
- Body: `{ "prompt": "user input", "duration_seconds": 30 }` — the length field is `duration_seconds` (a field named `duration` is ignored)
- Optional: add `"model": "identifier"` from `cachedModels.music` — if omitted the server uses `suno-v6`, not Smart Select
- Optional: `"instrumental": true`, `"lyrics"`, `"style"`, `"title"`
- Show a model dropdown populated from `cachedModels.music` with a "Default" option that omits `model`
- Response result has `urls` array of audio URLs — render as `<audio>` players, plus a `tracks` array with `title` / `duration` / `thumbnail_url` per track
- Duration bounds are per model — read `min_output_duration` / `max_output_duration` (and `default_duration`) from the model entry. The server clamps `duration_seconds` to 5-600 and each model clamps again to its own window

### 5. AI Chat
- Endpoint: `POST /v1/chat`
- Body: `{ "message": "user input" }`
- Optional: add `"model": "identifier"` from `cachedModels.chat` — if omitted, Smart Select picks the best model
- Show a model dropdown populated from `cachedModels.chat` with an "Auto (Smart Select)" option as default
- For follow-up messages, include `"session_id"` from the first response
- Response result has `content` (the AI text reply), plus `reasoning_content` and `image_urls` / `video_urls` / `audio_urls` when the model returns them
- Optional: `"web_search": true`, and `"media_urls"` — an array of public image/video/audio URLs to attach to the message
- Show conversation history in a chat bubble UI

### 6. Credit Balance
- Endpoint: `GET /v1/account/credits`
- Show in the header/sidebar: `credits.total` from the response

## Model Selection UI
- Each tool should have a dropdown showing available models fetched from the API
- Default selection is "Auto (Smart Select)" which omits the `model` field
- When user picks a specific model, send its `identifier` as the `model` field
- Show each model's `name` and its `credit` field in the dropdown, e.g. `` `${m.name} — ${m.credit} credits` `` — never a price you typed yourself. `credit` is the base price: the final cost is multiplied by `resolution_multipliers[resolution]` (and `sound_credit_multiplier` when sound is on). Chat models bill per token (`input_token_rate` / `output_token_rate`, credits per 1K tokens), so a chat model's `credit` is not the exact per-reply charge
- After completion the status response carries `credits_used` — the amount actually charged
- NEVER hardcode model names, identifiers or prices — always render them from `cachedModels`

## UI Requirements
- Responsive layout — works on mobile and desktop
- Each tool gets its own page/tab in the sidebar
- Show loading spinners while polling
- Display errors clearly if generation fails
- Show credit balance in the top bar
- Call `initModels()` on app startup before rendering tools

Image Generator App

A focused image generation app with gallery.

Build an AI image generator web app using the Kolbo API.

## API Details

- Base URL: `https://api.kolbo.ai/api`
- Auth header on every request: `X-API-Key: YOUR_API_KEY`
- NEVER hardcode or guess model names. Fetch them from the API.

## Complete API Helper

```javascript
const API_KEY = "YOUR_API_KEY";
const BASE = "https://api.kolbo.ai/api";
const HEADERS = { "X-API-Key": API_KEY, "Content-Type": "application/json" };

// Fetch available image models on startup — populate a dropdown from these
let imageModels = [];

async function initModels() {
  const res = await fetch(`${BASE}/v1/models?type=image`, { headers: { "X-API-Key": API_KEY } });
  const data = await res.json();
  imageModels = data.models || [];
}

async function generateImage(prompt, aspectRatio = "1:1", model = null, referenceImages = []) {
  const body = { prompt, aspect_ratio: aspectRatio };
  if (model) body.model = model; // omit for Smart Select (auto)
  if (referenceImages.length) body.reference_images = referenceImages; // array of public image URLs
  const res = await fetch(`${BASE}/v1/generate/image`, {
    method: "POST",
    headers: HEADERS,
    body: JSON.stringify(body),
  });
  const data = await res.json();
  if (!data.success) throw new Error(data.error);

  while (true) {
    await new Promise((r) => setTimeout(r, (data.poll_interval_hint || 3) * 1000));
    const poll = await fetch(`${BASE}${data.poll_url}`, { headers: { "X-API-Key": API_KEY } });
    const status = await poll.json();
    if (status.state === "completed") return status.result.urls;
    if (status.state === "failed" || status.state === "cancelled") {
      throw new Error(status.error || `Generation ${status.state}`);
    }
  }
}
```

## App Features

1. **Prompt input** — text area with a "Generate" button
2. **Model selector** — dropdown populated from `imageModels`, default "Auto (Smart Select)". Label each option with the model's own `name` and `credit` fields (`` `${m.name} — ${m.credit} credits` ``) — never a hardcoded name or price. When "Auto" is selected, don't send a `model` field.
3. **Aspect ratio selector** — buttons built from the selected model's `supported_aspect_ratios`, defaulting to its `default_aspect_ratio`. On "Auto", omit `aspect_ratio` entirely.
4. **Reference images** (optional) — let users add several image URLs; send them as the `reference_images` array and cap the count at the selected model's `max_reference_images`
5. **Loading state** — show spinner and "Generating..." text while polling
6. **Image display** — show generated images in a grid, click to view full size
7. **Gallery** — save previously generated images with their prompts (local storage)
8. **Download button** — download any generated image
9. **Error handling** — show error messages if generation fails
10. **Credits display** — fetch from `GET /v1/account/credits` and show `credits.total` in the header
11. Call `initModels()` on app startup

## UI Style
- Clean, minimal design with dark mode
- Responsive — works on mobile
- Use a card-based layout for the gallery

Video Generator App

Build an AI video generator web app using the Kolbo API. Support both text-to-video and image-to-video generation.

## API Details

- Base URL: `https://api.kolbo.ai/api`
- Auth header: `X-API-Key: YOUR_API_KEY`
- NEVER hardcode or guess model names. Fetch them from the API.

## Complete API Helper

```javascript
const API_KEY = "YOUR_API_KEY";
const BASE = "https://api.kolbo.ai/api";
const HEADERS = { "X-API-Key": API_KEY, "Content-Type": "application/json" };

// Fetch available models on startup — populate dropdowns from these
let textToVideoModels = [];
let imageToVideoModels = [];

async function initModels() {
  const [t2v, i2v] = await Promise.all([
    fetch(`${BASE}/v1/models?type=video`, { headers: { "X-API-Key": API_KEY } }).then(r => r.json()),
    fetch(`${BASE}/v1/models?type=video_from_image`, { headers: { "X-API-Key": API_KEY } }).then(r => r.json()),
  ]);
  textToVideoModels = t2v.models || [];
  imageToVideoModels = i2v.models || [];
}

// Text-to-Video
async function generateVideo(prompt, duration = 5, aspectRatio = "16:9", model = null) {
  const body = { prompt, duration, aspect_ratio: aspectRatio };
  if (model) body.model = model; // omit for Smart Select (auto)
  const res = await fetch(`${BASE}/v1/generate/video`, { method: "POST", headers: HEADERS, body: JSON.stringify(body) });
  const data = await res.json();
  if (!data.success) throw new Error(data.error);
  return pollResult(data.poll_url, data.poll_interval_hint);
}

// Image-to-Video
async function generateVideoFromImage(prompt, imageUrl, duration = 5, aspectRatio = "16:9", model = null) {
  const body = { prompt, image_url: imageUrl, duration, aspect_ratio: aspectRatio };
  if (model) body.model = model; // omit for Smart Select (auto)
  const res = await fetch(`${BASE}/v1/generate/video/from-image`, { method: "POST", headers: HEADERS, body: JSON.stringify(body) });
  const data = await res.json();
  if (!data.success) throw new Error(data.error);
  return pollResult(data.poll_url, data.poll_interval_hint);
}

// Shared polling helper
async function pollResult(pollUrl, intervalSeconds) {
  while (true) {
    await new Promise((r) => setTimeout(r, (intervalSeconds || 8) * 1000));
    const poll = await fetch(`${BASE}${pollUrl}`, { headers: { "X-API-Key": API_KEY } });
    const status = await poll.json();
    if (status.state === "completed") return status.result;
    if (status.state === "failed" || status.state === "cancelled") {
      throw new Error(status.error || `Generation ${status.state}`);
    }
  }
}
```

## App Features

1. **Two tabs**: "Text to Video" and "Image to Video"
2. **Text-to-Video tab**: prompt text area, plus duration and aspect-ratio selectors built from the selected model's `supported_durations` and `supported_aspect_ratios` (defaults `default_duration` / `default_aspect_ratio`). Never hardcode those lists.
3. **Image-to-Video tab**: same as above PLUS an image upload/URL input for the source frame (`image_url` is required here and takes ONE image; `prompt` is optional). Multi-reference video (several images, videos or audio clips) is a different endpoint, `POST /v1/generate/elements` — don't try to send it here
4. **Model selector** on both tabs — dropdown populated from `textToVideoModels` / `imageToVideoModels`, default "Auto (Smart Select)". Label each option from the model's own `name` and `credit` fields — never a hardcoded name or price. When "Auto" is selected, don't send a `model` field.
5. **Progress indicator** — show elapsed time while generating (videos take 30-120 seconds)
6. **Video player** — render result as `<video>` with controls, autoplay, and loop. Use `result.playback_urls[i]` as the `src` when that array is present (a browser-safe preview of a master the browser may not decode), otherwise `result.urls[i]`
7. **Thumbnail preview** — show `result.thumbnail_url` while video loads
8. **Download button** — download the video file from `result.urls[i]` (the master)
9. **History** — show previously generated videos with thumbnails (local storage)
10. **Credits display** — fetch from `GET /v1/account/credits` and show `credits.total` in the header
11. Call `initModels()` on app startup

## UI Style
- Modern dark UI
- Big centered video player for results
- Responsive layout

Music Generator App

Build an AI music generator web app using the Kolbo API.

## API Details

- Base URL: `https://api.kolbo.ai/api`
- Auth header: `X-API-Key: YOUR_API_KEY`
- NEVER hardcode or guess model names. Fetch them from the API.

## Complete API Helper

```javascript
const API_KEY = "YOUR_API_KEY";
const BASE = "https://api.kolbo.ai/api";
const HEADERS = { "X-API-Key": API_KEY, "Content-Type": "application/json" };

// Fetch available music models on startup — populate a dropdown from these
let musicModels = [];

async function initModels() {
  const res = await fetch(`${BASE}/v1/models?type=music`, { headers: { "X-API-Key": API_KEY } });
  const data = await res.json();
  musicModels = data.models || [];
}

async function generateMusic(prompt, durationSeconds = 30, model = null) {
  const body = { prompt, duration_seconds: durationSeconds }; // the field is duration_seconds, not duration
  if (model) body.model = model; // omit for the server default (suno-v6)
  const res = await fetch(`${BASE}/v1/generate/music`, {
    method: "POST",
    headers: HEADERS,
    body: JSON.stringify(body),
  });
  const data = await res.json();
  if (!data.success) throw new Error(data.error);

  while (true) {
    await new Promise((r) => setTimeout(r, (data.poll_interval_hint || 8) * 1000));
    const poll = await fetch(`${BASE}${data.poll_url}`, { headers: { "X-API-Key": API_KEY } });
    const status = await poll.json();
    if (status.state === "completed") return status.result; // urls[], tracks[], title, duration, lyrics
    if (status.state === "failed" || status.state === "cancelled") {
      throw new Error(status.error || `Generation ${status.state}`);
    }
  }
}
```

## App Features

1. **Prompt input** — describe the music style, mood, instruments
2. **Model selector** — dropdown populated from `musicModels`, default "Default" (omit `model`; the server then uses `suno-v6`). Label each option from the model's own `name` and `credit` fields — never a hardcoded name or price.
3. **Duration slider** — sent as `duration_seconds`; bounds come from the selected model's `min_output_duration` / `max_output_duration`, starting at `default_duration`
4. **Instrumental toggle and lyrics box** (optional) — send `instrumental: true` or a `lyrics` string
5. **Audio player** — one `<audio>` element per entry in `result.tracks` (each has `title`, `duration`, `thumbnail_url`), with waveform visualization if possible
6. **Download button** — download the generated audio
7. **History** — list of previously generated tracks with play buttons
8. **Credits display** — fetch from `GET /v1/account/credits` and show `credits.total` in the header
9. Call `initModels()` on app startup

## UI Style
- Music app aesthetic — dark background, accent colors
- Waveform or audio visualizer animation during playback

AI Chatbot App

Build an AI chatbot web app using the Kolbo API.

## API Details

- Base URL: `https://api.kolbo.ai/api`
- Auth header: `X-API-Key: YOUR_API_KEY`
- NEVER hardcode or guess model names. Fetch them from the API.

## Complete API Helper

```javascript
const API_KEY = "YOUR_API_KEY";
const BASE = "https://api.kolbo.ai/api";
const HEADERS = { "X-API-Key": API_KEY, "Content-Type": "application/json" };

// Fetch available chat models on startup — populate a dropdown from these
let chatModels = [];

async function initModels() {
  const res = await fetch(`${BASE}/v1/models?type=chat`, { headers: { "X-API-Key": API_KEY } });
  const data = await res.json();
  chatModels = data.models || [];
}

async function sendMessage(message, sessionId = null, model = null) {
  const body = { message };
  if (sessionId) body.session_id = sessionId;
  if (model) body.model = model; // omit for Smart Select (auto)

  const res = await fetch(`${BASE}/v1/chat`, { method: "POST", headers: HEADERS, body: JSON.stringify(body) });
  const data = await res.json();
  if (!data.success) throw new Error(data.error);

  while (true) {
    await new Promise((r) => setTimeout(r, (data.poll_interval_hint || 2) * 1000));
    const poll = await fetch(`${BASE}${data.poll_url}`, { headers: { "X-API-Key": API_KEY } });
    const status = await poll.json();
    if (status.state === "completed") return {
      content: status.result.content,
      session_id: data.session_id,
    };
    if (status.state === "failed" || status.state === "cancelled") {
      throw new Error(status.error || `Chat ${status.state}`);
    }
  }
}

// Paginated: page (default 1), limit (default 20, max 50). Items: { session_id, name, project_id, last_activity, created_at }
async function getConversations(page = 1) {
  const res = await fetch(`${BASE}/v1/chat/conversations?page=${page}&limit=20`, { headers: { "X-API-Key": API_KEY } });
  return (await res.json()).conversations;
}

// Paginated, oldest first: page (default 1), limit (default 50, max 100). Items: { message_id, role, content, status, created_at, ... }
async function getMessages(sessionId, page = 1) {
  const res = await fetch(`${BASE}/v1/chat/conversations/${sessionId}/messages?page=${page}&limit=50`, { headers: { "X-API-Key": API_KEY } });
  return (await res.json()).messages;
}
```

## App Features

1. **Chat interface** — message bubbles for user and AI, auto-scroll to bottom
2. **Model selector** — dropdown populated from `chatModels`, default "Auto (Smart Select)". Label each option from the model's own `name` and `credit` fields — never a hardcoded name or price. When "Auto" is selected, don't send a `model` field.
3. **Input bar** — text input at the bottom with send button, submit on Enter
4. **Conversation list** — sidebar showing past conversations, fetch from `getConversations()`
5. **New conversation** — button to start fresh (omit session_id)
6. **Loading indicator** — typing dots animation while polling
7. **Markdown rendering** — AI responses may contain markdown, render it properly
8. **System prompt** — optional settings panel to set a custom `system_prompt`. It is only applied when the request has NO `session_id` (i.e. on the first message of a new conversation) and is silently ignored afterwards, so start a new conversation to change it.
9. **Credits display** — fetch from `GET /v1/account/credits` and show `credits.total` in the header
10. Call `initModels()` on app startup

## UI Style
- ChatGPT-style layout: sidebar + main chat area
- Dark mode
- Responsive — full screen chat on mobile

Tips

  • Replace YOUR_API_KEY with your real API key from Developer Console
  • Smart Select is automatic — you never need to specify a model. On image, video and chat the API picks the best one for each request; music without a model uses suno-v6.
  • If you need a specific model, first fetch available models: GET /v1/models?type=image (or video, video_from_image, music, chat) and use an identifier from the response as the model field in your request. An identifier the API does not recognize is rejected with 400 MODEL_NOT_FOUND (the error message suggests near matches); omit model instead if you want Smart Select (or suno-v6 on music). Always take identifiers from GET /v1/models.
  • Credit balance: Use GET /v1/account/credits to show remaining credits in your app.
  • Error handling: Check for data.success === false on every response — errors come back as { "success": false, "error": "...", "code": "..." }. The common ones: 403 INSUFFICIENT_CREDITS (the SDK checks your balance before it starts anything, so this is a 403, not a 402; the body also carries balance, required and pricing_url), 400 INVALID_PROMPT (empty or non-string prompt, or chat message), 400 INVALID_MODEL (model sent as something other than a string) and 400 TOO_MANY_REFERENCE_IMAGES (more than one reference_images entry on /v1/generate/video). A generation that fails after it was accepted shows up in the status poll as state: "failed" with an error message. A 429 comes from the per-endpoint rate limiter as { "status": false, "error": "Too many requests to sdk — the limit is 30 per 60s. Retry in 42s.", "message": "...", "limit": 30, "window_seconds": 60, "retryAfter": 42 } — note it uses status, not success, and carries no code field. See Errors & Limits.

Generation endpoints are rate limited per authenticated user in a 60-second window, and the limit is shared across endpoints, not per endpoint. POST /v1/generate/image, POST /v1/generate/image-edit and POST /v1/edit/image share one 30 requests/min counter. POST /v1/generate/video, /video/from-image, /music, /speech, /sound and the other generation routes share a second 30 requests/min counter — and so do POST /v1/chat, POST /v1/edit/video, POST /v1/media/upload and POST /v1/video/trim (POST /v1/transcribe has its own 100/min counter). So an app that uploads a file, generates video and chats in the same minute is spending from one allowance. The chat-history reads (GET /v1/chat/conversations and .../messages) use the separate 120/min media-library counter, and GET /v1/models, GET /v1/account/credits and status polling have no per-endpoint limit. Rejected or failed requests do not count against the window. Back off on 429 using retryAfter rather than retrying immediately.