Visual DNA
Create and manage Visual DNA presets for character/product/style consistency across generations.
Visual DNA captures the visual identity of a character, product, style, or environment from reference images. Once created, you can attach Visual DNAs to image and video generations to maintain consistency across outputs.
Create Visual DNA
Upload reference images and create a Visual DNA preset. The API analyzes your images and generates a reusable identity profile.
Endpoint
POST /api/v1/visual-dnaRequest Body (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Name for this Visual DNA (max 100 chars) |
dna_type | string | No | "character", "product", "style", or "environment" (default: "character") |
images | file(s) | Yes | 1-4 reference images |
prompt_helper | string | No | Additional description to guide the analysis |
Example
curl -X POST https://api.kolbo.ai/api/v1/visual-dna \
-H "X-API-Key: kolbo_live_..." \
-F "name=Emma" \
-F "dna_type=character" \
-F "[email protected]" \
-F "[email protected]" \
-F "prompt_helper=Young woman with red hair"Response
{
"success": true,
"visual_dna": {
"id": "6601a1b2c3d4e5f6a7b8c9d0",
"name": "Emma",
"dna_type": "character",
"description": "AI-generated visual analysis...",
"thumbnail_url": "https://cdn.kolbo.ai/visual-dna/...",
"images": ["https://cdn.kolbo.ai/..."],
"created_at": "2026-03-06T12:00:00Z"
}
}Visual DNA creation takes 10-30 seconds as the API analyzes your reference images.
List Visual DNAs
Returns all Visual DNAs accessible to your account. By default this includes your personal DNAs, global system presets (cast characters, etc.), and any organization-shared DNAs. Use query params to filter.
Endpoint
GET /api/v1/visual-dnaQuery Parameters
| Parameter | Type | Description |
|---|---|---|
scope | string | Filter by ownership: "personal" (your own), "global" (system presets/cast), "organization" (org-shared). Omit for all. |
search | string | Search by name, tags, or description (case-insensitive) |
collection | string | Filter global presets by collection: cast, influencers, props, locations, styles, glamour, street |
tags | string | Comma-separated tags to filter by (OR logic) |
Example
# List only your personal Visual DNAs
curl "https://api.kolbo.ai/api/v1/visual-dna?scope=personal" \
-H "X-API-Key: kolbo_live_..."
# Search global cast characters
curl "https://api.kolbo.ai/api/v1/visual-dna?scope=global&collection=cast&search=emma" \
-H "X-API-Key: kolbo_live_..."Response
{
"success": true,
"visual_dnas": [
{
"id": "6601a1b2c3d4e5f6a7b8c9d0",
"name": "Emma",
"dna_type": "character",
"description": "AI-generated visual analysis...",
"thumbnail_url": "https://cdn.kolbo.ai/...",
"images": ["https://cdn.kolbo.ai/..."],
"videos": [],
"audio_clips": [],
"is_global": false,
"content_scope": "personal",
"preset_collection": null,
"tags": ["portrait", "redhead"],
"generation_status": "ready",
"folder_id": null,
"gender": "female",
"ethnicity_preset": "caucasian",
"hair_color": "red",
"eye_color": "green",
"age_range_preset": "young-adult",
"created_at": "2026-03-06T12:00:00Z"
}
],
"count": 1
}Character-specific fields (gender, ethnicity, ethnicity_preset, body_type, body_type_preset, hair_color, eye_color, skin_tone, outfit, age_range_preset, specific_age) are included only for dna_type: "character". kling_voice_id is included when the DNA has a voice profile. is_shared is included when the DNA has been shared via a public link.
Get Visual DNA
Endpoint
GET /api/v1/visual-dna/:idExample
curl https://api.kolbo.ai/api/v1/visual-dna/6601a1b2c3d4e5f6a7b8c9d0 \
-H "X-API-Key: kolbo_live_..."Response
Returns the same fields as the list endpoint for a single Visual DNA.
{
"success": true,
"visual_dna": {
"id": "6601a1b2c3d4e5f6a7b8c9d0",
"name": "Emma",
"dna_type": "character",
"description": "AI-generated visual analysis...",
"thumbnail_url": "https://cdn.kolbo.ai/...",
"images": ["https://cdn.kolbo.ai/..."],
"videos": [],
"audio_clips": [],
"is_global": false,
"content_scope": "personal",
"preset_collection": null,
"tags": ["portrait", "redhead"],
"generation_status": "ready",
"folder_id": null,
"gender": "female",
"ethnicity_preset": "caucasian",
"hair_color": "red",
"eye_color": "green",
"age_range_preset": "young-adult",
"created_at": "2026-03-06T12:00:00Z"
}
}Delete Visual DNA
Endpoint
DELETE /api/v1/visual-dna/:idExample
curl -X DELETE https://api.kolbo.ai/api/v1/visual-dna/6601a1b2c3d4e5f6a7b8c9d0 \
-H "X-API-Key: kolbo_live_..."Response
{
"success": true,
"message": "Visual DNA deleted successfully"
}Global (system) Visual DNAs cannot be deleted.
Character Sheet (stronger character consistency)
For character DNAs, a multi-angle character sheet (turnaround) is the single biggest consistency booster — the same step the in-app Visual DNA wizard offers. Generate one from your reference images, then attach it when creating the DNA.
POST /api/v1/visual-dna/character-sheet| Field | Type | Required | Description |
|---|---|---|---|
image_urls | array | Yes | 1+ reference image URLs of the character (varied angles work best). |
Charges credits. Response:
{ "success": true, "character_sheet_url": "https://…", "credits_used": 12, "resolution": "2K" }Then pass character_sheet_url (as characterSheetUrl) when creating the DNA — POST /v1/visual-dna forwards it as the profile's primary reference. MCP: generate_character_sheet → create_visual_dna with character_sheet_url.
Folders — Organizing Your Characters
When a project accumulates many Visual DNAs (a large cast, multiple productions), organize them into user folders. Folders are flat (no nesting), unique-named per user, and hold personal DNAs only — global presets and organization DNAs cannot be placed in personal folders.
List Folders
GET /api/v1/visual-dna/foldersReturns each folder with its live item_count:
{
"success": true,
"folders": [
{ "id": "65f1…", "name": "Main Cast", "color": "#FF5733", "item_count": 6, "created_at": "…", "updated_at": "…" }
],
"count": 1
}To list the DNAs inside a folder, call GET /v1/visual-dna and filter by the folder_id field returned on each profile.
Create a Folder
POST /api/v1/visual-dna/folders| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Folder name (max 100 chars, unique per user — duplicates return 409). |
color | string | No | Hex color for the folder chip, e.g. #FF5733. |
Rename / Recolor a Folder
PUT /api/v1/visual-dna/folders/:folderIdBody: { "name": "…", "color": "#00AA00" } — name is required (pass the current name to keep it).
Delete a Folder
DELETE /api/v1/visual-dna/folders/:folderIdThe DNAs inside are not deleted — they move back to root. Response includes items_moved_to_root.
Move a DNA Into / Out of a Folder
PUT /api/v1/visual-dna/:id/folderBody: { "folder_id": "65f1…" } to file it, or { "folder_id": null } to move it back to root. Global presets return 403 ("import it first"); organization DNAs cannot be placed in personal folders.
MCP Tools
The matching @kolbo/mcp tools: list_visual_dna_folders, create_visual_dna_folder, update_visual_dna_folder, delete_visual_dna_folder, move_visual_dna_to_folder. Typical flow when building a large cast:
1. create_visual_dna_folder { name: "Film X Cast" }
2. create_visual_dna (per character)
3. move_visual_dna_to_folder { visual_dna_id, folder_id } # file each as you goUsing Visual DNA in Generations
Pass visual_dna_ids when generating images or videos to maintain character/product consistency:
Image Generation
curl -X POST https://api.kolbo.ai/api/v1/generate/image \
-H "X-API-Key: kolbo_live_..." \
-H "Content-Type: application/json" \
-d '{
"prompt": "Emma standing in a coffee shop",
"visual_dna_ids": ["6601a1b2c3d4e5f6a7b8c9d0"],
"aspect_ratio": "1:1"
}'Video Generation
curl -X POST https://api.kolbo.ai/api/v1/generate/video \
-H "X-API-Key: kolbo_live_..." \
-H "Content-Type: application/json" \
-d '{
"prompt": "Emma walking through a park",
"visual_dna_ids": ["6601a1b2c3d4e5f6a7b8c9d0"],
"duration": 5
}'You can pass up to 3 Visual DNA IDs per generation to combine multiple identities.
JavaScript Example
const fs = require("fs");
const FormData = require("form-data");
const API_KEY = "kolbo_live_YOUR_API_KEY";
const BASE = "https://api.kolbo.ai/api";
async function main() {
// 1. Create a Visual DNA from reference images
const form = new FormData();
form.append("name", "Brand Mascot");
form.append("dna_type", "character");
form.append("images", fs.createReadStream("mascot1.jpg"));
form.append("images", fs.createReadStream("mascot2.jpg"));
const createRes = await fetch(`${BASE}/v1/visual-dna`, {
method: "POST",
headers: { "X-API-Key": API_KEY, ...form.getHeaders() },
body: form
});
const { visual_dna } = await createRes.json();
console.log("Created Visual DNA:", visual_dna.id);
// 2. Generate an image using the Visual DNA
const genRes = await fetch(`${BASE}/v1/generate/image`, {
method: "POST",
headers: {
"X-API-Key": API_KEY,
"Content-Type": "application/json"
},
body: JSON.stringify({
prompt: "Brand mascot presenting a new product",
visual_dna_ids: [visual_dna.id]
})
});
const { poll_url } = await genRes.json();
// 3. Poll until the generation completes
let result;
do {
await new Promise((r) => setTimeout(r, 3000));
const status = await fetch(`${BASE}${poll_url}`, {
headers: { "X-API-Key": API_KEY }
});
result = await status.json();
} while (result.state === "processing");
console.log("Image URLs:", result.result.urls);
}
main();Python Example
import time
import requests
API_KEY = "kolbo_live_YOUR_API_KEY"
BASE = "https://api.kolbo.ai/api"
HEADERS = {"X-API-Key": API_KEY}
# 1. Create a Visual DNA from reference images
files = [
("images", ("mascot1.jpg", open("mascot1.jpg", "rb"), "image/jpeg")),
("images", ("mascot2.jpg", open("mascot2.jpg", "rb"), "image/jpeg")),
]
data = {"name": "Brand Mascot", "dna_type": "character"}
create_res = requests.post(f"{BASE}/v1/visual-dna", headers=HEADERS, data=data, files=files)
visual_dna = create_res.json()["visual_dna"]
print("Created Visual DNA:", visual_dna["id"])
# 2. Generate an image using the Visual DNA
gen_res = requests.post(
f"{BASE}/v1/generate/image",
headers={**HEADERS, "Content-Type": "application/json"},
json={
"prompt": "Brand mascot presenting a new product",
"visual_dna_ids": [visual_dna["id"]],
},
)
poll_url = gen_res.json()["poll_url"]
# 3. Poll until the generation completes
while True:
time.sleep(3)
status = requests.get(f"{BASE}{poll_url}", headers=HEADERS).json()
if status["state"] != "processing":
break
print("Image URLs:", status["result"]["urls"])Tips
- Upload 2-4 diverse reference images for best results (different angles, lighting)
- Character DNAs work best with clear face shots
- Product DNAs work best with multiple angles of the same product
- Visual DNA IDs work with both image and video generation endpoints
- Global Visual DNAs (provided by Kolbo) appear in your list but cannot be deleted