Cinematic Presets
Layer a deliberate photographic "Cinema mode" treatment onto image generations and edits, and discover the generation preset catalog.
Cinematic Presets ("Cinema mode") let you compose a deliberate photographic look for an image by picking presets across independent dimensions — camera body, lens, focal length, aperture, angle, shot type, color grade, and lighting. The selected fragments are woven into your prompt before enhancement, so the result reads like an intentional camera setup rather than a list of gear names.
Cinema mode is entirely optional. Apply it only when the user wants a specific cinematic look —
omit it for an ordinary generation. It is available on
image generation and
image editing via the cinematic field.
Dimensions
Two different lists matter here, and they are not identical:
Dimension keys the cinematic object accepts (fixed server-side allow-list — anything else is a 400):
| Dimension | What it controls |
|---|---|
camera | Camera body / format (e.g. ARRI Alexa, 16mm film, smartphone) |
lens | Lens character (e.g. anamorphic, vintage prime, macro) |
focal_length | Focal length / field of view (e.g. 24mm wide, 85mm portrait) |
aperture | Aperture / depth of field (e.g. f/1.4 shallow, f/8 deep) |
angle | Camera angle (e.g. low angle, birds-eye, eye level) |
shot_type | Shot type / framing (e.g. close-up, wide shot, full shot) |
color_palette | Color grade (e.g. teal & orange, technicolor, classic B&W) |
lighting | Lighting technique (e.g. rim light, golden hour, low-key) |
genre | Genre treatment. The key is still on the server allow-list, but whether any genre presets exist is seed-dependent — if the list endpoint returns no genre group in your environment, there is no id you can put here. |
tempo | Cut rhythm / pacing treatment. Also on the allow-list and also seed-dependent — only usable when the list endpoint returns a tempo group. |
Groups the list endpoint returns are whatever is seeded and active, so the response may also
contain groups such as looks (bundle recipes that expand to a map of other dimensions) and
moveset.
The list endpoint is a catalog, not an input schema. A group it returns is not automatically a
valid cinematic key — looks and moveset ids are rejected with a 400 if you put them in the
cinematic object. Only the ten keys in the table above are accepted. A looks entry is a recipe:
copy the ids from its bundle map into the matching cinematic keys instead.
The catalog is data-driven — always fetch the live set from the endpoint below rather than hardcoding ids.
List Cinematic Presets
Returns all active presets grouped by dimension. Each preset carries id, name, description,
thumbnail_url, and sort_order; some also carry preview_url (a motion preview on video-oriented
dimensions — thumbnail_url stays the poster), ui_hint (a short UI-only pacing hint for tempo
entries, never injected into the prompt), and, for
looks entries, a bundle map of dimension → preset id. Fields that are not set are omitted.
Groups come back in a fixed order — looks, camera, lens, focal_length, aperture, angle,
shot_type, lighting, color_palette, genre, tempo, moveset — with any other seeded group
appended after; within a group, presets are sorted by sort_order, then name. Groups with no active
presets are left out.
Endpoint
GET /api/v1/cinematic-presetsTakes no parameters.
Example
curl https://api.kolbo.ai/api/v1/cinematic-presets \
-H "X-API-Key: kolbo_live_..."Response
The SDK route wraps the grouped catalog in a dimensions object:
{
"success": true,
"dimensions": {
"camera": [
{
"id": "6a40...aa01",
"name": "ARRI Alexa 35",
"description": "shot on an ARRI Alexa 35 digital cinema camera, wide dynamic range...",
"thumbnail_url": "https://kolbo-general-media.fra1.cdn.digitaloceanspaces.com/cinema-deck/camera/ARRI_Alexa_35.webp",
"sort_order": 1
}
],
"lens": [],
"color_palette": [],
"lighting": []
}
}If the cinematic-presets catalog is not deployed in the environment you are calling, this route
returns { "success": true, "dimensions": {} } rather than an error. Treat an empty dimensions
map as "Cinema mode unavailable here", not as a failure. This SDK route serves a fresh JSON body on
every call — it does not set an ETag, so If-None-Match has no effect. (The catalog itself is
cached server-side, so repeated calls are cheap.)
The matching @kolbo/mcp tool is list_cinematic_presets. With no arguments it returns a compact
id + name index of every group; pass the optional dimension argument (e.g. "lighting") to get
full descriptions (and bundle for looks) for that one group. Both shapes include an
available_dimensions list of the group keys present in your environment.
Applying Cinema Mode
Pass a cinematic object on the generation request. Each key is a dimension; each value is a
preset id from the list endpoint. Include only the dimensions the user actually wants.
{
"prompt": "a lone traveler crossing a desert at dusk",
"cinematic": {
"camera": "6a40...aa01",
"color_palette": "6a40...cc07",
"lighting": "6a40...dd12"
}
}The "Auto" rule
- Any dimension you omit (or set to
null) is Auto. When at least one dimension is set, the prompt enhancer intelligently completes the unset dimensions in the spirit of the ones you chose (e.g. picking a smartphone camera steers toward a candid, deep-focus everyday look; picking a film camera steers toward a filmic treatment). - Omit the
cinematicobject entirely for a normal, non-cinematic generation — nothing is injected and the standard enhancement pipeline decides the look.
Model support
Cinema mode only applies when the selected model supports it. If none of the models on the request
support Cinema, the validated cinematic selection is dropped silently — the generation still
runs, with no cinematic treatment and no error. Pass a specific model known to support Cinema
(high-quality cinematic image models) rather than relying on automatic selection, and confirm with the
status response (below). Validation still runs first, so a malformed or wrong-dimension id is a 400
even on a model that would drop it.
Validation
- The value must be a real JSON object, never an array. One preset per dimension (the shape enforces it — a key holds a single id).
- Each value must be a valid ObjectId string,
null, or"".nulland""mean "Auto" for that dimension. Any other value (a number, an object, a malformed id) is a400. - Each
idmust resolve to an active preset in that exact dimension — an inactive preset, or alightingid in thecameraslot, returns a400naming the dimension and id. - Unknown dimension keys are rejected with a
400that names the allowed set. - A
cinematicobject whose every value isnull/""is treated as no selection at all — nothing is injected.
A validation failure comes back through the standard SDK error envelope with HTTP 400:
{
"success": false,
"error": "Invalid cinematic dimension key(s): looks. Allowed: camera, color_palette, lighting, genre, lens, focal_length, aperture, angle, shot_type, tempo",
"code": "GENERATION_ERROR"
}On the SDK routes, cinematic is forwarded only when it is an object that is not an array —
a JSON-encoded string is dropped silently before validation ever runs, so the request
succeeds with no cinematic treatment applied and no error. (The underlying validator would happily
parse a JSON string; the SDK layer just never hands it one.) Send it as a nested JSON object.
Applying cinematic also forces the prompt-enhancement pass on, even if you set
enhance_prompt: false — the selected descriptors are handed to the enhancer as a style directive
rather than concatenated onto your prompt.
Full Example
# 1. Discover presets
curl https://api.kolbo.ai/api/v1/cinematic-presets -H "X-API-Key: kolbo_live_..."
# 2. Generate with a cinematic look
curl https://api.kolbo.ai/api/v1/generate/image \
-H "X-API-Key: kolbo_live_..." \
-H "Content-Type: application/json" \
-d '{
"prompt": "a lone traveler crossing a desert at dusk",
"cinematic": {
"camera": "6a40...aa01",
"lens": "6a40...bb03",
"color_palette": "6a40...cc07",
"lighting": "6a40...dd12"
}
}'The same cinematic object works on POST /api/v1/generate/image-edit.
What the status response reports
When a generation actually applied Cinema mode, its
status response carries a cinematic_presets array — one
entry per applied dimension, in composition order (shot_type, angle, camera, lens,
focal_length, aperture, lighting, color_palette, genre, tempo):
{
"cinematic_presets": [
{ "dimension": "camera", "id": "6a40...aa01", "name": "ARRI Alexa 35", "thumbnail_url": "https://..." }
]
}The key is absent when nothing was applied — including when the selection was dropped because the model does not support Cinema — so check it to confirm the look was used.
Generation Presets (GET /v1/presets)
A separate, unrelated catalog: curated prompt-template presets you apply to a whole generation with
the preset_id field. Cinematic presets are photographic dimensions; generation presets are whole
creative directions.
Endpoint
GET /api/v1/presetsQuery Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
type | string | No | One of image, image_edit, video, music, text_to_video. Omit to return every catalog in one flat list. Any other value returns an empty presets array. |
The route reads no other query parameters — there is no server-side search, paging, or limit, so filter the list yourself. image and image_edit are separate catalogs with different ids.
text_to_video is an alias for the video catalog — the same entries come back, tagged type: "text_to_video".
Response
{
"success": true,
"presets": [
{
"id": "cinematic-portrait",
"name": "Cinematic Portrait",
"description": "…",
"thumbnail_url": "https://cdn.kolbo.ai/…",
"category": "portrait",
"type": "image"
}
],
"count": 1
}categoryis the grouping key forimage,image_edit,video, andtext_to_video; alwaysnullformusic.musicentries may also carryaudio_url(a preview) andprompt_text.- If one underlying catalog fails to load, the response still returns
success: truewith the presets gathered so far plus awarningstring.
The MCP tool list_presets passes type through verbatim. Its optional search argument is a client-side filter over each preset's name,
description, and category, applied after the full list comes back.
Example
curl "https://api.kolbo.ai/api/v1/presets?type=image" \
-H "X-API-Key: kolbo_live_..."Pass the returned id as preset_id on the matching generation endpoint. preset_id is read by
POST /v1/generate/image, /v1/generate/image-edit, /v1/generate/video,
/v1/generate/video/from-image, /v1/generate/music, and /v1/generate/elements. On the two image
routes it accepts either an image or an image_edit preset id (creation presets are tried first);
an unknown or inactive id is a 400. It is not read by first-last-frame, video-from-video, or lipsync.
Like a moodboard, a preset forces the prompt-enhancement pass on so its description is synthesized
with your prompt rather than concatenated. preset_id and cinematic can be combined on the image
routes.