API reference
The HTTP API the kol CLI and MCP server use. Everything is JSON. Calls that change or read your AIs need a token from the sign-in flow (POST /api/pair, then approve the code in the Kol app, then GET /api/pair/{code}), sent as Authorization: Bearer <token>.
Errors are {"error": "...", "hint": "..."} (hint is optional) with a 4xx or 5xx status.
The full OpenAPI 3.1 spec: openapi.yaml. Load it in any OpenAPI tool to generate a client.
Sign-in
POST /api/pair
Start signing in · no sign-in needed
Returns a short code to approve in the Kol app (Companions → Creator portal), and a secret deviceCode that only you see. Codes expire after 5 minutes. At most 20 codes per address every 10 minutes.
Body
| Field | Type | Description |
|---|---|---|
client | cli | Ask for a CLI sign-in (with a device code). |
label | string | What is signing in, for example "kol on my-laptop". |
{
"client": "cli",
"label": "kol on my-laptop"
}| Status | Meaning |
|---|---|
| 200 | A code to approve. |
| 429 | Too many requests. Wait and try again. |
GET /api/pair/{code}
Collect the token · no sign-in needed
Poll every 2 seconds until the code is approved. Needs the deviceCode from the start.
| Parameter | In | Description |
|---|---|---|
code | path | |
device | query | The deviceCode from POST /api/pair. |
| Status | Meaning |
|---|---|
| 200 | Approved. Keep the token secret; it works for 90 days. |
| 202 | Not approved yet. Try again in 2 seconds. |
| 410 | The code expired, was already used, or the device code is wrong. |
GET /api/me
Who you are · needs a token
| Status | Meaning |
|---|---|
| 200 | You. |
| 401 | No token, or it expired or was revoked. Sign in again. |
POST /api/logout
Sign out · needs a token
The token stops working.
| Status | Meaning |
|---|---|
| 200 | Signed out. |
| 401 | No token, or it expired or was revoked. Sign in again. |
Rules
GET /api/schema
Allowed values and limits · no sign-in needed
| Status | Meaning |
|---|---|
| 200 | What a draft may contain. |
POST /api/validate
Check a draft · no sign-in needed
The same check as saving, without saving. problem is a short code, see the Draft schema.
Body
| Field | Type | Description |
|---|---|---|
draft (required) | Draft |
| Status | Meaning |
|---|---|
| 200 | The result. |
AIs
GET /api/creations
Your AIs · needs a token
| Status | Meaning |
|---|---|
| 200 | Every AI you made. |
| 401 | No token, or it expired or was revoked. Sign in again. |
POST /api/creations
Make an AI · needs a token
Saves a new draft. Only you can see it until you publish it. At most 20 per person.
Body
| Field | Type | Description |
|---|---|---|
draft (required) | Draft |
| Status | Meaning |
|---|---|
| 200 | The AI. |
| 400 | Something in the request is wrong; error says what. |
| 401 | No token, or it expired or was revoked. Sign in again. |
GET /api/creations/{id}
One AI · needs a token
| Parameter | In | Description |
|---|---|---|
id | path | The AI's ID, like c-1a2b3c4d. |
| Status | Meaning |
|---|---|
| 200 | The AI. |
| 404 | There is no such AI, or it isn't yours (error is "not yours"). |
PUT /api/creations/{id}
Change an AI · needs a token
Saves a new version. If it is published, everyone gets the change on their next call. kind can't change.
| Parameter | In | Description |
|---|---|---|
id | path | The AI's ID, like c-1a2b3c4d. |
Body
| Field | Type | Description |
|---|---|---|
draft (required) | Draft |
| Status | Meaning |
|---|---|
| 200 | The AI. |
| 400 | Something in the request is wrong; error says what. |
| 404 | There is no such AI, or it isn't yours (error is "not yours"). |
POST /api/creations/{id}/publish
Publish or unpublish · needs a token
Puts it in the marketplace (on: true) or takes it out. People who have it keep it.
| Parameter | In | Description |
|---|---|---|
id | path | The AI's ID, like c-1a2b3c4d. |
Body
| Field | Type | Description |
|---|---|---|
on (required) | boolean |
| Status | Meaning |
|---|---|
| 200 | The AI. |
| 404 | There is no such AI, or it isn't yours (error is "not yours"). |
PUT /api/creations/{id}/knowledge
Replace its knowledge · needs a token
Replaces everything it knows with these items. Web pages are read once, now. All or nothing: on an error nothing changes. At most 50 items and 40,000 characters in total.
| Parameter | In | Description |
|---|---|---|
id | path | The AI's ID, like c-1a2b3c4d. |
Body
| Field | Type | Description |
|---|---|---|
items (required) | array of KnowledgeInput |
| Status | Meaning |
|---|---|
| 200 | The AI. |
| 400 | Something in the request is wrong; error says what. |
| 404 | There is no such AI, or it isn't yours (error is "not yours"). |
GET /api/creations/{id}/requests
Requests it took · needs a token
Requests callers confirmed and asked it to send you (the requests skill).
| Parameter | In | Description |
|---|---|---|
id | path | The AI's ID, like c-1a2b3c4d. |
| Status | Meaning |
|---|---|
| 200 | Newest first. |
| 404 | There is no such AI, or it isn't yours (error is "not yours"). |
Testing
POST /api/try
Talk to an AI in text · needs a token
The AI's next reply to a conversation, with the same instructions and skills it has in a call. Send a draft (with knowledge) to try something unsaved, or a saved creation ID. With no messages you get its greeting. Tools run in test mode: nothing is delivered. dryRun returns the instructions without calling the AI model.
Runs on your own AI key. At most 120 per hour.
Body
{
"draft": {
"name": "Kitchen Buddy",
"tagline": "Cooks with you.",
"description": "",
"persona": "You are Kitchen Buddy",
"a calm home cook.": null,
"greeting": "",
"icon": "restaurant",
"color": "#E8590C",
"voice": "cedar",
"price": 0,
"canAnswerForYou": false,
"kind": "companion"
},
"knowledge": [
{
"title": "notes.md",
"text": "Salt pasta water well."
}
],
"messages": [
{
"role": "user",
"text": "How much salt goes in pasta water?"
}
]
}| Status | Meaning |
|---|---|
| 200 | The reply, or with dryRun the instructions. |
| 400 | Something in the request is wrong; error says what. |
| 402 | You have no AI key. Add one in the Kol app (Companions → Your AI key). |
| 404 | There is no such AI, or it isn't yours (error is "not yours"). |
| 429 | Too many requests. Wait and try again. |
| 502 | The AI model did not answer, or your AI key was rejected. |
GET /api/events
Live events · needs a token
Server-sent events (text/event-stream): each data: line is one JSON Event. Try-outs, voice tests from the app or portal, and new requests. A comment line every 20 seconds keeps it open.
| Status | Meaning |
|---|---|
| 200 | The stream. |
| 401 | No token, or it expired or was revoked. Sign in again. |
Schemas
Error
| Field | Type | Description |
|---|---|---|
error (required) | string | |
hint | string | What to do about it. |
PairStart
| Field | Type | Description |
|---|---|---|
code (required) | string | 6 characters to approve in the Kol app. |
link (required) | string | The same code as a link the phone can open (for a QR code). |
expiresInSec (required) | integer | |
deviceCode | string | Only with client "cli": the secret needed to collect the token. Never show it to anyone. |
PairDone
| Field | Type | Description |
|---|---|---|
token (required) | string | Send as Authorization Bearer. |
me (required) | Person | |
expiresAt | string |
Person
| Field | Type | Description |
|---|---|---|
id | string | Your 6-character Kol ID. |
name | string |
Me
Everything in Person, plus:
| Field | Type | Description |
|---|---|---|
access | object | Who pays for your try-outs and your public AIs' calls. |
Rules
| Field | Type | Description |
|---|---|---|
icons | array of string | |
colors | array of string | |
voices | array of string | |
prices | array of number | |
limits | object | |
kinds | array of string |
Draft
What you fill in. The kol CLI makes this from kol.json and persona.md. Problem codes from validation: name, tagline (missing), persona (under 20 characters), too long, look (icon, color or voice not allowed), price, kind, requestWhat (requests on but nothing listed), malformed (a field missing or the wrong type).
| Field | Type | Description |
|---|---|---|
name (required) | string | |
tagline (required) | string | |
description (required) | string | |
persona (required) | string | Its instructions. |
greeting (required) | string | First words. {owner} is replaced by the name of who it talks to. |
icon (required) | sparkles, chatbubbles, restaurant, school, fitness, heart, musical-notes, book, briefcase, leaf, rocket, happy | |
color (required) | #3B5BDB, #E8590C, #2F9E44, #C2255C, #7048E8, #0C8599, #E67700, #495057 | |
voice (required) | marin, cedar, coral, sage, ash, verse, ballad, alloy | |
price (required) | 0, 0.99, 1.99, 2.99, 4.99 | USD a month for a companion; 0 is free. |
canAnswerForYou (required) | boolean | Companions only. It may answer calls for its owner and take a message. |
kind | companion, service | |
takesRequests | boolean | The requests skill. |
requestWhat | string | What a request must include. |
Creation
| Field | Type | Description |
|---|---|---|
id | string | |
version | integer | Goes up by one on every change. |
draft | Draft | |
published | boolean | |
serviceId | string or null | A service: its Kol ID, once it has been online. |
installs | integer | People who have it (you included). |
calls | integer | |
minutes | integer | |
requests | integer | |
knowledge | array of KnowledgeItem |
KnowledgeItem
| Field | Type | Description |
|---|---|---|
id | string | |
kind | text, file, url | |
title | string | |
chars | integer | |
addedAt | string |
KnowledgeInput
One of: object · object
Message
| Field | Type | Description |
|---|---|---|
role (required) | user, assistant | |
text (required) | string |
TryRequest
| Field | Type | Description |
|---|---|---|
draft | Draft | |
knowledge | array of object | With draft. Text only (web pages are read when saved). |
creation | string | A saved AI's ID |
messages | array of Message | The conversation so far, oldest first. The last one is from the user. Empty for the greeting. |
as | owner, standIn | standIn tries it answering a call for its owner. |
dryRun | boolean |
TryReply
| Field | Type | Description |
|---|---|---|
as | owner, service, standIn | |
model | string | |
reply | string | |
tools | array of object |
DryRun
| Field | Type | Description |
|---|---|---|
as | owner, service, standIn | |
instructions | string | Everything the AI is told. |
greeting | string | |
tools | array of object |
Request
| Field | Type | Description |
|---|---|---|
id | string | |
fromName | string | |
at | string | |
text | string |
Event
One of: A test or try-out line. · A new request from a caller. · Your AIs changed (in the app or another window).