> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ruapi.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# A Telegram bot on an LLM (Claude/GPT)

> Build a Telegram bot that answers through an LLM in under an hour. Python, copy-paste code.

A Telegram bot is probably the fastest way to put an LLM in front of people: no website, no app — you just open a chat and type. Below is the full path from an empty folder to a working bot that answers through Claude or GPT using your RuAPI key. There isn't much code, and it's short enough to copy in one go.

We use RuAPI's OpenAI-compatible protocol: swap the `base_url`, and the same `openai` SDK works with Claude, GPT, Gemini, and DeepSeek.

<Steps>
  <Step title="Prerequisites">
    * **A RuAPI key** — `sk-...`. Create it in the Console: **Tokens** → **Create token**. Top up your balance in USDT — see [top up](/en/topup).
    * **Python 3.10+** — check with `python --version`.
    * **A Telegram bot token** — we'll get this in the next step.
  </Step>

  <Step title="Create the bot in Telegram">
    Open a chat with [@BotFather](https://t.me/BotFather) in Telegram and send `/newbot`. BotFather will ask for the bot's name and a username (it must end in `bot`). In return it sends an **HTTP API token** — a string like `123456789:AAH...`. Copy it; you'll need it shortly.

    <Warning>
      The bot token is a password. Don't publish it in your code, repository, or
      screenshots. If you leak it by accident, send BotFather `/revoke` to get a new one.
    </Warning>
  </Step>

  <Step title="Install the dependencies">
    ```bash theme={null}
    pip install python-telegram-bot openai
    ```

    `python-telegram-bot` version 21+ is an async framework for Telegram. `openai` is the client we'll point at RuAPI.
  </Step>

  <Step title="Write the bot">
    Create a file called `bot.py`. This is a fully working minimal bot: on every text message it sends your text to the model and replies with the model's answer.

    ```python bot.py theme={null}
    import os

    from openai import OpenAI
    from telegram import Update
    from telegram.ext import (
        ApplicationBuilder,
        ContextTypes,
        MessageHandler,
        filters,
    )

    # Read keys from environment variables — never hardcode secrets in code.
    TELEGRAM_TOKEN = os.environ["TELEGRAM_TOKEN"]
    RUAPI_KEY = os.environ["RUAPI_KEY"]

    # OpenAI SDK client pointed at RuAPI (OpenAI-compatible protocol).
    client = OpenAI(
        api_key=RUAPI_KEY,
        base_url="https://www.ruapi.ai/v1",
    )


    async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
        user_text = update.message.text

        response = client.chat.completions.create(
            model="claude-opus-4-8",  # exact model names are on the pricing page
            messages=[{"role": "user", "content": user_text}],
        )
        answer = response.choices[0].message.content

        await update.message.reply_text(answer)


    def main() -> None:
        app = ApplicationBuilder().token(TELEGRAM_TOKEN).build()
        app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
        app.run_polling()


    if __name__ == "__main__":
        main()
    ```

    <Note>
      The example uses the model `claude-opus-4-8`. The same key also reaches other
      models: `gpt-5.4`, `gemini-3.5-flash`, `deepseek-v4-pro`, and more. Exact names are
      on the **Pricing** page at [www.ruapi.ai](https://www.ruapi.ai).
    </Note>
  </Step>

  <Step title="Run it">
    Pass both tokens via environment variables and run the script:

    ```bash theme={null}
    export TELEGRAM_TOKEN="123456789:AAH..."
    export RUAPI_KEY="sk-YOUR_KEY"
    python bot.py
    ```

    The bot starts quietly and begins listening for messages (`run_polling` polls Telegram). Find your bot in Telegram by its username, send it anything, and it will answer through the model. Press `Ctrl+C` to stop.
  </Step>

  <Step title="Make it better">
    The minimal bot has no memory and answers every message from a blank slate. A few directions to grow:

    * **Conversation history.** Store the message history per `chat_id` (for example, in `context.chat_data`) and pass the whole list to `messages=[...]` — then the bot remembers earlier turns.
    * **A system prompt.** Add `{"role": "system", "content": "You are a friendly assistant..."}` as the first element to set tone and role.
    * **A /start command.** Add a `CommandHandler("start", ...)` with a greeting — it makes the bot feel friendlier.
    * **Switch models.** Change the `model` field to switch to GPT or Gemini.
    * **Cheaper at scale.** If you handle a lot of traffic, move the bot to a more affordable model — `gemini-3.5-flash` or `deepseek-v4-pro`. They're great for chat and spend your balance much more slowly.
  </Step>
</Steps>

## Troubleshooting

<AccordionGroup>
  <Accordion title="The bot is silent and doesn't answer">
    Check that the bot token was copied whole, with no stray spaces, and that the
    script is actually running (`run_polling` must be active, the terminal window
    still open). Make sure you're messaging the exact bot you created with
    BotFather. Errors print to the terminal — look there.
  </Accordion>

  <Accordion title="401 (Unauthorized) error">
    The problem is with the **RuAPI** key, not the bot token. Check `RUAPI_KEY` —
    it must start with `sk-`. You can view the key in the Console on the
    **Tokens** page.
  </Accordion>

  <Accordion title="402 (Payment Required) error">
    Your balance ran out. Top it up in USDT — see [top up](/en/topup).
  </Accordion>
</AccordionGroup>

## What's next

* [Quickstart](/en/quickstart) — the basics of the API and `base_url`.
* [Streaming responses](/en/streaming) — make the bot type its answer out instead of pausing on long replies.
* [Errors](/en/errors) — what the response codes mean.
* Questions? [support@ruapi.ai](mailto:support@ruapi.ai)
