Документация · Bot API

Боты Koto на любом языке

Простой HTTP-API. Вы шлёте обычный HTTP + JSON; шлюз Koto держит E2E-идентичность бота и его инбокс, расшифровывает входящие и переводит ваши вызовы в зашифрованные операции Koto. Криптографию вы не трогаете.

Обзор

API устроен по знакомой схеме: метод задаётся путём, токен едет в заголовке Authorization, а ответ — JSON-конверт { ok, result }. Никакого SDK не требуется — достаточно уметь делать HTTP-запросы. Формат вызовов совместим с существующими клиентскими библиотеками для Telegram Bot API*, поэтому часто достаточно перенаправить их базовый URL на шлюз Koto.

Поток простой: создаёте бота в @BotKoto и получаете токен → вызываете методы, передавая токен в заголовке Authorization → получаете апдейты через long-poll getUpdates или webhook.

* Telegram — товарный знак Telegram Messenger LLP. Koto разработан независимо, не связан с Telegram и не одобрен им; название приводится исключительно для описания совместимости.

1. Создать бота

Откройте @BotKoto в любом клиенте Koto, отправьте /newbot, выберите имя и @username. Вы получите токен вида kbot_0a1b2c…. Держите его в секрете — он управляет ботом.

2. Вызвать API

Метод — это весь путь, а токен едет в заголовке Authorization: Bearer (не в URL, чтобы не утёк в логи):

endpoint
# the method is the whole path; the token rides in a header
{GATEWAY}/{method}
Authorization: Bearer {TOKEN}

# example
curl -H "Authorization: Bearer kbot_0a1b…" \
  https://api.koto.run/getMe

Каждый ответ — JSON-конверт:

envelope
{ "ok": true,  "result":  }
{ "ok": false, "error": "reason" }

Быстрая проверка, что бот жив:

getMe
curl -H "Authorization: Bearer kbot_0a1b…" \
  https://api.koto.run/getMe
# {"ok":true,"result":{"id":"bot-…","username":"mybot","is_bot":true}}

Отправить сообщение:

sendMessage
curl -X POST https://api.koto.run/sendMessage \
  -H "Authorization: Bearer kbot_…" \
  -H 'content-type: application/json' \
  -d '{"chat_id":"KOTO-…","text":"Hello from Koto!"}'

3. Получать апдейты

Два взаимоисключающих способа:

Long-poll getUpdates — тяните апдейты и подтверждайте растущим offset. offset = последний update_id + 1 подтверждает всё, что ниже. getUpdates держит соединение до timeout секунд (по умолчанию 25).

Webhook setWebhook — шлюз сам POST-ит каждый апдейт на ваш URL. Пока webhook установлен, getUpdates возвращает 409.

Пример: эхо-бот

Полноценный бот на чистом bash — только HTTP + JSON, без Koto-SDK и без крипто. Long-poll getUpdates и ответ через sendMessage:

echo.sh
#!/usr/bin/env bash
# A full bot over plain HTTP — no SDK, no crypto. The token rides in an
# Authorization: Bearer header, never the URL.
# Run:  BOT_TOKEN=kbot_xxx ./echo.sh
API="http://127.0.0.1:8090"
AUTH=(-H "Authorization: Bearer $BOT_TOKEN")

offset=0
while true; do
  resp=$(curl -s "${AUTH[@]}" "$API/getUpdates?offset=$offset&timeout=20")
  for upd in $(echo "$resp" | jq -c '.result[]?'); do
    offset=$(( $(jq '.update_id' <<<"$upd") + 1 ))
    chat=$(jq -r '.message.chat.id // ""' <<<"$upd")
    text=$(jq -r '.message.text // ""' <<<"$upd")
    [ -n "$chat" ] && [ -n "$text" ] && \
      curl -s -X POST "${AUTH[@]}" "$API/sendMessage" -H 'content-type: application/json' \
        -d "$(jq -nc --arg c "$chat" --arg t "Echo: $text" '{chat_id:$c,text:$t}')"
  done
done

Методы

chat_id — то, что пришло в message.chat.id апдейта. Идентификаторы сообщений — непрозрачные строки. Успешная отправка возвращает { "message_id": "…" }, void-операция возвращает true.

Чтение

МетодHTTPПараметрыРезультат
getMeGET{ id, username, is_bot }
getUpdatesGET?offset= &timeout= &limit=массив Update
getChatGET?chat_id={ id, type, members }

Отправка и действия

МетодТелоЗаметки
sendMessage{ chat_id, text, reply_markup?, reply_to_message_id? }текст, опц. inline-клавиатура и ответ-цитата
sendPhoto{ chat_id, photo, mime, w, h, caption? }photo — base64 байтов изображения
sendDocument{ chat_id, document, file_name, mime, size }document — base64 файла
editMessageText{ chat_id, message_id, text }изменить текст
editMessageReplyMarkup{ chat_id, message_id, reply_markup }пустой markup убирает клавиатуру
deleteMessage{ chat_id, message_id }удалить
forwardMessage{ chat_id, text, from? }from — подпись «переслано от»
sendPoll{ chat_id, question, options[], is_anonymous? }опрос
pinChatMessage{ chat_id, message_id }закрепить
unpinChatMessage{ chat_id }открепить
setMessageReaction{ chat_id, message_id, emoji, add? }add по умолчанию true
sendChatAction{ chat_id, action? }показывает «печатает…»
answerCallbackQuery{ callback_query_id }no-op ack (в Koto нет спиннера на кнопке)

Меню команд (список «/»)

МетодТелоЗаметки
setMyCommands{ commands: [{ command, description }] }публичный список команд
getMyCommandsтекущий список
deleteMyCommandsочистить

Webhooks

МетодТелоЗаметки
setWebhook{ url, secret_token? }шлюз POST-ит апдейты на url; secret_token возвращается как X-Bot-Webhook-Secret
deleteWebhookобратно на getUpdates
getWebhookInfo{ url, pending_update_count, … }

Объект Update

getUpdates (и тело webhook-POST) возвращают Update. Ровно одно поле полезной нагрузки заполнено на апдейт:

Update
{
  "update_id": 42,
  "message":          {  },   // new incoming message
  "edited_message":   {  },   // a message's text was edited
  "callback_query":   {  },   // inline button press
  "poll_answer":      {  },   // poll vote
  "message_reaction": {  }    // reaction toggled
}

Message

Message
{
  "message_id": "…",
  "date": 1733836800,
  "chat": { "id": "…" },
  "from": { "id": "KOTO-…" },
  "text": "hello",
  "caption": "…",                                  // for a photo/document
  "photo":    { "data": "<base64>", "mime": "image/jpeg", "w": 1280, "h": 720 },
  "document": { "data": "<base64>", "file_name": "…", "mime": "…", "size": 1234 },
  "reply_to_message": {  },                       // if this is a quoted reply
  "forward_from": "Alice",                         // if forwarded
  "reply_markup": [[  ]]                          // attached keyboard
}

callback_query: { id, from, chat, message_id, data } — передайте chat.id в sendMessage, чтобы ответить на нажатие.

Inline-кнопки

reply_markup — это ряды кнопок. Каждая кнопка — { text, data }:

reply_markup
{
  "chat_id": "KOTO-…",
  "text": "Choose an option",
  "reply_markup": [
    [ { "text": "Yes", "data": "y" }, { "text": "No", "data": "n" } ]
  ]
}

Нажатие приходит апдейтом callback_query с полем data нажатой кнопки. На него можно ответить вызовом answerCallbackQuery (в Koto это безобидный ack) и отправить сообщение в chat.id из колбэка.

Мини-приложения

Мини-приложение — это веб-страница, которую бот открывает внутри чата Koto. Пользователь жмёт кнопку приложения (▦) рядом с полем ввода, страница грузится в песочнице и может общаться с ботом. URL обязан быть HTTPS.

Указать URL мини-приложения

Через клиент Koto (бот → Mini App → вставить URL) или через реестр с управляющим токеном бота:

registry
PUT /v1/bots/<token>/webapp     {"url": "https://example.com/app"}

Мост KotoWebApp

index.html
<script src="koto-webapp.js"></script>
<script>
  KotoWebApp.ready();                       // theme + platform from the host
  KotoWebApp.MainButton.setText("Done").show();
  KotoWebApp.MainButton.onClick(function () {
    KotoWebApp.sendData(JSON.stringify({ ok: true }));  // → sent to the bot
  });
</script>
ЧленЧто делает
ready()сообщить хосту, что страница загружена; заполняет themeParams/platform
sendData(string)отправить строку боту, затем приложение закрывается
close() / expand()закрыть / развернуть лист на всю высоту
openLink(url)открыть URL в браузере пользователя
themeParamsцвета хоста (также как CSS-переменные --koto-*)
MainButton.setText .show .hide .enable .disable .onClick
onEvent(name, cb)события: ready, themeChanged, mainButtonClicked

sendData(s) доставляет s боту как обычное входящее сообщение (бот видит его через getUpdates/webhook). Шлите компактный JSON и парсите его в боте.

Лимиты и особенности

  • Рейт-лимит: на бота, по умолчанию 30 запросов/сек → 429 при превышении.
  • Медиа — инлайн base64: шлите байты напрямую в photo / document, без двухшаговой загрузки и file_id.
  • Идентификаторы — это Koto ID (KOTO-… для пользователей, bot-… для ботов), не числовые.
  • End-to-end: сообщения зашифрованы на проводе, слепой релей не видит открытый текст. Шлюз расшифровывает за бота — поэтому оператор бота (и хостящий его шлюз) видят то, что пишут боту. Чаты с ботом не приватны от самого бота. Переписка пользователь↔пользователь это не затрагивает.

Статус возможностей

ВозможностьСтатус
Текст, фото, документ, опросы✅ реализовано
Edit / delete / pin / реакции / forward✅ реализовано
Inline-клавиатуры + нажатия (callback_query)✅ реализовано
Меню команд (setMyCommands)✅ реализовано
getUpdates long-poll и webhooks✅ реализовано
Ответы-цитаты✅ реализовано
Боты в группах/каналах (>2 участников)⚠️ методы работают в группе, где бот уже есть; добавление в группу через Bot API пока не подключено
Inline-режим (@bot … в любом чате)❌ пока не поддерживается
Платежи в боте❌ пока не поддерживается

Хостинг

Большинству ботов хостинг не нужен: вы работаете через управляемый шлюз Koto — достаточно вашего токена kbot_… и публичного базового URL.

Нужен полный контроль над ключами? Шлюз и одиночный коннектор (вы держите ключи бота у себя, тот же API) можно развернуть самостоятельно. Параметры развёртывания и переменные окружения описаны в README репозитория koto-bot — здесь, в публичной справке по API, мы их не дублируем.

Скачать для Windows