Kolbo.AIKolbo.AI Docs
Developer API

Authentication

Create and manage API keys for the Kolbo Developer API.

All API requests require an API key passed via the X-API-Key header.

API Key Format

Keys follow the format kolbo_live_<60 hex characters> — the literal prefix kolbo_live_ plus 30 random bytes rendered as hex.

The kolbo_live_ prefix is mandatory. Any key that does not start with it is rejected as Invalid API key format before any lookup happens.

Creating a Key

Go to Developer Console and click Create Key.

Via API

The key-management endpoints live under /api/api-keys (not /api/v1). Creating, revealing and revoking a key require an interactive sign-in: the request must be authenticated with a JWT from your browser session (Authorization: Bearer ...), which is what the Developer Console sends.

EndpointJWTX-API-Key
POST /api/api-keys (create)YesNo — 403
GET /api/api-keys/{keyId}/revealYesNo — 403
DELETE /api/api-keys/{keyId} (revoke)YesNo — 403
GET /api/api-keys (list)YesYes
GET /api/api-keys/{keyId} (details)YesYes

An API key cannot mint, reveal or revoke API keys — not even one with write permission. Those three calls made with X-API-Key return 403 with { "status": false, "code": "INTERACTIVE_AUTH_REQUIRED", "message": "Sign in to manage API key secrets." }.

curl -X POST https://api.kolbo.ai/api/api-keys \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "My Integration", "permissions": ["read", "write"], "expiresInDays": 365}'

Request Body

ParameterTypeRequiredDescription
namestringYesLabel for the key. Must be a non-empty string; whitespace is trimmed. An empty or non-string value returns 400.
permissionsstring[]NoAny subset of read | write. Defaults to ["read", "write"]. A single string (e.g. "read") is accepted and wrapped into an array. Any other value returns 400 (Invalid permission: "<value>". Allowed: read, write) — admin keys cannot be self-created.
expiresInDaysnumberNoDefaults to 365. Parsed with parseInt, then clamped to 1–730. Out-of-range values are clamped rather than rejected (1000 → 730, -5 → 1); 0 and unparseable values fall back to 365.

Returns 201 on success:

{
  "status": true,
  "data": {
    "id": "key_id",
    "keyPrefix": "kolbo_live_a1b2c3d4e...",
    "name": "My Integration",
    "permissions": ["read", "write"],
    "createdAt": "2026-03-05T10:00:00Z",
    "expiresAt": "2027-03-05T10:00:00Z"
  },
  "fullKey": "kolbo_live_abc123def456...",
  "message": "API key created. You can view the full key again any time from this page."
}

The full key is not one-time. It is stored encrypted alongside the validation hash, so you can retrieve it again with the reveal endpoint below or from the Developer Console.

Reveal a Key Again

curl https://api.kolbo.ai/api/api-keys/KEY_ID/reveal \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Returns { "status": true, "fullKey": "kolbo_live_..." }. Ownership is enforced in the lookup, so a key belonging to someone else is indistinguishable from one that does not exist (404, API key not found).

Every other failure returns 400 with a message:

messageCause
This key was created before full-reveal was supported. Create a new key to view it in full.Key minted before the encrypted copy existed — the only fix is to create a replacement key.
This connector credential cannot be revealedInternal connector (OAuth) credentials, keys with source: "connector", and Developer Console USD keys (billingMode: "usd"). isRevealable only reflects the first case, so a USD or connector-source key can show isRevealable: true and still be refused.
Unable to reveal this keyThe stored copy could not be decrypted.

Revealing a key does not require it to be active — revoked and expired keys can still be revealed, but they will not authenticate.

keyPrefix (returned by the create, list and details endpoints) is the first 20 characters of the key followed by a literal .... It is a display label, not a usable credential.

Using the Key

Include it in every request via the X-API-Key header:

curl https://api.kolbo.ai/api/v1/models \
  -H "X-API-Key: YOUR_API_KEY"

JavaScript (fetch):

async function main() {
  const response = await fetch("https://api.kolbo.ai/api/v1/models", {
    headers: { "X-API-Key": "YOUR_API_KEY" }
  });
  const data = await response.json();
  console.log(data);
}
main();

Python (requests):

import requests

response = requests.get(
    "https://api.kolbo.ai/api/v1/models",
    headers={"X-API-Key": "YOUR_API_KEY"}
)
print(response.json())

Optional: Tagging a Session

Every request may additionally carry X-Kolbo-Caller-Session-Id, a stable identifier you choose for one run of your integration. Credit deductions made while it is present are tagged with it, so you can later ask what a whole run cost — see Credits & Billing.

HeaderTypeRequiredDescription
X-Kolbo-Caller-Session-IdstringNo1–128 characters, matching [A-Za-z0-9._:-]+ only. A UUID is the expected shape. Anything longer, empty, or containing a character outside that set is silently discarded — the request still succeeds, it is just not tagged.
curl https://api.kolbo.ai/api/v1/models \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "X-Kolbo-Caller-Session-Id: run-2026-07-27-a"

Managing Keys

List Keys

curl https://api.kolbo.ai/api/api-keys \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Returns { "status": true, "data": [ ... ] }, newest first. The list is not filtered — revoked and expired keys are returned alongside live ones. Read isActive and isExpired rather than assuming every row is usable.

FieldTypeDescription
idstringKey id — the KEY_ID path segment for reveal / details / revoke.
keyPrefixstringFirst 20 characters of the key plus a literal .... Display label, not a credential.
namestringThe label you supplied at creation.
permissionsstring[]read and/or write.
isActivebooleanfalse once revoked. Revocation is a flag flip; the row is never deleted.
isExpiredbooleanComputed against expiresAt at read time.
lastUsedstring | nullTimestamp of the last successful authentication. null if never used.
usageCountnumberIncremented on every successful authentication.
createdAt / expiresAtstringISO timestamps.
sourcestringWhere the key came from: web for keys you create here; other values (e.g. cli, desktop, connector) mark keys minted by Kolbo sign-in flows.
credentialTypestringapi_key, or oauth_connector for an internal connector credential.
billingModestringcredits or usd. List only — not returned by the details endpoint.
isRevealablebooleanfalse for internal connector credentials. It does not account for USD keys or connector-source keys, which the reveal endpoint also refuses — see the reveal errors above.

The list also includes keys minted automatically by Kolbo sign-in flows (Kobi Code, the desktop app, connectors), so expect rows you did not create in the Developer Console.

Get Key Details

curl https://api.kolbo.ai/api/api-keys/KEY_ID \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Returns the same field set as one list row (minus billingMode), under data. A key id that does not exist returns 404; one that exists but belongs to someone else returns 403 — unlike the reveal endpoint, which collapses both into 404.

Revoke a Key

curl -X DELETE https://api.kolbo.ai/api/api-keys/KEY_ID \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Returns { "status": true, "message": "API key revoked successfully" }. An unknown key id returns 404; a key that belongs to someone else returns 403. Requires a JWT — see the table above.

Revocation is immediate and permanent — there is no un-revoke. The key stays in the list with isActive: false.

Permission Scopes

A key carries read, write, or both.

  • Safe methods (GET, HEAD, OPTIONS) are always allowed, whatever the key's scope.
  • A key without write (or admin) is blocked on every mutating request, returning 403 with code API_KEY_READ_ONLY.
  • A few routes enforce write permission on every key, including grandfathered ones, and return 403 for a key without write:
    • POST /api/v1/music-library/clean/{trackId} and POST /api/v1/music-library/import (paid music; code API_KEY_READ_ONLY)
    • POST /api/v1/projects/{id}/transfer, POST /api/v1/project-transfers/{id}/accept, POST /api/v1/project-transfers/{id}/decline, DELETE /api/v1/project-transfers/{id} (code API_KEY_READ_ONLY)
    • POST /api/v1/downloads (no code; body { "error": "API key requires write permission" })
    • POST /api/v1/editor/sessions, PATCH /api/v1/editor/sessions and POST /api/v1/editor/exports (code FORBIDDEN)
    • Every Flows write and run: POST /api/v1/flows, PATCH /api/v1/flows/{flowId}, POST /api/v1/flows/{flowId}/ + snapshot, undo, duplicate, move, trash, restore or runs, and POST /api/v1/flows/{flowId}/runs/{runId}/cancel or /retry (code FORBIDDEN)

Scope enforcement only applies to keys minted after it was introduced. Older keys are grandfathered and can still perform writes even if their listed permissions say read only. Do not rely on an old key's read label as a security boundary — mint a fresh key if you need a genuinely read-only credential.

Limits

  • Expiration is required — every key has an expiresAt. Default 365 days, clamped to 1–730 days.
  • Permissions: read and write only (admin keys cannot be self-created).
  • Key creation is rate limited to 10 attempts per hour per user; the reveal endpoint to 30 per minute. Both return 429 with { "status": false, "message": "...", "retryAfter": <seconds> } (3600 for create, 60 for reveal).

When a Key Stops Working

An otherwise valid key is rejected when any of these are true:

ConditionStatusResponse
No X-API-Key header and no Authorization bearer token401Unauthorized - Token missing
Wrong prefix, unknown key, revoked, or past expiresAt401Invalid API key format / Invalid or expired API key
Account restricted by an administrator401User account has been restricted
Account soft-deleted and pending permanent deletion401Account is scheduled for permanent deletion. Restore it via the link in your email to use this API key again.
Developer Console USD key used outside the Developer Console API401USD API key is restricted to the developer console API
Email not verified403{ "status": false, "message": "Please verify your email to access the platform.", "emailNotVerified": true }
Read-only key on a mutating request403{ "status": false, "message": "This API key is read-only. Create a key with write permission to perform this action.", "code": "API_KEY_READ_ONLY" }
Unexpected server error while validating the key500{ "message": "Authentication server error", "tokenExpired": false }

Every 401 above shares one body — { "message": "...", "tokenExpired": false } — with no code field. Distinguish them by reading message, not by branching on a code.

Keys are not auto-revoked during the deletion grace window, so restoring an account brings its existing keys back without re-creating them.

Security Best Practices

  • Store keys in environment variables, never in code
  • Use separate keys for different integrations
  • Revoke unused keys promptly
  • Monitor usage via the key details endpoint — every successful authentication bumps usageCount and lastUsed