Kami·API Reference
https://api.kami.bot/api

REST API for the Kami agent platform. Manages agents, threads, messages, knowledge, and identities.

Authentication

All endpoints require Authorization: Bearer <token>. Create an API key (dk_…) with POST /keys; browser sessions use a token from POST /sessions.

sessions
post/sessionsCreate session

Creates a new session. Use master key to create operator sessions, or a public API key for user sessions.

Request
curl -X POST https://api.kami.bot/api/sessions \
  -H "Authorization: Bearer $API_KEY"
get/sessionsList active sessions

Returns all active (non-revoked, non-expired) sessions for the current entity.

Response type
object
Example
{}
Request
curl -X GET https://api.kami.bot/api/sessions \
  -H "Authorization: Bearer $API_KEY"
post/sessions/login-via-linkCreate a session from a bot-issued magic link
Request
curl -X POST https://api.kami.bot/api/sessions/login-via-link \
  -H "Authorization: Bearer $API_KEY"
post/sessions/recognizeCreate a recognized session from a recognition token
Request
curl -X POST https://api.kami.bot/api/sessions/recognize \
  -H "Authorization: Bearer $API_KEY"
post/sessions/refreshRefresh session

Refreshes an expired session token. Identity persists, access token rotates.

Response type
object
Example
{}
Request
curl -X POST https://api.kami.bot/api/sessions/refresh \
  -H "Authorization: Bearer $API_KEY"
post/sessions/ws-tokenMint short-lived WebSocket token

Returns a 5-minute JWT scoped to a specific agent for this session's entity. The agent is specified per-call via the agentId body field — the session JWT carries identity, not agent. The caller must be a participant in a chat with that agent (or the agent's creator). Used by browser + mobile WS clients that can't carry Authorization headers on the WS upgrade.

Response type
object
Example
{}
Request
curl -X POST https://api.kami.bot/api/sessions/ws-token \
  -H "Authorization: Bearer $API_KEY"
post/sessions/revokeRevoke session

Revokes the current session token. The token becomes invalid immediately.

Response type
object
Example
{}
Request
curl -X POST https://api.kami.bot/api/sessions/revoke \
  -H "Authorization: Bearer $API_KEY"
keys
post/keysCreate API key

Creates a new API key. Requires master key (owner) auth.

Body type
{
  label?:  string  // Human-readable key label.
  agentId?:  string  // Agent this key is scoped to.
  type?:  "public" | "secret"  // Key type. Public keys can create sessions. Secret keys have full API access.
  allowedOrigins?:  string[]  // Allowed CORS origins for this key.
}
Example
{
  "label": "label",
  "agentId": "agentId",
  "type": "type",
  "allowedOrigins": []
}
Response type
{
  key:  string  // The full API key — shown only once.
  id:  string  // Key ID.
  label:  string
  type:  string
  agentId?:  string
}
Example
{
  "key": "key",
  "id": "id",
  "label": "label",
  "type": "type",
  "agentId": "agentId"
}
Request
curl -X POST https://api.kami.bot/api/keys \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "label",
    "agentId": "agentId",
    "type": "type",
    "allowedOrigins": []
  }'
get/keysList API keys

Returns all API keys (without full key values). Requires master key (owner) auth.

Response type
{
  keys:  object[]
}
Example
{
  "keys": []
}
Request
curl -X GET https://api.kami.bot/api/keys \
  -H "Authorization: Bearer $API_KEY"
delete/keys/{id}Delete API key

Revokes an API key. Requires master key (owner) auth.

Path parameters
idrequiredstringKey ID to delete.
Response type
{
  deleted:  boolean
}
Example
{
  "deleted": false
}
Request
curl -X DELETE https://api.kami.bot/api/keys/{id} \
  -H "Authorization: Bearer $API_KEY"
agents
post/agentsCreate agent
Body type
{
  id:  string  // Unique agent ID (slug-style).
  name:  string  // Display name.
  personality?:  string  // System personality prompt.
  createdBy?:  string  // Creator identifier.
  avatarUrl?:  string  // Legacy image URL (prefer `avatar`).
  avatar?:  object  // Polymorphic avatar/incarnation metadata { kind, …data }.
  appearance?:  string  // Canonical appearance description (what the character looks like, constant across incarnations).
  models?:  object  // Per-role model overrides (master key only; not persisted across reboots - bench use).
}
Example
{
  "id": "id",
  "name": "name",
  "personality": "personality",
  "createdBy": "createdBy",
  "avatarUrl": "avatarUrl",
  "avatar": null,
  "appearance": "appearance",
  "models": null
}
Request
curl -X POST https://api.kami.bot/api/agents \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "id",
    "name": "name",
    "personality": "personality",
    "createdBy": "createdBy",
    "avatarUrl": "avatarUrl",
    "avatar": null,
    "appearance": "appearance",
    "models": null
  }'
get/agentsList / discover agents

Public agents to anonymous callers; full list to admins. Supports search + sort + pagination.

Response type
{
  agents:  object[]
  total:  number
}
Example
{
  "agents": [],
  "total": 0
}
Request
curl -X GET https://api.kami.bot/api/agents \
  -H "Authorization: Bearer $API_KEY"
get/agents/{id}Get agent
Path parameters
idrequiredstringAgent ID.
Response type
{
  agent:  object
}
Example
{
  "agent": null
}
Request
curl -X GET https://api.kami.bot/api/agents/{id} \
  -H "Authorization: Bearer $API_KEY"
patch/agents/{id}Update agent
Path parameters
idrequiredstringAgent ID.
Body type
{
  name?:  string  // New display name.
  personality?:  string  // New personality prompt.
  avatarUrl?:  string  // Legacy image URL (prefer `avatar`).
  avatar?:  object  // Polymorphic avatar/incarnation metadata { kind, …data }.
  appearance?:  string  // Canonical appearance description (constant across incarnations).
  slug?:  string  // URL slug (lowercase + hyphens, must start with alphanumeric).
  description?:  string  // Hub-card tagline.
  visibility?:  "public" | "unlisted" | "private"  // Hub listing visibility.
  dmPolicy?:  "everyone" | "admins" | "off"  // Who may DM the agent: everyone / admins / off. Owner-only.
}
Example
{
  "name": "name",
  "personality": "personality",
  "avatarUrl": "avatarUrl",
  "avatar": null,
  "appearance": "appearance",
  "slug": "slug",
  "description": "description",
  "visibility": "visibility",
  "dmPolicy": "dmPolicy"
}
Response type
{
  agent:  object
}
Example
{
  "agent": null
}
Request
curl -X PATCH https://api.kami.bot/api/agents/{id} \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "name",
    "personality": "personality",
    "avatarUrl": "avatarUrl",
    "avatar": null,
    "appearance": "appearance",
    "slug": "slug",
    "description": "description",
    "visibility": "visibility",
    "dmPolicy": "dmPolicy"
  }'
delete/agents/{id}Delete agent
Path parameters
idrequiredstringAgent ID.
Response type
{
  deleted:  boolean
}
Example
{
  "deleted": false
}
Request
curl -X DELETE https://api.kami.bot/api/agents/{id} \
  -H "Authorization: Bearer $API_KEY"
post/agents/{id}/voice-outSpeak text on the agent's voice emission rail (operator)
Path parameters
idrequiredstringAgent ID.
Body type
{
  chatId:  string  // Scope chat id (e.g. the world slug for vibeworld scopes).
  platform?:  string  // Scope platform (floor + emission key).
  threadId?:  string
  text:  string  // The text to synthesize and play on the emission rail.
}
Example
{
  "chatId": "chatId",
  "platform": "platform",
  "threadId": "threadId",
  "text": "text"
}
Request
curl -X POST https://api.kami.bot/api/agents/{id}/voice-out \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "chatId": "chatId",
    "platform": "platform",
    "threadId": "threadId",
    "text": "text"
  }'
get/agents/{id}/keepsakesPublic keepsake images

No auth required. The agent's most recent PUBLICLY SAFE self-generated images (bot_gen, zero external reference images - tagged role='keepsake' at ingest). The companion room hangs them in its wall frames. Never user uploads or reference-based portraits, by construction.

Path parameters
idrequiredstringAgent ID.
Response type
{
  images:  object[]
}
Example
{
  "images": []
}
Request
curl -X GET https://api.kami.bot/api/agents/{id}/keepsakes \
  -H "Authorization: Bearer $API_KEY"
get/agents/{id}/publicPublic agent profile

No auth required. Returns public profile, platforms, and builtin capabilities.

Path parameters
idrequiredstringAgent ID.
Response type
{
  profile:  object
  platforms:  object[]
  capabilities:  object[]
  uptime:  number  // Server uptime in seconds.
}
Example
{
  "profile": null,
  "platforms": [],
  "capabilities": [],
  "uptime": 0
}
Request
curl -X GET https://api.kami.bot/api/agents/{id}/public \
  -H "Authorization: Bearer $API_KEY"
get/agents/{id}/statsAgent activity counters (thread + message count)

Public. Three integer counters used by the hub to render per-agent cards.

Path parameters
idrequiredstringAgent ID.
Response type
{
  threadCount:  number
  messageCount:  number
  lastActivityAt:  number
}
Example
{
  "threadCount": 0,
  "messageCount": 0,
  "lastActivityAt": 0
}
Request
curl -X GET https://api.kami.bot/api/agents/{id}/stats \
  -H "Authorization: Bearer $API_KEY"
get/agents/{id}/connectionsPlatform connections
Path parameters
idrequiredstringAgent ID.
Response type
{
  agentId:  string
  connections:  object[]
}
Example
{
  "agentId": "agentId",
  "connections": []
}
Request
curl -X GET https://api.kami.bot/api/agents/{id}/connections \
  -H "Authorization: Bearer $API_KEY"
get/agents/{id}/connections/whatsapp/qrWhatsApp link state (QR / pairing code)
Path parameters
idrequiredstringAgent ID.
Response type
{
  agentId:  string
  status:  string  // Connection status: connected / needs_auth / reconnecting / ...
  connected:  boolean
  qr:  string  // Raw QR payload to render when awaiting a scan. Null when connected/unavailable.
  pairingCode:  string  // Pairing code to enter in WhatsApp → Linked Devices, when BAILEYS_PAIRING_PHONE is set. Null otherwise.
}
Example
{
  "agentId": "agentId",
  "status": "status",
  "connected": false,
  "qr": "qr",
  "pairingCode": "pairingCode"
}
Request
curl -X GET https://api.kami.bot/api/agents/{id}/connections/whatsapp/qr \
  -H "Authorization: Bearer $API_KEY"
post/agents/{id}/connections/whatsapp/restartRestart WhatsApp link (regenerate QR / code)
Path parameters
idrequiredstringAgent ID.
Response type
{
  agentId:  string
  ok:  boolean
  message:  string
}
Example
{
  "agentId": "agentId",
  "ok": false,
  "message": "message"
}
Request
curl -X POST https://api.kami.bot/api/agents/{id}/connections/whatsapp/restart \
  -H "Authorization: Bearer $API_KEY"
post/agents/{id}/credentials/{key}Set or replace an encrypted credential (write-only)
Path parameters
idrequiredstringAgent ID.
keyrequiredstringCredential key, e.g. TELEGRAM_BOT_TOKEN, DISCORD_BOT_TOKEN, FAL_API_KEY.
Body type
{
  value:  string  // The raw secret to store (e.g. a bot token). Stored encrypted; never echoed back.
}
Example
{
  "value": "value"
}
Response type
{
  key:  string
  createdAt:  number
  updatedAt:  number
}
Example
{
  "key": "key",
  "createdAt": 0,
  "updatedAt": 0
}
Request
curl -X POST https://api.kami.bot/api/agents/{id}/credentials/{key} \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "value": "value"
  }'
delete/agents/{id}/credentials/{key}Delete a stored credential
Path parameters
idrequiredstringAgent ID.
keyrequiredstringCredential key, e.g. TELEGRAM_BOT_TOKEN, DISCORD_BOT_TOKEN, FAL_API_KEY.
Response type
{
  key:  string
  deleted:  boolean  // True if a row was removed; false if none existed.
}
Example
{
  "key": "key",
  "deleted": false
}
Request
curl -X DELETE https://api.kami.bot/api/agents/{id}/credentials/{key} \
  -H "Authorization: Bearer $API_KEY"
get/agents/{id}/credentialsList configured credential keys (never values)
Path parameters
idrequiredstringAgent ID.
Response type
{
  agentId:  string
  credentials:  object[]
}
Example
{
  "agentId": "agentId",
  "credentials": []
}
Request
curl -X GET https://api.kami.bot/api/agents/{id}/credentials \
  -H "Authorization: Bearer $API_KEY"
post/agents/{id}/connections/{platform}Connect a branded bot channel (BYO-token)
Path parameters
idrequiredstringAgent ID.
platformrequiredstringWhich channel to connect/disconnect.
Body type
{
  token:  string  // The platform bot token (BotFather / Discord developer portal). Stored encrypted; validated before connecting.
}
Example
{
  "token": "token"
}
Response type
{
  agentId:  string
  connections:  object[]
}
Example
{
  "agentId": "agentId",
  "connections": []
}
Request
curl -X POST https://api.kami.bot/api/agents/{id}/connections/{platform} \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "token": "token"
  }'
delete/agents/{id}/connections/{platform}Disconnect a channel + drop its token
Path parameters
idrequiredstringAgent ID.
platformrequiredstringWhich channel to connect/disconnect.
Response type
{
  agentId:  string
  connections:  object[]
}
Example
{
  "agentId": "agentId",
  "connections": []
}
Request
curl -X DELETE https://api.kami.bot/api/agents/{id}/connections/{platform} \
  -H "Authorization: Bearer $API_KEY"
get/agents/{id}/activityAgent activity

The agent's durative sessions right now. Public callers get an abstract view (kind + status); operators/owners get full detail (surface, timing). Liveness is TTL-guarded at read time.

Path parameters
idrequiredstringAgent ID.
Response type
{
  events:  object[]  // Reserved (empty) - private activity events are not exposed here.
  sessions:  object[]  // Durative sessions the agent is running now. Public callers see an ABSTRACT view (kind + status); operators/owners see full detail (surface, timing).
}
Example
{
  "events": [],
  "sessions": []
}
Request
curl -X GET https://api.kami.bot/api/agents/{id}/activity \
  -H "Authorization: Bearer $API_KEY"
post/agents/{id}/operatorsGrant operator access
Path parameters
idrequiredstringAgent ID.
Body type
{
  entityId:  string  // Canonical entity ID to grant operator access.
}
Example
{
  "entityId": "entityId"
}
Response type
{
  granted:  boolean
  agentId:  string
  entityId:  string
}
Example
{
  "granted": false,
  "agentId": "agentId",
  "entityId": "entityId"
}
Request
curl -X POST https://api.kami.bot/api/agents/{id}/operators \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "entityId": "entityId"
  }'
delete/agents/{id}/operatorsRevoke operator access
Path parameters
idrequiredstringAgent ID.
Response type
{
  removed:  boolean
  agentId:  string
}
Example
{
  "removed": false,
  "agentId": "agentId"
}
Request
curl -X DELETE https://api.kami.bot/api/agents/{id}/operators \
  -H "Authorization: Bearer $API_KEY"
post/agents/{id}/knowledgeAdd knowledge
Path parameters
idrequiredstringAgent ID.
Body type
{
  name:  string  // Knowledge item name.
  content:  string  // Knowledge content.
  chatId?:  string  // Scope to a specific chat.
  entityId?:  string  // Associated entity.
  sourceType?:  "text" | "url" | "builtin" | "learned"  // How the knowledge was added.
  summary?:  string  // Short summary for listings.
}
Example
{
  "name": "name",
  "content": "content",
  "chatId": "chatId",
  "entityId": "entityId",
  "sourceType": "sourceType",
  "summary": "summary"
}
Request
curl -X POST https://api.kami.bot/api/agents/{id}/knowledge \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "name",
    "content": "content",
    "chatId": "chatId",
    "entityId": "entityId",
    "sourceType": "sourceType",
    "summary": "summary"
  }'
get/agents/{id}/knowledgeList knowledge
Path parameters
idrequiredstringAgent ID.
Response type
{
  knowledge:  object[]
}
Example
{
  "knowledge": []
}
Request
curl -X GET https://api.kami.bot/api/agents/{id}/knowledge \
  -H "Authorization: Bearer $API_KEY"
get/agents/{id}/workspaces/{workspaceId}/configGet workspace config (excluded categories)
Path parameters
idrequiredstringAgent ID.
workspaceIdrequiredstringWorkspace ID (Discord guild id).
Response type
{
  agentId:  string
  platform:  string
  workspaceId:  string
  excludedCategoryIds:  string[]
}
Example
{
  "agentId": "agentId",
  "platform": "platform",
  "workspaceId": "workspaceId",
  "excludedCategoryIds": []
}
Request
curl -X GET https://api.kami.bot/api/agents/{id}/workspaces/{workspaceId}/config \
  -H "Authorization: Bearer $API_KEY"
patch/agents/{id}/workspaces/{workspaceId}/configUpdate workspace config (excluded categories)
Path parameters
idrequiredstringAgent ID.
workspaceIdrequiredstringWorkspace ID (Discord guild id).
Body type
{
  excludedCategoryIds:  string[]  // Full set of excluded category ids (replaces the current set).
}
Example
{
  "excludedCategoryIds": []
}
Response type
{
  agentId:  string
  platform:  string
  workspaceId:  string
  excludedCategoryIds:  string[]
}
Example
{
  "agentId": "agentId",
  "platform": "platform",
  "workspaceId": "workspaceId",
  "excludedCategoryIds": []
}
Request
curl -X PATCH https://api.kami.bot/api/agents/{id}/workspaces/{workspaceId}/config \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "excludedCategoryIds": []
  }'
get/agents/{id}/usageAgent usage + plan
Path parameters
idrequiredstringAgent ID.
Query parameters
periodstringBilling period 'YYYY-MM' (UTC). Defaults to the current month.
chatIdstringScope the count to one chat/group. Required for scope-admin (non-operator) callers.
Response type
{
  period:  string  // Billing period 'YYYY-MM'.
  responses:  number  // Delivered bot responses in the period (for the chat if chatId given, else the agent total).
  limit:  number  // Monthly response limit from the agent's plan (default 5000).
  plan:  string  // Plan name from the agent's plan (default 'creator').
}
Example
{
  "period": "period",
  "responses": 0,
  "limit": 0,
  "plan": "plan"
}
Request
curl -X GET https://api.kami.bot/api/agents/{id}/usage \
  -H "Authorization: Bearer $API_KEY"
get/agents/{id}/spendAgent LLM cost ($), owner-only
Path parameters
idrequiredstringAgent ID.
Query parameters
periodstringTime range: 1h | 6h | 24h | 7d | 30d. Default 24h.
Response type
{
  agentId:  string
  period:  string
  total:  object
  byThread:  object[]
  byChat:  object[]
  byModel:  object[]
}
Example
{
  "agentId": "agentId",
  "period": "period",
  "total": null,
  "byThread": [],
  "byChat": [],
  "byModel": []
}
Request
curl -X GET https://api.kami.bot/api/agents/{id}/spend \
  -H "Authorization: Bearer $API_KEY"
get/agents/{id}/billingSubscription status
Path parameters
idrequiredstringAgent ID.
Response type
{
  configured:  boolean  // Whether the server has Stripe wired (secret key + price id).
  plan:  string  // Plan name from agent_plans, or null (free default).
  status:  string  // Stripe subscription status: active|trialing|past_due|canceled|… or null.
  subscribed:  boolean  // True when status is active or trialing.
  monthlyResponseLimit:  number  // Monthly response limit for the plan.
  currentPeriodEnd:  number  // Unix seconds the current period / access lasts until.
  hasStripeCustomer:  boolean  // Whether a Stripe Customer exists for this agent.
}
Example
{
  "configured": false,
  "plan": "plan",
  "status": "status",
  "subscribed": false,
  "monthlyResponseLimit": 0,
  "currentPeriodEnd": 0,
  "hasStripeCustomer": false
}
Request
curl -X GET https://api.kami.bot/api/agents/{id}/billing \
  -H "Authorization: Bearer $API_KEY"
post/agents/{id}/billing/checkoutStart a Stripe Checkout for the Creator plan
Path parameters
idrequiredstringAgent ID.
Body type
{
  returnPath?:  string  // Console path to return to after checkout. Defaults to /<agentId>.
}
Example
{
  "returnPath": "returnPath"
}
Response type
{
  url:  string  // Stripe Checkout URL to redirect the buyer to.
}
Example
{
  "url": "url"
}
Request
curl -X POST https://api.kami.bot/api/agents/{id}/billing/checkout \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "returnPath": "returnPath"
  }'
post/agents/{id}/billing/portalOpen the Stripe Billing Portal
Path parameters
idrequiredstringAgent ID.
Body type
{
  returnPath?:  string  // Console path to return to after checkout. Defaults to /<agentId>.
}
Example
{
  "returnPath": "returnPath"
}
Response type
{
  url:  string  // Stripe Billing Portal URL to manage the subscription.
}
Example
{
  "url": "url"
}
Request
curl -X POST https://api.kami.bot/api/agents/{id}/billing/portal \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "returnPath": "returnPath"
  }'
skills
get/agents/{id}/skillsList agent skills
Path parameters
idrequiredstringAgent ID.
Query parameters
chatIdstringWhen present, `enabled` reflects the per-chat override for agent-global builtins.
Response type
{
  agentId:  string
  skills:  object[]
}
Example
{
  "agentId": "agentId",
  "skills": []
}
Request
curl -X GET https://api.kami.bot/api/agents/{id}/skills \
  -H "Authorization: Bearer $API_KEY"
patch/agents/{id}/skills/{name}Toggle a skill on/off
Path parameters
idrequiredstringAgent ID.
namerequiredstringSkill name (knowledge row name).
Body type
{
  enabled:  boolean  // Target enabled state.
  chatId?:  string  // When present, writes a per-chat override (admin-gated). When absent, flips the row's own enabled flag (operator-gated).
}
Example
{
  "enabled": false,
  "chatId": "chatId"
}
Response type
{
  name:  string
  enabled:  boolean
  scope:  "chat" | "agent"  // chat = per-chat override; agent = row-level flag.
}
Example
{
  "name": "name",
  "enabled": false,
  "scope": "scope"
}
Request
curl -X PATCH https://api.kami.bot/api/agents/{id}/skills/{name} \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": false,
    "chatId": "chatId"
  }'
delete/agents/{id}/skills/{name}Delete (archive) a skill
Path parameters
idrequiredstringAgent ID.
namerequiredstringSkill name (knowledge row name).
Query parameters
chatIdstringWhen present, `enabled` reflects the per-chat override for agent-global builtins.
Response type
{
  deleted:  boolean
  name:  string
}
Example
{
  "deleted": false,
  "name": "name"
}
Request
curl -X DELETE https://api.kami.bot/api/agents/{id}/skills/{name} \
  -H "Authorization: Bearer $API_KEY"
post/agents/{id}/skills/installInstall a skill by URL
Path parameters
idrequiredstringAgent ID.
Body type
{
  url:  string  // URL of the skill .md to fetch and install.
  chatId?:  string  // Scope the installed skill to a chat. Omit for agent-global (operator).
}
Example
{
  "url": "url",
  "chatId": "chatId"
}
Request
curl -X POST https://api.kami.bot/api/agents/{id}/skills/install \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "url",
    "chatId": "chatId"
  }'
threads
post/threadsCreate thread
Body type
{
  title?:  string  // Thread title.
  id?:  string  // Custom thread ID (defaults to UUID).
  type?:  string  // Thread type (private or group).
  agentId?:  string  // Agent to assign to this thread.
}
Example
{
  "title": "title",
  "id": "id",
  "type": "type",
  "agentId": "agentId"
}
Request
curl -X POST https://api.kami.bot/api/threads \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "title",
    "id": "id",
    "type": "type",
    "agentId": "agentId"
  }'
get/threadsList threads
Response type
{
  threads:  object[]
}
Example
{
  "threads": []
}
Request
curl -X GET https://api.kami.bot/api/threads \
  -H "Authorization: Bearer $API_KEY"
get/threads/{id}Get thread detail
Path parameters
idrequiredstringThread ID.
Response type
{
  id:  string
  title:  string
  type:  string
  agentId:  string
  config:  object
  participants:  object[]
  lastMessageAt:  number
}
Example
{
  "id": "id",
  "title": "title",
  "type": "type",
  "agentId": "agentId",
  "config": null,
  "participants": [],
  "lastMessageAt": 0
}
Request
curl -X GET https://api.kami.bot/api/threads/{id} \
  -H "Authorization: Bearer $API_KEY"
delete/threads/{id}Delete thread
Path parameters
idrequiredstringThread ID.
Response type
{
  deleted:  boolean
}
Example
{
  "deleted": false
}
Request
curl -X DELETE https://api.kami.bot/api/threads/{id} \
  -H "Authorization: Bearer $API_KEY"
patch/threads/{id}/configUpdate thread config
Path parameters
idrequiredstringThread ID.
Body type
{
  agentId?:  string  // Override agent for config lookup.
  language?:  string  // ISO language code.
  replyMode?:  "social" | "quiet" | "silent"  // Reply mode.
  instructions?:  string  // Custom instructions.
  topicFocus?:  string  // Topic-scope: when set, the agent engages ONLY with messages on this topic here. null/empty clears the restriction.
  knowledgeMode?:  "open" | "grounded"  // Knowledge mode: open (free) or grounded (answer only from sources).
  allowedRoleIds?:  string[]  // Role whitelist: platform role ids allowed to engage. [] / null clears (everyone).
  substantiveSaturation?:  number  // Saturation cap override. null = inherit from chat/agent default.
  postStimulusDecay?:  number  // Post-stimulus decay multiplier override. null = inherit.
  threadId?:  string  // Sub-encounter id (Telegram topic, Discord thread). When set, overrides apply at thread level; omitted = chat level.
}
Example
{
  "agentId": "agentId",
  "language": "language",
  "replyMode": "replyMode",
  "instructions": "instructions",
  "topicFocus": "topicFocus",
  "knowledgeMode": "knowledgeMode",
  "allowedRoleIds": [],
  "substantiveSaturation": 0,
  "postStimulusDecay": 0,
  "threadId": "threadId"
}
Response type
{
  configured:  boolean
}
Example
{
  "configured": false
}
Request
curl -X PATCH https://api.kami.bot/api/threads/{id}/config \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "agentId",
    "language": "language",
    "replyMode": "replyMode",
    "instructions": "instructions",
    "topicFocus": "topicFocus",
    "knowledgeMode": "knowledgeMode",
    "allowedRoleIds": [],
    "substantiveSaturation": 0,
    "postStimulusDecay": 0,
    "threadId": "threadId"
  }'
post/threads/{id}/stimulusInject operator stimulus into a thread
Path parameters
idrequiredstringThread ID.
Body type
{
  kind:  "topic-seed" | "world-event" | "nudge"  // Stimulus type.
  text?:  string  // Prompt text the agents see.
  payload?:  object  // Structured envelope.
  source?:  string  // Origin tag for audit / dashboards.
  agentId?:  string  // Single-agent target; default = all agents in thread.
  priority?:  number  // Inbox priority.
}
Example
{
  "kind": "kind",
  "text": "text",
  "payload": null,
  "source": "source",
  "agentId": "agentId",
  "priority": 0
}
Response type
{
  injected:  boolean
  threadId:  string
  inboxItemIds:  string[]
  agentIds:  string[]
}
Example
{
  "injected": false,
  "threadId": "threadId",
  "inboxItemIds": [],
  "agentIds": []
}
Request
curl -X POST https://api.kami.bot/api/threads/{id}/stimulus \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "kind",
    "text": "text",
    "payload": null,
    "source": "source",
    "agentId": "agentId",
    "priority": 0
  }'
post/threads/{id}/testAsk the agent a test question (grounded path, side-effect-free)
Path parameters
idrequiredstringThread ID.
Body type
{
  question:  string  // The test question to ask the agent.
}
Example
{
  "question": "question"
}
Response type
{
  answer:  string  // The agent's answer.
  sources?:  string[]  // Knowledge sources the agent cited.
  usedWebSearch?:  boolean  // Whether web_search was used.
}
Example
{
  "answer": "answer",
  "sources": [],
  "usedWebSearch": false
}
Request
curl -X POST https://api.kami.bot/api/threads/{id}/test \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "question"
  }'
post/threads/{id}/agentsAdd agent to thread
Path parameters
idrequiredstringThread ID.
Body type
{
  agentId:  string  // Agent ID to add to thread.
}
Example
{
  "agentId": "agentId"
}
Response type
{
  added:  boolean
  canonicalId:  string
}
Example
{
  "added": false,
  "canonicalId": "canonicalId"
}
Request
curl -X POST https://api.kami.bot/api/threads/{id}/agents \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "agentId"
  }'
delete/threads/{id}/agents/{agentId}Remove agent from thread
Path parameters
idrequiredstringThread ID.
agentIdrequiredstringAgent ID.
Response type
{
  removed:  boolean
}
Example
{
  "removed": false
}
Request
curl -X DELETE https://api.kami.bot/api/threads/{id}/agents/{agentId} \
  -H "Authorization: Bearer $API_KEY"
get/threads/{id}/agendaAgent beats & scheduled tasks in this scope
Path parameters
idrequiredstringThread ID.
Response type
{
  threadId:  string
  items:  object[]
}
Example
{
  "threadId": "threadId",
  "items": []
}
Request
curl -X GET https://api.kami.bot/api/threads/{id}/agenda \
  -H "Authorization: Bearer $API_KEY"
post/threads/{id}/agendaSchedule a recurring beat in this scope
Path parameters
idrequiredstringThread ID.
Body type
{
  instruction:  string
  cron:  string  // 5-field cron, e.g. "0 9 * * *" for daily at 09:00.
  timezone?:  string  // IANA timezone for the cron; defaults to UTC.
}
Example
{
  "instruction": "instruction",
  "cron": "cron",
  "timezone": "timezone"
}
Request
curl -X POST https://api.kami.bot/api/threads/{id}/agenda \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "instruction": "instruction",
    "cron": "cron",
    "timezone": "timezone"
  }'
delete/threads/{id}/agenda/{itemId}Remove a beat from this scope
Path parameters
idrequiredstring
itemIdrequiredstring
Response type
{
  deleted:  boolean
}
Example
{
  "deleted": false
}
Request
curl -X DELETE https://api.kami.bot/api/threads/{id}/agenda/{itemId} \
  -H "Authorization: Bearer $API_KEY"
get/threads/{id}/adminsWho admins the agent in this scope
Path parameters
idrequiredstringThread ID.
Response type
{
  threadId:  string
  admins:  object[]
}
Example
{
  "threadId": "threadId",
  "admins": []
}
Request
curl -X GET https://api.kami.bot/api/threads/{id}/admins \
  -H "Authorization: Bearer $API_KEY"
get/threads/{id}/activityWhat the agent considered & did in this scope
Path parameters
idrequiredstringThread ID.
Response type
{
  threadId:  string
  events:  object[]
}
Example
{
  "threadId": "threadId",
  "events": []
}
Request
curl -X GET https://api.kami.bot/api/threads/{id}/activity \
  -H "Authorization: Bearer $API_KEY"
get/threads/{id}/rolesPlatform roles assignable in this scope (for the role whitelist)
Path parameters
idrequiredstringThread ID.
Response type
{
  threadId:  string
  roles:  object[]
}
Example
{
  "threadId": "threadId",
  "roles": []
}
Request
curl -X GET https://api.kami.bot/api/threads/{id}/roles \
  -H "Authorization: Bearer $API_KEY"
messages
get/threads/{id}/messagesGet thread messages (paginated)
Path parameters
idrequiredstringThread ID.
Response type
{
  threadId:  string
  messages:  object[]
  hasMore:  boolean
}
Example
{
  "threadId": "threadId",
  "messages": [],
  "hasMore": false
}
Request
curl -X GET https://api.kami.bot/api/threads/{id}/messages \
  -H "Authorization: Bearer $API_KEY"
post/threads/{id}/messagesSend message (sync or stream)
Path parameters
idrequiredstringThread ID.
Response - text/event-stream
data: {"type": "token", "text": "Hello"}
data: {"type": "done", "response": "Hello there", "responseType": "reply"}
data: {"type": "error", "message": "..."}
: heartbeat
Request
curl -X POST https://api.kami.bot/api/threads/{id}/messages \
  -H "Authorization: Bearer $API_KEY"
post/threads/{id}/cancelCancel active LLM response
Path parameters
idrequiredstringThread ID.
Response type
{
  cancelled:  boolean
}
Example
{
  "cancelled": false
}
Request
curl -X POST https://api.kami.bot/api/threads/{id}/cancel \
  -H "Authorization: Bearer $API_KEY"
get/threads/{id}/streamSSE event stream

Server-Sent Events stream for real-time thread events. Optional ?since= for replay.

Path parameters
idrequiredstringThread ID.
Request
curl -X GET https://api.kami.bot/api/threads/{id}/stream \
  -H "Authorization: Bearer $API_KEY"
post/threads/{id}/uploadUpload a file for this thread (any type)
Path parameters
idrequiredstring
Response type
{
  url:  string
  type:  string
  mimeType:  string
  filename:  string
  size:  number
}
Example
{
  "url": "url",
  "type": "type",
  "mimeType": "mimeType",
  "filename": "filename",
  "size": 0
}
Request
curl -X POST https://api.kami.bot/api/threads/{id}/upload \
  -H "Authorization: Bearer $API_KEY"
get/media/{key}Serve an uploaded file
Path parameters
keyrequiredstring
Request
curl -X GET https://api.kami.bot/api/media/{key} \
  -H "Authorization: Bearer $API_KEY"
members
get/threads/{id}/usersList thread members
Path parameters
idrequiredstringThread ID.
Response type
{
  threadId:  string
  users:  object[]
}
Example
{
  "threadId": "threadId",
  "users": []
}
Request
curl -X GET https://api.kami.bot/api/threads/{id}/users \
  -H "Authorization: Bearer $API_KEY"
get/threads/{id}/users/{userId}Member detail + notes
Path parameters
idrequiredstringThread ID.
userIdrequiredstringUser entity ID.
Response type
{
  threadId:  string
  userId:  string
  profile:  object
  profileNotes:  string
  notes:  string
  monthlyArc:  object[]
}
Example
{
  "threadId": "threadId",
  "userId": "userId",
  "profile": null,
  "profileNotes": "profileNotes",
  "notes": "notes",
  "monthlyArc": []
}
Request
curl -X GET https://api.kami.bot/api/threads/{id}/users/{userId} \
  -H "Authorization: Bearer $API_KEY"
get/threads/{id}/contextPrivacy context inspector
Path parameters
idrequiredstringThread ID.
Response type
{
  threadId:  string
  agentId:  string
  memberCount:  number
  members:  object[]
  privacy:  object
  notes:  object
}
Example
{
  "threadId": "threadId",
  "agentId": "agentId",
  "memberCount": 0,
  "members": [],
  "privacy": null,
  "notes": null
}
Request
curl -X GET https://api.kami.bot/api/threads/{id}/context \
  -H "Authorization: Bearer $API_KEY"
get/threads/{id}/memoryThread digests
Path parameters
idrequiredstringThread ID.
Response type
{
  threadId:  string
  digests:  object[]
}
Example
{
  "threadId": "threadId",
  "digests": []
}
Request
curl -X GET https://api.kami.bot/api/threads/{id}/memory \
  -H "Authorization: Bearer $API_KEY"
get/threads/{id}/catch-me-upWhat the caller missed since they were last active here
Path parameters
idrequiredstringThread ID.
Response type
{
  threadId:  string
  lastActiveAt:  number
  missed:  object[]
}
Example
{
  "threadId": "threadId",
  "lastActiveAt": 0,
  "missed": []
}
Request
curl -X GET https://api.kami.bot/api/threads/{id}/catch-me-up \
  -H "Authorization: Bearer $API_KEY"
knowledge
post/threads/{id}/knowledgeAdd thread knowledge
Path parameters
idrequiredstringThread ID.
Body type
{
  name:  string  // Knowledge item name.
  content?:  string  // Knowledge content. Optional for url sources (the daemon fetches the page).
  agentId?:  string  // Override agent for knowledge scope.
  sourceType?:  "url" | "text" | "file" | "learned" | "observed" | "skill" | "builtin"  // Source type.
  sourceUrl?:  string  // Source URL (required for url sources without content).
  summary?:  string  // Short summary.
}
Example
{
  "name": "name",
  "content": "content",
  "agentId": "agentId",
  "sourceType": "sourceType",
  "sourceUrl": "sourceUrl",
  "summary": "summary"
}
Request
curl -X POST https://api.kami.bot/api/threads/{id}/knowledge \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "name",
    "content": "content",
    "agentId": "agentId",
    "sourceType": "sourceType",
    "sourceUrl": "sourceUrl",
    "summary": "summary"
  }'
get/threads/{id}/knowledgeList thread knowledge
Path parameters
idrequiredstringThread ID.
Response type
{
  threadId:  string
  knowledge:  object[]
}
Example
{
  "threadId": "threadId",
  "knowledge": []
}
Request
curl -X GET https://api.kami.bot/api/threads/{id}/knowledge \
  -H "Authorization: Bearer $API_KEY"
post/threads/{id}/knowledge/fileUpload a knowledge file (multipart)
Path parameters
idrequiredstringThread ID.
Request
curl -X POST https://api.kami.bot/api/threads/{id}/knowledge/file \
  -H "Authorization: Bearer $API_KEY"
delete/knowledge/{id}Delete knowledge item
Path parameters
idrequiredstringKnowledge item ID.
Response type
{
  deleted:  boolean
}
Example
{
  "deleted": false
}
Request
curl -X DELETE https://api.kami.bot/api/knowledge/{id} \
  -H "Authorization: Bearer $API_KEY"
patch/knowledge/{id}Update knowledge item
Path parameters
idrequiredstringKnowledge item ID.
Body type
{
  content?:  string  // New full content.
  summary?:  string  // New short summary.
}
Example
{
  "content": "content",
  "summary": "summary"
}
Response type
{
  id:  string
  updated:  boolean
}
Example
{
  "id": "id",
  "updated": false
}
Request
curl -X PATCH https://api.kami.bot/api/knowledge/{id} \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "content",
    "summary": "summary"
  }'
entities
get/entitiesSearch entities
Response type
{
  entities:  object[]
}
Example
{
  "entities": []
}
Request
curl -X GET https://api.kami.bot/api/entities \
  -H "Authorization: Bearer $API_KEY"
get/entities/{id}Entity detail
Path parameters
idrequiredstringEntity ID.
Response type
{
  id:  string
  name:  string
  aliases:  object[]
  memory:  object
}
Example
{
  "id": "id",
  "name": "name",
  "aliases": [],
  "memory": null
}
Request
curl -X GET https://api.kami.bot/api/entities/{id} \
  -H "Authorization: Bearer $API_KEY"
get/entities/{id}/threadsEntity's threads
Path parameters
idrequiredstringEntity ID.
Response type
{
  threads:  object[]
}
Example
{
  "threads": []
}
Request
curl -X GET https://api.kami.bot/api/entities/{id}/threads \
  -H "Authorization: Bearer $API_KEY"
post/entities/linkLink/merge two entities
Body type
{
  code?:  string  // Link code from a link token.
  sourceEntity?:  string  // Source entity ID for direct merge.
  targetEntity?:  string  // Target entity ID for direct merge.
}
Example
{
  "code": "code",
  "sourceEntity": "sourceEntity",
  "targetEntity": "targetEntity"
}
Response type
{
  mergedEntityId:  string
  aliasCount:  number
}
Example
{
  "mergedEntityId": "mergedEntityId",
  "aliasCount": 0
}
Request
curl -X POST https://api.kami.bot/api/entities/link \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "code",
    "sourceEntity": "sourceEntity",
    "targetEntity": "targetEntity"
  }'
users
get/users/{id}Global user profile
Path parameters
idrequiredstringUser entity ID.
Response type
{
  userId:  string
  profile:  object
  profileNotes:  string
  globalNotes:  string
  memory:  object[]
}
Example
{
  "userId": "userId",
  "profile": null,
  "profileNotes": "profileNotes",
  "globalNotes": "globalNotes",
  "memory": []
}
Request
curl -X GET https://api.kami.bot/api/users/{id} \
  -H "Authorization: Bearer $API_KEY"
post/users/linkLink accounts (admin merge)
Body type
{
  keepId:  string  // Entity ID to keep.
  mergeId:  string  // Entity ID to merge into keepId.
}
Example
{
  "keepId": "keepId",
  "mergeId": "mergeId"
}
Response type
{
  merged:  boolean
  keepId:  string
  mergedId:  string
  operationId:  string
}
Example
{
  "merged": false,
  "keepId": "keepId",
  "mergedId": "mergedId",
  "operationId": "operationId"
}
Request
curl -X POST https://api.kami.bot/api/users/link \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "keepId": "keepId",
    "mergeId": "mergeId"
  }'
me
get/meCurrent user profile + threads
Response type
{
  entityId:  string
  displayName:  string
  isAnonymous:  boolean
  agentId:  string
  threads:  object[]
  aliases:  object[]
}
Example
{
  "entityId": "entityId",
  "displayName": "displayName",
  "isAnonymous": false,
  "agentId": "agentId",
  "threads": [],
  "aliases": []
}
Request
curl -X GET https://api.kami.bot/api/me \
  -H "Authorization: Bearer $API_KEY"
get/me/agentsAgents the current user has talked to or created

Session-scoped. Each agent appears once with a role + lastActiveAt.

Response type
{
  agents:  object[]
}
Example
{
  "agents": []
}
Request
curl -X GET https://api.kami.bot/api/me/agents \
  -H "Authorization: Bearer $API_KEY"
post/me/agentsCreate your own agent

Session-gated. Mints a living agent owned by the caller (createdBy), unlisted, with a unique slug derived from the name. Capped per user.

Body type
{
  name:  string  // Display name.
  personality?:  string  // The LLM persona (free text). Optional - falls back to a generic character.
  description?:  string  // One-line tagline for hub cards.
}
Example
{
  "name": "name",
  "personality": "personality",
  "description": "description"
}
Request
curl -X POST https://api.kami.bot/api/me/agents \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "name",
    "personality": "personality",
    "description": "description"
  }'
post/me/agents/previewPreview an unsaved draft agent

Stateless single-turn chat with an unsaved persona (name + personality). Anonymous sessions allowed; hard-capped per session and globally. Creates no agent, chat, or memory.

Body type
{
  name:  string  // Draft display name.
  personality?:  string  // The draft persona (free text). Falls back to the default character.
  history?:  object[]  // Prior turns of this preview chat (most recent kept).
  message:  string  // The visitor's message to the draft.
}
Example
{
  "name": "name",
  "personality": "personality",
  "history": [],
  "message": "message"
}
Response type
{
  reply:  string
}
Example
{
  "reply": "reply"
}
Request
curl -X POST https://api.kami.bot/api/me/agents/preview \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "name",
    "personality": "personality",
    "history": [],
    "message": "message"
  }'
post/me/recognition-linkMint a recognition link for yourself

Recognized callers mint a single-use, short-TTL recognition token for their own entity. Consumed at POST /sessions/recognize to mint a recognized (identity-only) session. Anonymous callers are refused.

Body type
{
  agentId?:  string  // Agent context for the link's landing page. Defaults to the caller's session agent.
}
Example
{
  "agentId": "agentId"
}
Request
curl -X POST https://api.kami.bot/api/me/recognition-link \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "agentId"
  }'
delete/me/aliasesDisconnect a connected account

Detaches one linked platform account from the caller's entity. Ownership-checked; reversible in the identity event log.

Body type
{
  platform:  string  // The platform/source of the alias (e.g. telegram, discord).
  platformId:  string  // The user's id on that platform (the alias sourceId).
}
Example
{
  "platform": "platform",
  "platformId": "platformId"
}
Response type
{
  ok:  boolean
}
Example
{
  "ok": false
}
Request
curl -X DELETE https://api.kami.bot/api/me/aliases \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "platform",
    "platformId": "platformId"
  }'
get/me/feedNow feed snapshot

What the caller's kamis are doing right now, paired with last-active timestamps. Used by the mobile Now tab cold-load ; /me/feed/stream provides the live updates afterwards.

Response type
object
Example
{}
Request
curl -X GET https://api.kami.bot/api/me/feed \
  -H "Authorization: Bearer $API_KEY"
get/me/feed/streamNow feed live SSE

text/event-stream of Now feed events. Initial snapshot event + per-activity-change activity events + 30s heartbeat comments. Auth via Bearer header or ?token= query param.

Response - text/event-stream
data: {"type": "token", "text": "Hello"}
data: {"type": "done", "response": "Hello there", "responseType": "reply"}
data: {"type": "error", "message": "..."}
: heartbeat
Request
curl -X GET https://api.kami.bot/api/me/feed/stream \
  -H "Authorization: Bearer $API_KEY"
get/me/activityActivity timeline

Newest-first rollup of the agent's authored recaps across every scope the caller belongs to. Powers the consumer Activity surface. Member-gated by construction.

Response type
object
Example
{}
Request
curl -X GET https://api.kami.bot/api/me/activity \
  -H "Authorization: Bearer $API_KEY"
scope
get/scope/{chatId}/streamScope events live SSE

text/event-stream of scope events for the given chatId. The caller must be a member of the chat. Initial ready event on connect, then one event per scope bus publish (utterance, agent_response_started, agent_response_completed). 30s heartbeat comments keep the connection alive through idle-killing proxies. Auth via Bearer header or ?token= query param.

Path parameters
chatIdrequiredstring
Response - text/event-stream
data: {"type": "token", "text": "Hello"}
data: {"type": "done", "response": "Hello there", "responseType": "reply"}
data: {"type": "error", "message": "..."}
: heartbeat
Request
curl -X GET https://api.kami.bot/api/scope/{chatId}/stream \
  -H "Authorization: Bearer $API_KEY"
get/scope/{chatId}/conversationUnified conversation events live SSE

text/event-stream of the unified ConversationEvent for the given scope (chatId). Same membership auth as /stream. Every event arrives as an SSE message event - the client reads data.kind to discriminate (one onmessage handler). 30s heartbeat. Auth via Bearer header or ?token= query param.

Path parameters
chatIdrequiredstring
Response - text/event-stream
data: {"type": "token", "text": "Hello"}
data: {"type": "done", "response": "Hello there", "responseType": "reply"}
data: {"type": "error", "message": "..."}
: heartbeat
Request
curl -X GET https://api.kami.bot/api/scope/{chatId}/conversation \
  -H "Authorization: Bearer $API_KEY"
post/scope/{chatId}/gestureTrigger an agent gesture in a scope

Publishes a gesture scope event so subscribed rendering surfaces play the named animation clip on the agent's avatar. Caller must be a member of the scope.

Path parameters
chatIdrequiredstring
Body type
{
  agentId:  string
  name:  string
}
Example
{
  "agentId": "agentId",
  "name": "name"
}
Response type
{
  ok:  boolean
}
Example
{
  "ok": false
}
Request
curl -X POST https://api.kami.bot/api/scope/{chatId}/gesture \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "agentId",
    "name": "name"
  }'
post/scope/{chatId}/output-modeSet the per-scope output modality (voice|text)

Persists the output-modality preference for the scope. voice makes an incarnated agent speak its reply; text keeps it written. Caller must be a member of the scope. When threadId is provided the override is thread-level (the chat-level value still applies to other topics).

Path parameters
chatIdrequiredstring
Body type
{
  agentId:  string
  mode:  "voice" | "text"
  threadId?:  string
}
Example
{
  "agentId": "agentId",
  "mode": "mode",
  "threadId": "threadId"
}
Response type
{
  ok:  boolean
  mode:  "voice" | "text"
}
Example
{
  "ok": false,
  "mode": "mode"
}
Request
curl -X POST https://api.kami.bot/api/scope/{chatId}/output-mode \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "agentId",
    "mode": "mode",
    "threadId": "threadId"
  }'
get/scope/{chatId}/output-modeRead the per-scope output modality (voice|text|unset)

Returns the STORED output-modality preference for the scope, or null when unset. Used by the web voice/text toggle to hydrate on mount. Caller must be a member of the scope.

Path parameters
chatIdrequiredstring
Query parameters
agentIdrequiredstring
threadIdstring
Response type
{
  mode:  "voice" | "text" | "null"
}
Example
{
  "mode": "mode"
}
Request
curl -X GET https://api.kami.bot/api/scope/{chatId}/output-mode \
  -H "Authorization: Bearer $API_KEY"
show
get/show/{scope}/episodesPublic journal: what ran on a show, when, and who was there
Response type
{
  scope:  string
  windowMinutes:  number
  episodes:  object[]
}
Example
{
  "scope": "scope",
  "windowMinutes": 0,
  "episodes": []
}
Request
curl -X GET https://api.kami.bot/api/show/{scope}/episodes \
  -H "Authorization: Bearer $API_KEY"
gatherings
get/gatherings/upcomingWhat is coming up, publicly
Response type
{
  gatherings:  object[]
}
Example
{
  "gatherings": []
}
Request
curl -X GET https://api.kami.bot/api/gatherings/upcoming \
  -H "Authorization: Bearer $API_KEY"
get/gatherings/pastWhat already happened, publicly
Response type
{
  gatherings:  object[]
}
Example
{
  "gatherings": []
}
Request
curl -X GET https://api.kami.bot/api/gatherings/past \
  -H "Authorization: Bearer $API_KEY"
get/gatherings/{id}One gathering by its shareable link
Response type
{
  id:  string
  title:  string
  host:  string
  startsAt:  number
  endAt:  number
  venue:  object
  hasRecording:  boolean
  recordingUrl?:  string
  timing:  "upcoming" | "live" | "past"
  audience:  number
}
Example
{
  "id": "id",
  "title": "title",
  "host": "host",
  "startsAt": 0,
  "endAt": 0,
  "venue": null,
  "hasRecording": false,
  "recordingUrl": "recordingUrl",
  "timing": "timing",
  "audience": 0
}
Request
curl -X GET https://api.kami.bot/api/gatherings/{id} \
  -H "Authorization: Bearer $API_KEY"
admin
get/admin/healthSystem health check
Response type
{
  platforms:  object[]
  llm:  object
  agenda:  object
  objectives:  object
  uptime:  number
  memory:  object
}
Example
{
  "platforms": [],
  "llm": null,
  "agenda": null,
  "objectives": null,
  "uptime": 0,
  "memory": null
}
Request
curl -X GET https://api.kami.bot/api/admin/health \
  -H "Authorization: Bearer $API_KEY"
get/admin/health/agentsPer-agent health rollup
Response type
{
  agents:  object[]
  checkedAt:  number
}
Example
{
  "agents": [],
  "checkedAt": 0
}
Request
curl -X GET https://api.kami.bot/api/admin/health/agents \
  -H "Authorization: Bearer $API_KEY"
get/admin/costsLLM cost breakdown
Response type
{
  total:  object
  breakdown:  object[]
  period:  string
}
Example
{
  "total": null,
  "breakdown": [],
  "period": "period"
}
Request
curl -X GET https://api.kami.bot/api/admin/costs \
  -H "Authorization: Bearer $API_KEY"
get/admin/spendConsumption rollup: per-agent, per-scope, per-model + over-budget scopes
Response type
{
  period:  string
  total:  object
  byAgent:  object[]
  byScope:  object[]
  byModel:  object[]
  overBudget:  object[]
  watchdog:  object
}
Example
{
  "period": "period",
  "total": null,
  "byAgent": [],
  "byScope": [],
  "byModel": [],
  "overBudget": [],
  "watchdog": null
}
Request
curl -X GET https://api.kami.bot/api/admin/spend \
  -H "Authorization: Bearer $API_KEY"
get/admin/spend-limitsPer-agent hard $ spend caps + the global default + enforcement state
Response type
{
  globalDefaultUsd:  number
  enforcement:  boolean
  limits:  object[]
}
Example
{
  "globalDefaultUsd": 0,
  "enforcement": false,
  "limits": []
}
Request
curl -X GET https://api.kami.bot/api/admin/spend-limits \
  -H "Authorization: Bearer $API_KEY"
post/admin/spend-limitsSet (or clear, with dailyCapUsd <= 0) an agent's hard $ cap
Body type
{
  agentId:  string
  dailyCapUsd:  number
}
Example
{
  "agentId": "agentId",
  "dailyCapUsd": 0
}
Response type
{
  globalDefaultUsd:  number
  enforcement:  boolean
  limits:  object[]
}
Example
{
  "globalDefaultUsd": 0,
  "enforcement": false,
  "limits": []
}
Request
curl -X POST https://api.kami.bot/api/admin/spend-limits \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "agentId",
    "dailyCapUsd": 0
  }'
get/admin/errorsRecent errors
Response type
{
  errors:  object[]
}
Example
{
  "errors": []
}
Request
curl -X GET https://api.kami.bot/api/admin/errors \
  -H "Authorization: Bearer $API_KEY"
get/admin/chatsAll chats overview
Response type
{
  chats:  object[]
  pagination:  object
}
Example
{
  "chats": [],
  "pagination": null
}
Request
curl -X GET https://api.kami.bot/api/admin/chats \
  -H "Authorization: Bearer $API_KEY"
get/admin/objectivesActive objectives
Response type
{
  objectives:  object[]
}
Example
{
  "objectives": []
}
Request
curl -X GET https://api.kami.bot/api/admin/objectives \
  -H "Authorization: Bearer $API_KEY"
get/admin/agendaScheduled items
Response type
{
  items:  object[]
  pagination:  object
}
Example
{
  "items": [],
  "pagination": null
}
Request
curl -X GET https://api.kami.bot/api/admin/agenda \
  -H "Authorization: Bearer $API_KEY"
get/admin/tracesRecent LLM traces
Response type
{
  traces:  object[]
  pagination:  object
}
Example
{
  "traces": [],
  "pagination": null
}
Request
curl -X GET https://api.kami.bot/api/admin/traces \
  -H "Authorization: Bearer $API_KEY"
get/admin/scene-timelineMerged content+cost timeline for a scope, with health signals
Response type
{
  scope:  string
  health:  object
  entries:  object[]
}
Example
{
  "scope": "scope",
  "health": null,
  "entries": []
}
Request
curl -X GET https://api.kami.bot/api/admin/scene-timeline \
  -H "Authorization: Bearer $API_KEY"
get/admin/episodesA scope's activity cut into episodes (when, who, how many beats, what it cost)
Response type
{
  scope:  string
  windowMinutes:  number
  gapMinutes:  number
  episodes:  object[]
}
Example
{
  "scope": "scope",
  "windowMinutes": 0,
  "gapMinutes": 0,
  "episodes": []
}
Request
curl -X GET https://api.kami.bot/api/admin/episodes \
  -H "Authorization: Bearer $API_KEY"
get/admin/floor/{id}Speaking-floor live state for a chat
Path parameters
idrequiredstringChat ID.
Response type
{
  layerBEnabled:  boolean
  chatId:  string
  scopes:  object[]
}
Example
{
  "layerBEnabled": false,
  "chatId": "chatId",
  "scopes": []
}
Request
curl -X GET https://api.kami.bot/api/admin/floor/{id} \
  -H "Authorization: Bearer $API_KEY"
get/admin/gatheringsThe whole calendar, private entries included
Response type
{
  gatherings:  object[]
}
Example
{
  "gatherings": []
}
Request
curl -X GET https://api.kami.bot/api/admin/gatherings \
  -H "Authorization: Bearer $API_KEY"
post/admin/gatheringsSchedule a gathering (private unless asked otherwise)
Body type
{
  title:  string
  hostAgentId:  string
  startsAt:  number
  endAt?:  number
  venue?:  object
  visibility?:  "private" | "public"
}
Example
{
  "title": "title",
  "hostAgentId": "hostAgentId",
  "startsAt": 0,
  "endAt": 0,
  "venue": null,
  "visibility": "visibility"
}
Response type
{
  id:  string
  title:  string
  host:  string
  startsAt:  number
  endAt:  number
  venue:  object
  visibility:  "private" | "public"
  hasRecording:  boolean
  timing:  "upcoming" | "live" | "past"
  audience:  number
}
Example
{
  "id": "id",
  "title": "title",
  "host": "host",
  "startsAt": 0,
  "endAt": 0,
  "venue": null,
  "visibility": "visibility",
  "hasRecording": false,
  "timing": "timing",
  "audience": 0
}
Request
curl -X POST https://api.kami.bot/api/admin/gatherings \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "title",
    "hostAgentId": "hostAgentId",
    "startsAt": 0,
    "endAt": 0,
    "venue": null,
    "visibility": "visibility"
  }'
post/admin/gatherings/{id}/visibilityPublish a gathering, or take it back private
Body type
{
  visibility:  "private" | "public"
}
Example
{
  "visibility": "visibility"
}
Response type
{
  id:  string
  title:  string
  host:  string
  startsAt:  number
  endAt:  number
  venue:  object
  visibility:  "private" | "public"
  hasRecording:  boolean
  timing:  "upcoming" | "live" | "past"
  audience:  number
}
Example
{
  "id": "id",
  "title": "title",
  "host": "host",
  "startsAt": 0,
  "endAt": 0,
  "venue": null,
  "visibility": "visibility",
  "hasRecording": false,
  "timing": "timing",
  "audience": 0
}
Request
curl -X POST https://api.kami.bot/api/admin/gatherings/{id}/visibility \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "visibility": "visibility"
  }'
post/admin/gatherings/{id}/recordingAttach (or clear, with null) the gathering's recording artifact
Body type
{
  recordingRef:  string
}
Example
{
  "recordingRef": "recordingRef"
}
Response type
{
  id:  string
  title:  string
  host:  string
  startsAt:  number
  endAt:  number
  venue:  object
  visibility:  "private" | "public"
  hasRecording:  boolean
  timing:  "upcoming" | "live" | "past"
  audience:  number
}
Example
{
  "id": "id",
  "title": "title",
  "host": "host",
  "startsAt": 0,
  "endAt": 0,
  "venue": null,
  "visibility": "visibility",
  "hasRecording": false,
  "timing": "timing",
  "audience": 0
}
Request
curl -X POST https://api.kami.bot/api/admin/gatherings/{id}/recording \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "recordingRef": "recordingRef"
  }'
get/chats/{id}/messagesAdmin message viewer
Path parameters
idrequiredstringChat ID.
Response type
{
  chatId:  string
  messages:  object[]
  pagination:  object
}
Example
{
  "chatId": "chatId",
  "messages": [],
  "pagination": null
}
Request
curl -X GET https://api.kami.bot/api/chats/{id}/messages \
  -H "Authorization: Bearer $API_KEY"
get/traces/{id}Single trace detail
Path parameters
idrequiredstringTrace ID.
Response type
object
Example
{}
Request
curl -X GET https://api.kami.bot/api/traces/{id} \
  -H "Authorization: Bearer $API_KEY"