Files
featherChat/warzone/docs/BOT_API.md
Siavash Sameni 210fbbb35b feat: bot alias reservation + BOT_API.md documentation
- Aliases ending with Bot/bot/_bot reserved for registered bots only
- Non-bot users get clear error directing to /v1/bot/register
- Bot registration auto-creates alias (@name_bot suffix)
- BOT_API.md: full developer guide with endpoints, examples, echo bot
- LLM_HELP.md: expanded bot section with update types + Python example

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 07:34:45 +04:00

9.5 KiB

featherChat Bot API

Overview

featherChat exposes a Telegram Bot API-compatible HTTP interface, allowing developers to build bots that interact with featherChat users using familiar patterns. Bots register with the server, receive a token, and communicate via long-polling (webhook support is planned).

Key properties of v1:

  • Bot aliases must end with Bot, bot, or _bot (auto-enforced on registration).
  • Bots receive encrypted user messages as base64 blobs (raw_encrypted field). Plaintext bot-to-bot messages are delivered with a readable text field.
  • Bot-sent messages are plaintext (not E2E encrypted) in v1.
  • chat_id values are hex fingerprints (not numeric Telegram-style IDs).

Quick Start

1. Register your bot:
   POST /v1/bot/register
   {"name": "WeatherBot", "fingerprint": "aabbccdd..."}

2. Extract the token from the response.

3. Poll for updates:
   POST /v1/bot/<token>/getUpdates
   {"timeout": 5}

4. Send a reply:
   POST /v1/bot/<token>/sendMessage
   {"chat_id": "<sender_fingerprint>", "text": "Hello!"}

Endpoints

1. Register a Bot

POST /v1/bot/register

Creates a new bot, stores it in the server database, and auto-registers an alias.

Request:

{
  "name": "MyBot",
  "fingerprint": "aabbccdd1122334455667788aabbccdd"
}
Field Type Description
name string Display name. Alias suffix auto-added if needed.
fingerprint string Hex-encoded public key fingerprint for the bot.

Response:

{
  "ok": true,
  "result": {
    "token": "aabbccdd11223344:9f8e7d6c5b4a39281706abcdef012345",
    "name": "MyBot",
    "fingerprint": "aabbccdd1122334455667788aabbccdd",
    "alias": "@mybot_bot"
  }
}

Token format: <first-16-chars-of-fingerprint>:<32-hex-random-bytes>

Alias rules:

  • If the name already ends with Bot, bot, or _bot, the alias is the lowercased name (e.g. WeatherBot -> @weatherbot).
  • Otherwise _bot is appended (e.g. weather -> @weather_bot).
  • The alias is registered in both directions (alias -> fingerprint and fingerprint -> alias).

2. Get Bot Info

GET /v1/bot/:token/getMe

Returns information about the bot in a Telegram-compatible shape.

Response (valid token):

{
  "ok": true,
  "result": {
    "id": "aabbccdd1122334455667788aabbccdd",
    "is_bot": true,
    "first_name": "MyBot",
    "username": "MyBot"
  }
}

Response (invalid token):

{
  "ok": false,
  "description": "invalid token"
}

3. Get Updates (Long-Poll)

POST /v1/bot/:token/getUpdates

Returns queued messages for the bot and deletes them from the queue.

Request:

{
  "timeout": 5
}
Field Type Description
timeout u64 Optional. Long-poll wait in seconds. Capped at 5.

If the queue is empty and timeout > 0, the server waits up to timeout seconds (max 5) before returning an empty result, giving new messages a chance to arrive.

Response:

{
  "ok": true,
  "result": [ ...updates... ]
}

Update Types

Encrypted message (from a user — bot must decrypt if it has a session):

{
  "update_id": 1,
  "message": {
    "message_id": "uuid",
    "from": {
      "id": "sender_fingerprint",
      "is_bot": false,
      "first_name": "sender_finge"
    },
    "chat": {
      "id": "sender_fingerprint",
      "type": "private"
    },
    "date": 1711670400,
    "text": null,
    "raw_encrypted": "base64-encoded-wiremessage..."
  }
}

Key exchange (X3DH session initiation — same shape as encrypted message):

{
  "update_id": 2,
  "message": {
    "message_id": "uuid",
    "from": { "id": "sender_fp", "is_bot": false, "first_name": "sender_fp..." },
    "chat": { "id": "sender_fp", "type": "private" },
    "date": 1711670400,
    "text": null,
    "raw_encrypted": "base64-encoded-keyexchange..."
  }
}

Call signal:

{
  "update_id": 3,
  "message": {
    "message_id": "uuid",
    "from": { "id": "sender_fp", "is_bot": false, "first_name": "sender_fp..." },
    "chat": { "id": "sender_fp", "type": "private" },
    "date": 1711670400,
    "text": "/call_Offer",
    "call_signal": {
      "type": "Offer",
      "payload": "SDP or ICE data..."
    }
  }
}

File header:

{
  "update_id": 4,
  "message": {
    "message_id": "uuid",
    "from": { "id": "sender_fp", "is_bot": false, "first_name": "sender_fp..." },
    "chat": { "id": "sender_fp", "type": "private" },
    "date": 1711670400,
    "document": {
      "file_name": "report.pdf",
      "file_size": 204800
    }
  }
}

Bot message (plaintext, from another bot via sendMessage):

{
  "update_id": 5,
  "message": {
    "message_id": "uuid",
    "from": {
      "id": "other_bot_fingerprint",
      "is_bot": true
    },
    "chat": {
      "id": "other_bot_fingerprint",
      "type": "private"
    },
    "date": 1711670400,
    "text": "Hello from the other bot!"
  }
}

Note: Receipt and internal wire messages (FileChunk, GroupSenderKey, SenderKeyDistribution) are silently skipped and never delivered as updates.


4. Send Message

POST /v1/bot/:token/sendMessage

Sends a plaintext message to a user or another bot.

Request:

{
  "chat_id": "aabbccdd1122334455667788aabbccdd",
  "text": "Hello from MyBot!"
}
Field Type Description
chat_id string Recipient fingerprint (hex) or Ethereum address.
text string Plaintext message body.

Non-hex characters in chat_id are stripped and the value is lowercased before routing.

Response:

{
  "ok": true,
  "result": {
    "message_id": "550e8400-e29b-41d4-a716-446655440000",
    "chat": {
      "id": "aabbccdd1122334455667788aabbccdd",
      "type": "private"
    },
    "text": "Hello from MyBot!",
    "date": 1711670400,
    "delivered": true
  }
}

The delivered field indicates whether the message was sent over a live WebSocket connection (true) or queued for later retrieval (false).


Alias Rules

Rule Detail
Bot aliases must end with Bot, bot, or _bot Enforced at registration time.
Non-bot users cannot register aliases with these suffixes Reserved for bots.
Auto-registered on bot creation No separate alias step needed.
Users message bots via alias e.g. @mybot_bot, resolved like any other alias.

Differences from Telegram Bot API

Feature Telegram featherChat
chat_id type Numeric integer Hex fingerprint string
getUpdates timeout Up to 50s Capped at 5s
Message content Always plaintext Encrypted messages arrive as raw_encrypted base64; bot must decrypt if it has a session
Bot-sent messages Plaintext Plaintext (not E2E encrypted) in v1
Inline keyboards / callback queries Supported Not yet (planned)
Media groups Supported Not yet (planned)
Webhooks (setWebhook) Supported Not yet (planned)
File download (getFile) Supported Not yet (planned)

Example: Simple Echo Bot (Python)

import requests
import time

TOKEN = "your_bot_token"
API = f"http://localhost:7700/v1/bot/{TOKEN}"

while True:
    resp = requests.post(f"{API}/getUpdates", json={"timeout": 5}).json()
    for update in resp.get("result", []):
        msg = update.get("message", {})
        text = msg.get("text") or "[encrypted]"
        chat_id = msg.get("chat", {}).get("id", "")
        if text and chat_id:
            requests.post(f"{API}/sendMessage", json={
                "chat_id": chat_id,
                "text": f"Echo: {text}",
            })
    time.sleep(1)

Example: Registration (curl)

curl -X POST http://localhost:7700/v1/bot/register \
  -H "Content-Type: application/json" \
  -d '{"name": "EchoBot", "fingerprint": "aabbccdd1122334455667788aabbccdd"}'

Authentication

All bot endpoints (except /register) are authenticated by the token in the URL path. Tokens are generated at registration time and stored server-side. There is no expiration mechanism in v1 -- tokens remain valid until the server database is cleared.

The token grants full access to poll and send messages as the bot. Treat it like a password.


Internal Details

  • Bot info is stored in the tokens sled tree under key bot:<token>.
  • A reverse lookup bot_fp:<fingerprint> -> <token> is also maintained.
  • Aliases are stored in the aliases sled tree (a:<alias> -> fingerprint, fp:<fingerprint> -> alias).
  • Queued messages live in the messages sled tree under prefix queue:<bot_fingerprint>:* and are deleted after getUpdates consumes them.
  • Messages are delivered via deliver_or_queue -- live WebSocket if online, otherwise queued.

Future Plans

  • Webhook mode (setWebhook) -- push updates to a URL instead of polling.
  • Inline keyboards and callback queries -- interactive message buttons.
  • E2E encrypted bot sessions -- bots participate in X3DH key exchange.
  • File send/receive APIs -- sendDocument, getFile.
  • Group bot support -- bots in group chats with sender-key encryption.