Kolbo.AIKolbo.AI Docs
Developer API

Color Palettes

Color DNA — save a palette and strict-grade every graded generation on your account to those colors.

A Color DNA palette is a named set of 1-10 colors. Activating a palette turns it into a strict color grade for your account: a plain-language directive ("dominant terracotta, secondary deep navy, accent warm gold…") is woven into the prompt of every graded generation you make, telling the model to grade lighting, atmosphere, set dressing and wardrobe to those colors while leaving the subject and action alone. See the table below for exactly which endpoints are graded.

Color DNA is sticky and account-wide. One palette is active per account at a time, and it grades every graded generation in every project — whatever project_id the generation is sent with — until you deactivate it or activate a different one. Activating a palette needs no project. A projectId on create/activate is optional and only files the palette under that project (see below); it never limits the grade to that project.

Where the grade is applied

EndpointGradedPer-request opt-out
POST /api/v1/generate/imageYesskip_color_palette: true
POST /api/v1/generate/image-editYesskip_color_palette: true
POST /api/v1/generate/video (text-to-video)Yes — unless auto-routed to image-to-video (see below)skip_color_palette: true
POST /api/v1/generate/creative-directorYes (all scenes)none — the endpoint does not accept skip_color_palette
POST /api/v1/generate/video/from-imageNoskip_color_palette is accepted but has no effect

skip_color_palette is a boolean, optional, default false (grade applied). It only affects the single request it is sent on. Only the JSON literal true opts out — the string "true" is mapped to false by the SDK layer.

Image-to-video is not graded. Grading is mode-gated to text-to-video — a source image already fixes the colors, so grading the prompt would promise a look the output never takes. POST /generate/video/from-image therefore ignores the active palette, and skip_color_palette there is a no-op. The same applies when you send a reference_images entry to POST /generate/video: the SDK delegates that request to the model's image-to-video sibling, so it is not graded either.

Every other generation endpoint (Elements, first/last frame, video-to-video, lipsync, 3D, speech, sound, music, chat) is ungraded and does not accept skip_color_palette.

The directive is composed from each color's role and name in words only — hex codes are deliberately never sent to the model, because image models render literal hex strings and color strips as visible artifacts. A color saved without a name gets the nearest name from a built-in color table.

Endpoints

GET    /api/v1/color-palettes
POST   /api/v1/color-palettes
POST   /api/v1/color-palettes/analyze
PUT    /api/v1/color-palettes/:id
DELETE /api/v1/color-palettes/:id
POST   /api/v1/color-palettes/:id/activate
POST   /api/v1/color-palettes/deactivate

Where a project id is accepted, both projectId and project_id work (if you send both, projectId wins). List (query string), create and activate (body) read it; deactivate accepts and ignores it. Update, delete and analyze have no project parameter — and because the create/update bodies are validated strictly, sending projectId, project_id or any other unlisted field to PUT /color-palettes/:id is a 400 Validation error.

Error envelope. Successful responses use the normal SDK shape ({"success": true, …}), and so do errors raised inside the handler ({"success": false, "error": "…"}). But the create/update body validator and the shared rate limiter run before the handler, so their rejections come back in the underlying app shape instead — {"status": false, "message": "Validation error", "details": [...]} for a bad body, and {"status": false, "error": "…", "message": "…", "limit": 120, "window_seconds": 60, "retryAfter": …} for the 120/min bucket. Branch on the HTTP status code, not on the presence of a success field, when handling errors from these seven routes.

List Palettes

Returns your personal palettes plus the palettes shared to your active organization, newest first, and — separately and unpaginated — Kolbo's built-in system presets. is_active marks the palette that is currently your account's Color DNA, wherever it appears.

When a project id is supplied and you can access the project, the list also includes the palette that project has filed as its own (even if a teammate owns it), and — if you are the owner or an edit/full member — every palette created in that project by any member.

Endpoint

GET /api/v1/color-palettes

Query Parameters

ParameterTypeRequiredConstraint
projectId / project_idstringNoProject id. Adds that project's palettes to the list as described above. It does not affect is_active, which is account-wide. An invalid or inaccessible id is ignored, not an error.
pageintegerNoDefault 1. Clamped to a minimum of 1.
limitintegerNoDefault 50. Clamped to 1-100; a larger value is silently capped, not rejected.

Example

curl "https://api.kolbo.ai/api/v1/color-palettes?projectId=65f1c8a2e4b0a3c1d9f5e789" \
  -H "X-API-Key: kolbo_live_..."

Response

{
  "success": true,
  "color_palettes": [
    {
      "id": "66a2b3c4d5e6f7a8b9c0d1e2",
      "name": "Terracotta & Deep Navy",
      "colors": [
        { "hex": "#E2725B", "name": "terracotta", "role": "dominant" },
        { "hex": "#0F1E3D", "name": "deep navy", "role": "secondary" },
        { "hex": "#E8C170", "name": "warm gold", "role": "accent" }
      ],
      "source_image_urls": ["https://cdn.kolbo.ai/uploads/ref1.jpg"],
      "is_active": true,
      "content_scope": "personal",
      "created_at": "2026-06-02T10:11:12.000Z",
      "updated_at": "2026-06-02T10:11:12.000Z"
    }
  ],
  "presets": [
    {
      "id": "66a2b3c4d5e6f7a8b9c0d0aa",
      "name": "Example Preset",
      "colors": [{ "hex": "#E8C170", "name": "warm gold", "role": "dominant" }],
      "source_image_urls": [],
      "is_active": false,
      "content_scope": "system",
      "created_at": "2026-05-01T00:00:00.000Z",
      "updated_at": "2026-05-01T00:00:00.000Z"
    }
  ],
  "pagination": { "page": 1, "limit": 50, "total": 1, "pages": 1 }
}

pagination covers color_palettes only; presets is always returned in full.

content_scope is "personal", "organization" or (in presets) "system". A palette you create is "personal" unless you create it with shareWithOrganization: true. Update and delete match on ownership, so they work on palettes you own (personal or shared to your organization) and return 404 for everything else — teammates' palettes, organization palettes published by an org admin, and system presets. Activate is broader: you can activate system presets and your active organization's palettes directly.

Analyze Images

Extracts a palette from reference images with deterministic pixel math (median-cut quantization) — no model call, no credits, and nothing is saved. Feed the returned colors straight into the create endpoint.

Endpoint

POST /api/v1/color-palettes/analyze

Request Body

ParameterTypeRequiredConstraint
image_urlsstring[]Yes1-5 publicly reachable image URLs. Private/internal addresses are rejected, redirects are not followed, and each image is capped at 20 MB.

Images that cannot be downloaded or decoded are skipped; if none of them can be used the request returns 400 with "Failed to download any images". The response contains up to 6 colors, ordered by pixel population, with role assigned as dominant (first), secondary (second), then accent. Near-duplicate colors are merged, so you can get back fewer than 6. Each color's name is the nearest entry in a built-in color-name table, and the palette name is built from the first two color names.

Unlike create/update, this body is not strictly validated — any field other than image_urls is silently discarded. If image_urls is missing or out of range the error message names the internal field: "imageUrls must be an array of 1-5 URLs"; a non-string entry returns "Each imageUrl must be a string". Send image_urls.

Example

curl -X POST https://api.kolbo.ai/api/v1/color-palettes/analyze \
  -H "X-API-Key: kolbo_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "image_urls": [
      "https://cdn.kolbo.ai/uploads/moodboard-1.jpg",
      "https://cdn.kolbo.ai/uploads/moodboard-2.jpg"
    ]
  }'

Response

{
  "success": true,
  "name": "Terracotta & Deep Navy",
  "colors": [
    { "hex": "#E2725B", "name": "terracotta", "role": "dominant" },
    { "hex": "#0F1E3D", "name": "deep navy", "role": "secondary" },
    { "hex": "#E8C170", "name": "warm gold", "role": "accent" }
  ]
}

Create Palette

Endpoint

POST /api/v1/color-palettes

Request Body

ParameterTypeRequiredConstraint
namestringYes1-100 characters after trimming.
colorsobject[]Yes1-10 entries. See the color object below.
source_image_urlsstring[]NoMax 5 entries, each a valid URI. Stored as provenance only. A 6th entry is a 400.
is_activebooleanNoDefault true: the new palette immediately becomes your account's Color DNA, replacing the previously active one. Send false to save it without activating — only the JSON literal false skips activation; the string "false" passes validation but still activates.
projectId / project_idstringNoProject to file the palette under. Applied only when you are the project owner or an edit/full member: the palette is recorded as created in that project (so the project's edit/full members see it when they list with that project id) and, when it is also activated, becomes the project's own palette. An invalid, inaccessible or read-only id is silently ignored — no error. It never limits the grade to that project.
shareWithOrganizationbooleanNoDefault false. true publishes the palette to your active organization (content_scope: "organization") so its members see it in their list. Ignored when you have no active organization.

Color object:

FieldTypeRequiredConstraint
hexstringYes#RRGGBB, exactly 6 hex digits.
namestringNoUp to 60 characters after trimming; the empty string is accepted. Used verbatim in the prompt directive; when omitted or empty, the nearest built-in color name is used instead.
rolestringNodominant | secondary | accent | background. Stored default is accent, so responses always carry a role even when you omit it.

Creating a palette activates it by default — from then on every graded generation on your account is graded with it. Send "is_active": false when you only want to store a palette. A successful create returns HTTP 201.

Example

curl -X POST https://api.kolbo.ai/api/v1/color-palettes \
  -H "X-API-Key: kolbo_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Terracotta & Deep Navy",
    "colors": [
      { "hex": "#E2725B", "name": "terracotta", "role": "dominant" },
      { "hex": "#0F1E3D", "name": "deep navy", "role": "secondary" },
      { "hex": "#E8C170", "name": "warm gold", "role": "accent" }
    ]
  }'

Response

{
  "success": true,
  "color_palette": {
    "id": "66a2b3c4d5e6f7a8b9c0d1e2",
    "name": "Terracotta & Deep Navy",
    "colors": [
      { "hex": "#E2725B", "name": "terracotta", "role": "dominant" },
      { "hex": "#0F1E3D", "name": "deep navy", "role": "secondary" },
      { "hex": "#E8C170", "name": "warm gold", "role": "accent" }
    ],
    "source_image_urls": [],
    "is_active": true,
    "content_scope": "personal",
    "created_at": "2026-06-02T10:11:12.000Z",
    "updated_at": "2026-06-02T10:11:12.000Z"
  }
}

Update Palette

Renames a palette and/or replaces its colors. Only the owner of the palette can update it — anyone else gets 404. Activation is not affected.

Endpoint

PUT /api/v1/color-palettes/:id

Request Body

ParameterTypeRequiredConstraint
namestringNo1-100 characters after trimming.
colorsobject[]No1-10 entries, same object shape as create. Full replacement — omit to keep the current colors.
source_image_urlsstring[]NoMax 5 entries, each a valid URI. Replaces the stored list.

Example

curl -X PUT https://api.kolbo.ai/api/v1/color-palettes/66a2b3c4d5e6f7a8b9c0d1e2 \
  -H "X-API-Key: kolbo_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "name": "Terracotta & Navy v2" }'

Response

{
  "success": true,
  "color_palette": {
    "id": "66a2b3c4d5e6f7a8b9c0d1e2",
    "name": "Terracotta & Navy v2",
    "colors": [{ "hex": "#E2725B", "name": "terracotta", "role": "dominant" }],
    "source_image_urls": [],
    "is_active": true,
    "content_scope": "personal",
    "created_at": "2026-06-02T10:11:12.000Z",
    "updated_at": "2026-06-02T12:30:00.000Z"
  }
}

is_active here is the palette's stored flag: true when this palette is your account's active Color DNA. Updating the active palette changes the grade in place (subject to the cache described under Activate) — no re-activation needed.

Delete Palette

Owner only (404 otherwise). If this palette was your account's active Color DNA, Color DNA is turned off and your generations go back to ungraded. Any project that had filed it as its own palette has that reference cleared.

Endpoint

DELETE /api/v1/color-palettes/:id

Example

curl -X DELETE https://api.kolbo.ai/api/v1/color-palettes/66a2b3c4d5e6f7a8b9c0d1e2 \
  -H "X-API-Key: kolbo_live_..."

Response

{ "success": true, "id": "66a2b3c4d5e6f7a8b9c0d1e2" }

Activate Palette

Makes this palette your account's Color DNA, replacing whichever palette was active. The body is optional — an empty body is valid.

Endpoint

POST /api/v1/color-palettes/:id/activate

Request Body

ParameterTypeRequiredConstraint
projectId / project_idstringNoWhen you are the project owner or an edit/full member, the palette also becomes that project's own palette, and you may activate a palette owned by another member of that project. An invalid, inaccessible or read-only id is silently ignored.

You can activate a palette you own, any system preset (presets in the list response), any palette shared to your active organization, or — with a writable projectId — a palette owned by a member of that project. Anything else returns 404 "Color palette not found or access denied".

Example

curl -X POST https://api.kolbo.ai/api/v1/color-palettes/66a2b3c4d5e6f7a8b9c0d1e2/activate \
  -H "X-API-Key: kolbo_live_..."

Response

{
  "success": true,
  "color_palette": {
    "id": "66a2b3c4d5e6f7a8b9c0d1e2",
    "name": "Terracotta & Deep Navy",
    "colors": [{ "hex": "#E2725B", "name": "terracotta", "role": "dominant" }],
    "source_image_urls": [],
    "is_active": true,
    "content_scope": "personal",
    "created_at": "2026-06-02T10:11:12.000Z",
    "updated_at": "2026-06-02T10:11:12.000Z"
  }
}

The active palette is cached in-process for 60 seconds per user on each API worker. The worker that handles a create, update, delete, activate or deactivate drops its cache immediately, but other workers can keep grading with the previous palette for up to a minute.

Deactivate Palette

Turns Color DNA off for your account. Your generations stop being color-graded in every project, and the project-palette reference is cleared on every project you own. The palette itself is untouched and stays in your library.

Endpoint

POST /api/v1/color-palettes/deactivate

Request Body

None. A projectId / project_id is accepted for backward compatibility and ignored.

Example

curl -X POST https://api.kolbo.ai/api/v1/color-palettes/deactivate \
  -H "X-API-Key: kolbo_live_..."

Response

{ "success": true }

Examples

Full flow: references → palette → graded generation

API_KEY="kolbo_live_..."
BASE="https://api.kolbo.ai/api/v1"

# 1. Extract colors from reference images (free, saves nothing)
curl -s -X POST "$BASE/color-palettes/analyze" \
  -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
  -d '{ "image_urls": ["https://cdn.kolbo.ai/uploads/ref1.jpg"] }'

# 2. Save the palette - it becomes your account's active Color DNA in the same call
curl -s -X POST "$BASE/color-palettes" \
  -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
  -d '{
    "name": "Terracotta & Deep Navy",
    "colors": [
      { "hex": "#E2725B", "name": "terracotta", "role": "dominant" },
      { "hex": "#0F1E3D", "name": "deep navy", "role": "secondary" }
    ]
  }'

# 3. Every graded generation is now graded, in any project
curl -s -X POST "$BASE/generate/image" \
  -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
  -d '{ "prompt": "A coffee cup on a wooden table" }'

# 4. ...unless you opt this one call out
curl -s -X POST "$BASE/generate/image" \
  -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
  -d '{ "prompt": "Plain product cutout", "skip_color_palette": true }'

Turn Color DNA off

curl -X POST https://api.kolbo.ai/api/v1/color-palettes/deactivate \
  -H "X-API-Key: kolbo_live_..."

Credits and Rate Limits

  • All Color Palette endpoints are free — no credits are charged, including analyze.
  • Shared bucket: 120 requests per minute per user across the SDK's media/asset endpoints. Requests that fail (4xx/5xx) are not counted against it.
  • POST /color-palettes/analyze has an additional dedicated limit of 10 requests per minute per user; exceeding it returns 429 with code RATE_LIMITED.