Kolbo.AIKolbo.AI Docs
Developer API

Stock Library

Search Kolbo's unified multi-source stock media library (photos, videos, illustrations, vectors, 3D models, music, sound effects) and import assets into your media library.

The Stock Library is Kolbo's unified, multi-source catalog of ready-made media — photos, videos, illustrations, vectors, 3D models, music, and sound effects — aggregated behind one search. Use it to find b-roll, references, or project assets.

Library vs generation. These endpoints find existing assets and are free (no credits). To create new content, use image generation or video generation.

License. Your use of any asset is governed by the Asset Library License & Terms of Use. In short: Kolbo's own AI-generated music and sound effects are licensed for commercial use; third-party licensed assets (photos, videos, vectors, 3D) may be used only as original footage — not fed into AI generation/editing tools, and not used for AI training.

Sources today: Kolbo AI (kolbo-ai — our own AI-generated sound effects, music, and images), Pexels (photos, videos), Unsplash (photos), Pixabay (photos, illustrations, vectors, videos), Coverr (videos, music), Sketchfab (3D models), and Freesound (sound effects). Every route requires your X-API-Key.

The licensed production-music source (music) is not reachable through these endpoints. It is filtered out of /stock/sources and /stock/categories, and source=music returns 404 STOCK_NOT_FOUND on search, asset, and import. Use the Music Library endpoints for that catalog.

A source, or one of its media types, can be gated. Gated content is invisible rather than forbidden: the source is dropped from /stock/sources, /stock/categories returns an empty list, search returns an empty result set, and /stock/asset + /stock/import return 404 — never 403. If a source you expect is missing, that is why. Always read /stock/sources for the live list rather than hardcoding it.

Attribution. Every asset carries author, providerUrl, license, and a ready-to-render attribution string. When you display results you must credit the provider and the creator per their license.

Rate limits

RoutesLimit
sources, categories, collections, search, asset60 requests / minute / user
analyze-script20 requests / minute / user
import20 requests / minute / user

Sources

List the enabled sources and which media types + filters each supports. Takes no parameters.

Endpoint

GET /api/v1/stock/sources
{
  "success": true,
  "mediaTypes": ["image", "illustration", "vector", "video", "3d", "music", "sfx"],
  "sources": [
    {
      "key": "kolbo-ai", "label": "Kolbo AI", "label_he": null,
      "description": null, "description_he": null, "enabled": true,
      "mediaTypes": ["sfx", "music", "image"],
      "filters": {
        "sfx": ["query","category","subcategory","collectionId","packId","lengthBucket","order"],
        "music": ["query","genre","mood","theme","instrument","vocals","collectionId","order","bpmMin","bpmMax","durationMin","durationMax"],
        "image": ["query","collectionId","packId","orientation","subject","setting","timeOfDay","copySpace","peopleCount","order"]
      },
      "attribution": null, "order_index": 0
    },
    { "key": "pexels", "label": "Pexels", "mediaTypes": ["image", "video"], "filters": { "image": ["orientation","size","color","query"], "video": ["orientation","size","query"] }, "attribution": { "label": "Photos & videos provided by Pexels", "url": "https://www.pexels.com" } },
    { "key": "unsplash", "label": "Unsplash", "mediaTypes": ["image"], "filters": { "image": ["orientation","color","query"] } },
    { "key": "pixabay", "label": "Pixabay", "mediaTypes": ["image","illustration","vector","video"] },
    { "key": "coverr", "label": "Coverr", "mediaTypes": ["video","music"], "filters": { "video": ["category","orientation","order","query"], "music": ["order","query"] } },
    { "key": "sketchfab", "label": "Sketchfab", "mediaTypes": ["3d"], "filters": { "3d": ["query","category"] } },
    { "key": "freesound", "label": "Freesound", "mediaTypes": ["sfx"], "filters": { "sfx": ["query","order"] } }
  ]
}

mediaTypes at the top level is the full set the library can expose; each source's own mediaTypes is what that source supports and what you are allowed to see. Only sources with enabled: true are returned, ordered by order_index.

A source's filters map lists what the provider supports, not what this API forwards. /stock/search currently forwards only the parameters in its own table below — theme, vocals, instrument, bpmMin / bpmMax, durationMin / durationMax, subject, setting, timeOfDay, copySpace, peopleCount, and Pexels size are advertised here but are not accepted as query parameters yet.

Categories

Dynamic category/topic chips per source. Pass the returned providerParam as the category filter on Search.

Endpoint

GET /api/v1/stock/categories?source=pixabay&mediaType=image

Query Parameters

ParameterTypeRequiredConstraints
sourcestringNoRestrict to one source key. Max 32 chars. Omit for every source. A gated or blocked source returns { categories: [], count: 0 }.
mediaTypestringNoRestrict to one media type. Max 24 chars. Rows tagged mediaType: "all" match every type and are always included.
{
  "success": true,
  "count": 20,
  "categories": [
    {
      "source": "pixabay", "mediaType": "all", "key": "nature", "label": "Nature",
      "label_he": null, "providerParam": "nature", "paramType": "category",
      "thumbnailUrl": null, "order_index": 3, "group": null
    }
  ]
}

Rows come back sorted by source then order_index. paramType tells you which search parameter the row's providerParam belongs to (category or subcategory).

For Kolbo SFX (source=kolbo-ai&mediaType=sfx), categories are 2-level: top-level groups (group: null) and their sub-filters (each carries a group pointing to its parent, and paramType: "subcategory"). Pass a group's providerParam as category and a sub-filter's as subcategory.

Collections

Kolbo's own SFX library is organized into category collections (one per taxonomy group, kind: "category") and curated themed packs (kind: "pack" — e.g. Horror, Car Chase, In The Kitchen, Outer Space, Movie Trailer). Each has a cover image.

Endpoint

GET /api/v1/stock/collections?mediaType=sfx&kind=pack

Query Parameters

ParameterTypeRequiredConstraints
mediaTypestringNoDefault sfx. Only sfx returns anything — any other value returns an empty list.
kindstringNocategory or pack. Any other value is ignored and both kinds are returned.

This route only ever serves Kolbo's own (kolbo-ai) SFX collections — there is no source parameter. If kolbo-ai SFX is gated for your account you get { "collections": [], "count": 0 }.

{
  "success": true,
  "count": 12,
  "collections": [
    {
      "id": "6a3c...", "slug": "sfx-col-horror", "title": "Horror", "title_he": null,
      "description": null, "coverUrl": "https://media.kolbo.ai/...",
      "kind": "pack", "categoryKey": null, "mediaType": "sfx", "order_index": 2
    }
  ]
}

Use a collection/pack id as packId or collectionId in Search to browse just that set.

Unified search. With source=all (default) results from every provider that supports the media type are merged into one interleaved feed.

Endpoint

GET /api/v1/stock/search

Query Parameters

ParameterTypeRequiredConstraints
querystringNoKeyword search. For Kolbo AI sound effects, music and images a natural-language vibe works (semantic search) — see below. Omit to browse. Truncated to 200 chars (no error). A query written in a non-Latin script (Hebrew, Arabic, Cyrillic, Greek, CJK, Korean, Thai, Devanagari) is auto-translated to English first; Latin-script queries — including French, Spanish, German — are passed through verbatim.
sourcestringNoall (default), or a key from Sources: kolbo-ai, pexels, unsplash, pixabay, coverr, sketchfab, freesound. Truncated to 32 chars. music / synci404 STOCK_NOT_FOUND. An unknown key → 502 STOCK_ERROR.
mediaTypestringNoimage (default), illustration, vector, video, 3d, music, sfx. Anything else silently falls back to image. On a single-source search, a type the source does not support → 502 STOCK_ERROR.
categorystringNoA providerParam from Categories. For Kolbo SFX these are the 77 Soundly-style groups (e.g. ambience, animals, vehicles, weapons, water, designed) and the match is exact and case-sensitive — send providerParam verbatim (they are lowercase slugs). Max 256 chars.
subcategorystringNoKolbo SFX only. Sub-filter providerParam within a group (e.g. sword, splash, concrete, riser) — 623 sub-filters across the 77 groups. Same exact, case-sensitive match. Max 256 chars.
packIdstringNoKolbo AI only. Themed-pack id from Collections. Honoured for SFX on every path, and for AI images only on the keyword/browse path — an image search with a query runs semantic vibe search, which ignores packId. Kolbo AI music has collections but no packs. Must be a 24-char hex ObjectId: on SFX an invalid value is silently dropped, on images it makes the Kolbo source fail (502 STOCK_ERROR on a single-source search, or partial: true under source=all). Max 256 chars.
collectionIdstringNoKolbo AI only. Collection id from Collections. Honoured for music and images on every path, and for SFX only on the keyword/browse path — an SFX search with a query runs semantic vibe search, which ignores collectionId. Same 24-char hex ObjectId rule and same images-only failure mode as packId. Max 256 chars.
genrestringNoKolbo AI music only. Exact match against the track's genre field (clipped to 64 chars server-side); it is not a substring or fuzzy match. Max 256 chars.
moodstringNoKolbo AI music only. Exact match against one entry of the track's moods array (clipped to 64 chars server-side). Max 256 chars.
lengthBucketstringNoKolbo SFX only. A bucket from the SFX taxonomy: oneshot, short, medium, long, loop, loopmax. Not validated — an unrecognized value simply matches nothing. Every SFX result echoes its own bucket as meta.lengthBucket, so read that rather than guessing. Max 256 chars.
orientationstringNoUnified vocabulary landscape / portrait / square. Pexels takes all three natively; Pixabay maps landscape→horizontal and portrait→vertical (it also accepts those two raw values, and has no square); Unsplash maps square→squarish and also accepts horizontal / vertical; Coverr post-filters landscape / portrait best-effort; Kolbo AI images match the stored enum exactly (landscape | portrait | square). Unrecognized values are dropped.
colorstringNoColor filter. Pixabay: one or more comma-separated names from its own palette (unknown names are dropped, images/illustrations/vectors only). Pexels: a named or hex color (images only). Unsplash: a single named color, and only on an explicit query — it is ignored on a no-query browse.
orderstringNoSort order. popular / latest on Pixabay and Freesound; popular / latest / trending on Coverr; popular on Kolbo AI SFX and images (anything else = newest first). For Kolbo AI music: duration_asc, duration_desc, bpm_asc, bpm_desc, title, popular, newest — passing one of these disables semantic vibe ranking. On a mediaType=music multi-source feed, one of those seven values also re-sorts the whole merged page. Unrecognized values are dropped.
cursorstringNoOpaque pagination cursor, returned as nextCursor. Used by the cursor-paginated Sketchfab source: Sketchfab has no page numbers, so page > 1 without a cursor returns an empty Sketchfab result set. It also caps its own page at 24 regardless of perPage. Max 256 chars.
pagenumberNo1-based page. Default 1, floored at 1. kolbo-ai hard-caps pagination depth at page 50.
perPagenumberNoResults per page. Default 24, clamped to 1–80.

Every filter value above is truncated to 256 characters; only string values are forwarded.

Browse is family-filtered, search is not. When query is empty the results pass through a family-friendly content filter (the unprompted browse feed stays clean). An explicit query returns exactly what you asked for, unfiltered.

curl "https://api.kolbo.ai/api/v1/stock/search?query=ocean%20waves&source=all&mediaType=video&perPage=4" \
  -H "X-API-Key: kolbo_live_..."

Semantic "vibe" search (Kolbo AI)

The kolbo-ai source is Kolbo's own AI-generated library: sound effects (mediaType=sfx), music (mediaType=music), and images (mediaType=image). For all three, a query is matched semantically — describe the feeling or use, not just keywords:

# Sound effects by vibe
curl "https://api.kolbo.ai/api/v1/stock/search?source=kolbo-ai&mediaType=sfx&query=tense%20ominous%20build-up%20for%20a%20horror%20reveal" \
  -H "X-API-Key: kolbo_live_..."

# Music by vibe
curl "https://api.kolbo.ai/api/v1/stock/search?source=kolbo-ai&mediaType=music&query=uplifting%20hopeful%20corporate%20background" \
  -H "X-API-Key: kolbo_live_..."

# Images by vibe
curl "https://api.kolbo.ai/api/v1/stock/search?source=kolbo-ai&mediaType=image&query=quiet%20minimal%20workspace%20with%20room%20for%20a%20headline" \
  -H "X-API-Key: kolbo_live_..."

Kolbo AI audio assets ship downloadVariants with per-file labels: SFX use mp3 and wav, music uses 320 (MP3), wav, and midi; images ship a single original. Each label appears only when that file exists for the asset, so read the labels rather than assuming — and pass one back as variant on Import. (External visual providers still want concrete keywords, not a vibe.)

Semantic ranking is the path taken only when there is a query. Because the vibe and keyword paths apply slightly different filters, packId (images) and collectionId (SFX) are honoured on the keyword/browse path but dropped once a query makes the search semantic — see their rows above. An explicit order on Kolbo AI music also turns semantic ranking off, since a deterministic sort and a relevance ranking cannot both win.

Response

{
  "success": true,
  "assets": [
    {
      "source": "pexels",
      "sourceId": "12685044",
      "mediaType": "video",
      "title": "",
      "thumbnailUrl": "https://images.pexels.com/videos/.../poster.jpeg",
      "previewUrl": "https://images.pexels.com/videos/.../poster.jpeg",
      "width": 3840, "height": 2160, "durationSeconds": 20,
      "downloadVariants": [
        { "label": "uhd-2160p", "url": "https://...", "width": 3840, "height": 2160, "ext": "mp4", "fileSizeBytes": 12345678 }
      ],
      "author": { "name": "CityXcape", "url": "https://www.pexels.com/@cityxcape" },
      "providerUrl": "https://www.pexels.com/video/...",
      "license": { "name": "Pexels License", "attributionRequired": false, "url": "https://www.pexels.com/license/" },
      "tags": [],
      "attribution": "Video by CityXcape on Pexels"
    }
  ],
  "page": 1, "perPage": 4, "total": 8500, "hasMore": true, "partial": false, "nextCursor": null,
  "sources": [ { "source": "pexels", "total": 8000, "hasMore": true, "nextCursor": null }, { "source": "pixabay", "total": 500, "hasMore": true, "nextCursor": null } ]
}

Paginate by incrementing page (the same page is requested from each provider, so the interleaved feed stays consistent).

total is the sum across providers; a per-source sources[].total can be null when that provider does not report one. partial: true and a sources[].error: true entry mean one provider failed and the feed is incomplete — distinct from a genuinely empty result, and worth retrying. partial is only returned on the source=all fan-out; a single-source search omits it. nextCursor appears when a cursor-paginated provider (Sketchfab) participated; pass it back as cursor.

Asset

Resolve a single normalized asset with all download variants.

Endpoint

GET /api/v1/stock/asset/:source/:id
ParameterTypeRequiredConstraints
:sourcestringYeskolbo-ai, pexels, unsplash, pixabay, coverr, sketchfab, or freesound. music / synci404 STOCK_NOT_FOUND; an unknown key → 502 STOCK_ERROR.
:idstringYesThe provider asset id (sourceId).
mediaTypestring (query)NoMedia type hint (e.g. video) for sources that reuse ids across types. Truncated to 24 chars.
curl "https://api.kolbo.ai/api/v1/stock/asset/pexels/12685044?mediaType=video" \
  -H "X-API-Key: kolbo_live_..."

Returns { "success": true, "asset": { ... } } with the same asset shape as Search. An unresolvable id returns 404 STOCK_NOT_FOUND.

Analyze Script (auto b-roll)

AI helper that turns a video/voiceover script into concrete stock b-roll search terms you can feed into Search.

Endpoint

POST /api/v1/stock/analyze-script

Request Body

ParameterTypeRequiredConstraints
scriptstringYesThe script / scene description. Trimmed; empty → 400. Clipped server-side to the first 8000 characters.
curl -X POST https://api.kolbo.ai/api/v1/stock/analyze-script \
  -H "X-API-Key: kolbo_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "script": "Aerial shots of a coastal city at sunrise, then a team collaborating in a modern office." }'
{
  "success": true,
  "queries": ["coastal city sunrise", "aerial drone ocean", "team collaborating office", "modern office interior"],
  "mediaType": "video",
  "keywords": ["coast", "sunrise", "drone", "office", "teamwork"]
}

queries holds up to 6 concrete visual phrases (the model is asked for 3–6; only "at least one" is enforced, each clipped to 60 chars), mediaType is "video" or "image" (anything else becomes "image"), and keywords holds up to 6 tags. If no query at all can be derived you get 422 with code STOCK_SCRIPT_EMPTY.

Import

Copy a stock asset into your media library — downloaded to Kolbo's CDN with a stable URL so it can be used in projects and generations. Free. The licensed music source is not importable here — use Import Track to Media Library for it.

Endpoint

POST /api/v1/stock/import

Request Body

ParameterTypeRequiredConstraints
sourcestringYeskolbo-ai, pexels, unsplash, pixabay, coverr, freesound, or sketchfab. music / synci404 STOCK_NOT_FOUND; an unknown key → 400 STOCK_UNKNOWN_SOURCE.
idstringYesThe provider asset id. sketchfab takes its own path: the id must be a 32-character hex uid (400 STOCK_INVALID_ID), the model must be downloadable (400 STOCK_NOT_DOWNLOADABLE) and available as GLB (400 STOCK_NOT_GLB), and variant / mediaType are ignored.
mediaTypestringNoMedia type hint (e.g. video, vector). Needed for sources that reuse ids across types.
variantstringNoWhich download variant label to import (from Asset). An unknown label falls back to the first variant; an asset with no variants → 400 STOCK_NO_DOWNLOAD.
project_idstringNoProject to file the item under. projectId is accepted as an alias.
curl -X POST https://api.kolbo.ai/api/v1/stock/import \
  -H "X-API-Key: kolbo_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "source": "pexels", "id": "12685044", "mediaType": "video" }'
{
  "success": true,
  "alreadyImported": false,
  "libraryItem": { "_id": "...", "mediaType": "video", "url": "https://media.kolbo.ai/...", "filename": "..." }
}

Re-importing the same (source, id) returns the existing item with alreadyImported: true — dedup is per user, and nothing is re-downloaded. The created item is sourceType: "stock" with metadata.stockSource, metadata.stockSourceId, metadata.variant, and the author/license/attribution copied onto it, so it stays separate from your own uploads in the Media Library.

Typical Flow

  1. From a scriptPOST /stock/analyze-script to get queries[] + mediaType.
  2. SearchGET /stock/search for each query (source=all). Show thumbnailUrl + attribution.
  3. ResolveGET /stock/asset/:source/:id for the full download variants.
  4. Use itPOST /stock/import to copy the asset into the media library (stable CDN URL), then reference it in a project or generation.

Notes

  • All Stock Library endpoints are free — they do not consume credits.
  • Always display the provider + creator credit (attribution) when you show results.
  • Pixabay vectors currently ship as a high-resolution raster (true SVG requires Pixabay full API access); meta.vectorRasterOnly flags these.

Errors

All errors return { "success": false, "error": "...", "code": "..." }.

CodeStatusMeaning
STOCK_NOT_FOUND404Asset does not exist, or the source / media type is gated or blocked for you. Also returned for source=music / source=synci on search, asset and import.
STOCK_UNKNOWN_SOURCE400No such source key — import only. On /stock/search and /stock/asset the same condition surfaces as 502 STOCK_ERROR.
STOCK_NO_DOWNLOAD400The asset has no downloadable file (import).
STOCK_INVALID_ID400Malformed provider id (3D imports require a 32-char hex uid).
STOCK_NOT_DOWNLOADABLE400The Sketchfab model is not available for download.
STOCK_NOT_GLB400The Sketchfab model has no GLB build.
STOCK_TOO_LARGE400The asset exceeds the per-media-type import size cap: 350 MB for video, 150 MB for music, 60 MB for everything else (image, illustration, vector, sfx). Pick a smaller variant and retry.
STOCK_UNTRUSTED_HOST400The resolved download URL is not on the provider's allow-list.
STOCK_SOURCE_UNAVAILABLE503The 3D source is not configured on this environment (Sketchfab import). On /stock/search the same condition — a single source that is registered but has no credentials configured — surfaces as 502 STOCK_ERROR instead.
STOCK_SCRIPT_EMPTY422analyze-script could not derive any b-roll query.
STOCK_SCRIPT_ERROR502analyze-script failed.
STOCK_ERROR502Any other failure, including an unknown source, a registered-but-unconfigured source, or an unsupported single-source mediaType on search / asset.