Skip to content

API Reference

All endpoints are relative to https://api.worken.ru. Every request must include:

Authorization: Bearer sk-your-api-key
Content-Type: application/json   (for POST / PATCH)

Bots

Bots (also called virts) are AI agents that handle conversations.

Types

typescript
type BotStatus = 'active' | 'disabled' | 'error'

type Bot = {
  id: string
  name: string
  description: string | null
  status: BotStatus
  project_id: string
  created_at: string
  updated_at: string
}

type BotSettings = {
  ai: {
    instruction: string
    model: {
      id: string           // e.g. "openai/gpt-4o-mini"
      temperature: number  // 0.0–2.0
      max_tokens: number
      top_p: number
      frequency_penalty: number
      presence_penalty: number
    }
    memory: {
      lastMessages: number
      semanticRecall: boolean
      workingMemory: { enabled: boolean }
      generateTitle: boolean
    }
    formatting: {
      removeEmojis: boolean
      removeMarkdown: boolean
    }
    tools: Record<string, 'user_approve' | 'operator_approve' | 'auto'>
  }
}

List bots

GET /bots

Returns all bots in the current project.

Response 200

typescript
type ListBotsResponse = Bot[]

Create a bot

POST /bots

Body

typescript
type CreateBotBody = {
  name: string
}

Response 200

typescript
type CreateBotResponse = Bot

Example

sh
curl https://api.worken.ru/bots \
  -X POST \
  -H "Authorization: Bearer sk-..." \
  -H "Content-Type: application/json" \
  -d '{"name": "Sales Bot"}'

Get a bot

GET /bots/:bot_id

Response 200Bot


Update a bot

POST /bots/:bot_id

Body

typescript
type UpdateBotBody = {
  name?: string
  description?: string
}

Response 200Bot


Update bot status

POST /bots/:bot_id/status

Body

typescript
type SetBotStatusBody = {
  status: BotStatus
}

Get bot settings

GET /bots/:bot_id/settings

Response 200BotSettings


Update bot settings

POST /bots/:bot_id/settings

Partial updates are supported — only the provided fields are changed.

Body — partial BotSettings

Example — update model and instruction

sh
curl https://api.worken.ru/bots/${BOT_ID}/settings \
  -X POST \
  -H "Authorization: Bearer sk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "ai": {
      "instruction": "You are a sales assistant. Focus on product benefits.",
      "model": { "id": "openai/gpt-4o", "temperature": 0.7 }
    }
  }'

Clone a bot

POST /bots/:bot_id/clone

Creates a new bot with identical settings. Useful for A/B testing configurations.

Response 200Bot


Delete a bot

POST /bots/:bot_id/delete

Response 200


Chats

A chat is a channel through which users reach a bot — a Telegram group, a website widget, a WhatsApp inbox, etc.

Types

typescript
type ChatStatus = 'active' | 'disabled' | 'error'

type Chat = {
  id: string
  name: string
  bot_id: string
  integration_id: string | null
  status: ChatStatus
  project_id: string
  created_at: string
  updated_at: string
  events_24h: number  // message events in last 24 hours
}

List chats

GET /chats

Response 200

typescript
type ListChatsResponse = Chat[]

Get a chat

GET /chats/:chat_id

Response 200Chat


List threads in a chat

GET /chats/:chat_id/threads

Response 200

typescript
type Thread = {
  id: string
  chat_id: string
  bot_id: string
  mode: 'auto' | 'manual' | 'operator' | 'blocked'
  title: string | null
  last_message_at: string | null
  pending_count: number
  created_at: string
}

type ListThreadsResponse = Thread[]

Stream a response (SSE)

Send a new user message and receive the AI response as a Server-Sent Events stream.

POST /chats/:chat_id/threads/:thread_id/stream

Body

typescript
type StreamBody = {
  messages: Array<{
    role: 'user'
    content: string
  }>
  scheduledAt?: string  // ISO 8601 — defer the response
}

Responsetext/event-stream (Vercel AI SDK data stream v2)

typescript
// Events emitted during streaming
type StreamEvent =
  | { type: 'text-delta'; textDelta: string }
  | { type: 'tool-call'; toolName: string; args: unknown }
  | { type: 'tool-result'; toolName: string; result: unknown }
  | { type: 'finish'; finishReason: 'stop' | 'tool-calls' | 'length' }

Example — using the SDK

typescript
const stream = await worken.chats.threads.stream(chatId, threadId, {
  messages: [{ role: 'user', content: 'What is your return policy?' }],
})

for await (const chunk of stream) {
  process.stdout.write(chunk.textDelta ?? '')
}

Get thread messages

GET /chats/:chat_id/threads/:thread_id/messages

Returns the full message history from the agent's memory.

Response 200

typescript
type Message = {
  id: string
  role: 'user' | 'assistant' | 'tool'
  content: string
  created_at: string
}

type GetMessagesResponse = Message[]

Delete a thread

POST /chats/:chat_id/threads/:thread_id/delete

Removes the thread and its messages from memory.


Set thread mode

POST /chats/:chat_id/threads/:thread_id/mode

Body

typescript
type SetThreadModeBody = {
  mode: 'auto' | 'manual' | 'operator' | 'blocked'
}
ModeBehaviour
autoAI handles all replies
manualOperator sends replies, AI is paused
operatorOperator is composing; AI is paused
blockedNo replies sent

Threads

The /threads endpoint gives a project-wide view across all chats.

List threads

GET /threads

Query parameters

ParameterTypeDescription
chat_idstringFilter by chat
bot_idstringFilter by bot
searchstringFull-text search in messages
limitnumberMax results (default 20)
offsetnumberPagination offset
cursorstringCursor for real-time pagination

Response 200

typescript
type ListThreadsResponse = {
  data: Thread[]
  next_cursor: string | null
}

Get a thread

GET /threads/:thread_id

Response 200

typescript
type ThreadDetail = Thread & {
  person: {
    id: string
    name: string | null
    avatar_url: string | null
    external_id: string | null
  } | null
  stats: {
    messages_total: number
    user_messages: number
    bot_messages: number
  }
}

Send an operator message

POST /threads/:thread_id/send

Send a message as a human operator. The thread must be in manual mode.

Body

typescript
type SendMessageBody = {
  text: string
  scheduledAt?: string  // defer delivery — ISO 8601
}

Get working memory

GET /threads/:thread_id/memory

Returns the agent's current working memory for this thread — extracted facts the model retains across turns.

Response 200

typescript
type WorkingMemoryResponse = {
  content: string | null  // Markdown-formatted memory block
}

Real-time events (SSE)

Subscribe to live updates for all threads in the project:

GET /threads/events

Or for a single thread:

GET /threads/events/:thread_id

Event format

typescript
type ThreadEvent = {
  thread_id: string
  type: 'pending_count' | 'mode_changed' | 'message_created'
  pending_count?: number
  mode?: string
}

Example

typescript
const eventSource = new EventSource(
  'https://api.worken.ru/threads/events',
  { headers: { Authorization: `Bearer ${apiKey}` } }
)

eventSource.onmessage = (event) => {
  const data = JSON.parse(event.data) as ThreadEvent
  console.log(`Thread ${data.thread_id} has ${data.pending_count} pending messages`)
}

Integrations

Integrations connect your bots to external platforms.

Types

typescript
type IntegrationVendor =
  | 'telegram' | 'whatsapp' | 'vk' | 'ok' | 'max'
  | 'github' | 'google' | 'yandex'
  | 'amocrm' | 'bitrix' | 'avito'
  | 'sber' | 'worken'

type IntegrationStatus = 'active' | 'disabled' | 'error'

type Integration = {
  id: string
  name: string
  vendor: IntegrationVendor
  status: IntegrationStatus
  project_id: string
  created_at: string
  updated_at: string
}

List integrations

GET /integrations

Response 200Integration[]


Create an integration

POST /integrations

Body

typescript
type CreateIntegrationBody = {
  name: string
  vendor: IntegrationVendor
  auth_data: Record<string, unknown>  // vendor-specific credentials
}

Examples by vendor

typescript
// Telegram — bot token
{ vendor: 'telegram', auth_data: { token: '7123456789:AAH...' } }

// amoCRM — OAuth (after getting tokens via /integrations/:id/oauth/start)
{ vendor: 'amocrm', auth_data: { subdomain: 'mycompany' } }

// VK Communities — group access token
{ vendor: 'vk', auth_data: { access_token: 'vk1.a...' } }

Get an integration

GET /integrations/:id

Response 200Integration


Update an integration

POST /integrations/:id

Body

typescript
type UpdateIntegrationBody = {
  name?: string
  status?: IntegrationStatus
  auth_data?: Record<string, unknown>
  settings?: Record<string, unknown>
}

Delete an integration

DELETE /integrations/:id

Get integration profile

GET /integrations/:id/profile

Verifies that the stored credentials are valid and returns the authenticated identity (e.g. bot username for Telegram, account email for Google).

Response 200

typescript
type IntegrationProfile = {
  id: string
  name: string
  username?: string
  avatar_url?: string
}

OAuth flow

Start OAuth for integrations that use it (amoCRM, Bitrix24, Google, etc.):

POST /integrations/:id/oauth/start

Response 200

typescript
type OAuthStartResponse = {
  url: string  // redirect the user here
}

After the user authorises, the platform redirects back and credentials are saved automatically.


Manage integration chats

typescript
// List chats for this integration
GET  /integrations/:id/chats

// Create a new chat
POST /integrations/:id/chats
// body: { bot_id: string, name: string, settings?: object }

// Update a chat
POST /integrations/:id/chats/:chat_id

// Activate / deactivate
POST /integrations/:id/chats/:chat_id/status
// body: { status: 'active' | 'disabled' }

// Delete
DELETE /integrations/:id/chats/:chat_id

Billing

Types

typescript
type BillingAccount = {
  tariff: string
  credits: number   // main balance in credits
  bonus: number     // promotional credits
  subscription_until: string | null  // ISO 8601
}

type Transaction = {
  id: string
  type: 'charge' | 'topup' | 'bonus' | 'refund'
  amount: number
  description: string
  created_at: string
}

type Invoice = {
  id: string
  status: 'pending' | 'paid' | 'cancelled'
  amount: number
  payment_url: string | null
  created_at: string
}

Get billing account

GET /billing/account

Response 200BillingAccount


Get balance

GET /billing/balance

Returns current credit and bonus balances:

typescript
type BalanceResponse = {
  credits: number
  bonus: number
}

List transactions

GET /billing/transactions

Query parameterslimit (default 20), offset

Response 200

typescript
type ListTransactionsResponse = {
  data: Transaction[]
  total: number
}

List invoices

GET /billing/invoices

Response 200Invoice[]


Create an invoice (top up balance)

POST /billing/invoices

Body

typescript
type CreateInvoiceBody = {
  offer_id: string
  credits?: number  // custom top-up amount
}

Response 200

typescript
type CreateInvoiceResponse = {
  invoice: Invoice
  payment_url: string
}

List billing offers

GET /billing/offers

Returns available subscription plans and one-time top-up offers:

typescript
type BillingOffer = {
  id: string
  name: string
  price: number
  credits: number
  description: string
}

type ListOffersResponse = BillingOffer[]

Projects & API Keys

List projects

GET /projects

Response 200

typescript
type Project = {
  id: string
  name: string
  organization_id: string
  avatar_url: string | null
  created_at: string
}

type ListProjectsResponse = Project[]

Create a project

POST /projects

Body

typescript
type CreateProjectBody = {
  name: string
  organization_id: string
}

Create an API key

POST /projects/:id/api-keys

Body

typescript
type CreateApiKeyBody = {
  name: string
}

Response 200

typescript
type CreateApiKeyResponse = {
  id: string
  name: string
  key: string  // shown only once — store it securely
  created_at: string
}

List API keys

GET /projects/:id/api-keys

Returns key metadata — the secret value is never returned after creation.

Response 200

typescript
type ApiKey = {
  id: string
  name: string
  last_used_at: string | null
  created_at: string
}

type ListApiKeysResponse = ApiKey[]

Delete an API key

DELETE /projects/:id/api-keys/:key_id

Vector Stores (Knowledge Bases)

Worken provides an OpenAI-compatible Vector Store API for grounding agents in documents.

Types

typescript
type VectorStore = {
  id: string
  name: string
  file_count: number
  status: 'ready' | 'indexing' | 'error'
  created_at: string
}

type VectorStoreFile = {
  id: string
  filename: string
  status: 'processed' | 'pending' | 'error'
  created_at: string
}

Endpoints

typescript
POST   /vector_stores                          // create
GET    /vector_stores                          // list
GET    /vector_stores/:id                      // get
POST   /vector_stores/:id                      // update
DELETE /vector_stores/:id                      // delete
POST   /vector_stores/:id/files               // add file
GET    /vector_stores/:id/files               // list files
GET    /vector_stores/:id/files/:file_id      // get file
DELETE /vector_stores/:id/files/:file_id      // remove file

Webhook Endpoints

Register HTTP endpoints to receive real-time events from Worken.

Types

typescript
type WebhookEndpoint = {
  id: string
  url: string
  status: 'active' | 'disabled'
  created_at: string
}

type WebhookEvent = {
  id: string
  type: string   // e.g. "thread.message.created"
  created_at: string
  data: Record<string, unknown>
}

Endpoints

typescript
GET    /webhook-endpoints         // list
POST   /webhook-endpoints         // create  { url, secret }
PUT    /webhook-endpoints/:id     // update  { status?, secret? }
DELETE /webhook-endpoints/:id     // delete

Event types

EventDescription
thread.createdA new conversation started
thread.message.createdNew message in a thread
thread.mode.changedThread switched to manual / auto
integration.auth_lostIntegration credentials expired
billing.balance.lowCredits balance below threshold

Signature verification

Worken signs each webhook request with an HMAC-SHA256 signature using your secret:

typescript
import { createHmac } from 'node:crypto'

function verifyWebhook(body: string, signature: string, secret: string): boolean {
  const expected = createHmac('sha256', secret).update(body).digest('hex')
  return expected === signature
}

// In your handler:
app.post('/webhook', (req, res) => {
  const sig = req.headers['x-worken-signature'] as string
  if (!verifyWebhook(req.rawBody, sig, process.env.WORKEN_WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature')
  }
  // process event...
})

Error codes

HTTP statusErrorDescription
400Bad RequestMissing or invalid request body
401UnauthorizedAPI key is missing or invalid
403ForbiddenKey does not have access to this resource
404Not FoundResource does not exist
409ConflictResource already exists (e.g. duplicate chat)
422Unprocessable EntityValidation failed — see message for details
429Too Many RequestsRate limit exceeded — see Retry-After header
500Internal Server ErrorServer error — contact support

Руководство пользователя Worken AI