Боты 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, чтобы не утёк в логи):
# 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-конверт:
{ "ok": true, "result": … }
{ "ok": false, "error": "reason" }Быстрая проверка, что бот жив:
curl -H "Authorization: Bearer kbot_0a1b…" \
https://api.koto.run/getMe
# {"ok":true,"result":{"id":"bot-…","username":"mybot","is_bot":true}}Отправить сообщение:
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:
#!/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 | Параметры | Результат |
|---|---|---|---|
getMe | GET | — | { id, username, is_bot } |
getUpdates | GET | ?offset= &timeout= &limit= | массив Update |
getChat | GET | ?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_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_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, чтобы ответить на нажатие.
Мини-приложения
Мини-приложение — это веб-страница, которую бот открывает внутри чата Koto. Пользователь жмёт кнопку приложения (▦) рядом с полем ввода, страница грузится в песочнице и может общаться с ботом. URL обязан быть HTTPS.
Указать URL мини-приложения
Через клиент Koto (бот → Mini App → вставить URL) или через реестр с управляющим токеном бота:
PUT /v1/bots/<token>/webapp {"url": "https://example.com/app"}Мост KotoWebApp
<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, мы их не дублируем.