Business Accounts

Bot API 7.2 — March 2024, extended in 7.3 and 9.0

Telegram Business lets a user connect a bot to their personal account. Once connected, the bot sees the messages that arrive in that user’s private chats and can answer them as the user, not as itself. The customer never sees a bot: they see the person they wrote to.

This is the only part of the API where a bot acts on behalf of a human account, which is why nearly every send method carries a business_connection_id parameter.


The connection

The user connects your bot from Settings → Business → Chatbots. Your bot is told about it through on_business_connection():

from pyrogram import Client

app = Client("my_bot")

connections = {}


@app.on_business_connection()
async def connected(client, connection):
    connections[connection.user.id] = connection.id
    print(f"{connection.user.first_name} connected, enabled: {connection.is_enabled}")
    print(f"can reply: {connection.rights.can_reply}")


app.run()

The connection id is what you store. Everything else flows from it. You can also fetch a connection you already know the id of with get_business_connection().

Handling business messages

Business updates come through their own handlers, separate from the bot’s own messages, so a bot can serve both roles without the two streams mixing:

@app.on_business_message()
async def answer(client, message):
    await message.reply("Thanks for writing! We'll be with you shortly.")

A reply sent from inside these handlers is sent as the user. Under the hood the bound method carries the connection id for you; when you call a client method directly, pass it yourself:

await app.send_message(
    chat_id=customer_id,
    text="Your order is ready.",
    business_connection_id=connection_id,
)

Every send_* method accepts business_connection_id, as do edit_message_text(), send_reaction() and delete_business_messages().

Managing the account

Bot API 9.0 opened up the business account’s own settings. With the user’s permission a bot can change the things a business owner would otherwise set by hand:

Business chat links are deep links that open a chat with a message already typed:

from pyrogram import raw

link = await app.create_business_chat_link(
    raw.types.InputBusinessChatLink(
        message="I'd like to book a table",
        title="Reservations",
    )
)

print(link.link)

See also get_business_chat_links(), resolve_business_chat_link() and delete_business_chat_link().

Note

The account-management methods above are the user side of Telegram Business: they are what the business owner’s own client calls, so they are usable by user sessions, not by bots. A bot connected to that account works through the connection id instead.

Stars and gifts held by the account

A connected business account has its own Stars balance and its own gifts, distinct from the bot’s:

gifts = await app.get_business_account_gifts(
    business_connection_id=connection_id,
    exclude_unsaved=True,
)

balance = await app.get_business_account_star_balance(connection_id)

await app.transfer_business_account_stars(connection_id, star_count=100)

Gotchas

  • Check BusinessConnection’s rights before sending. A connection whose rights.can_reply is False was made in read-only mode and every send will be rejected; is_enabled going False means the user paused it. rights also gates gifts, stories and profile edits separately.

  • The connection id is per user, not per chat. One id covers every private chat that user has.

  • A business message is not a bot message: filters like filters.command still work, but the update arrives through on_business_message(), so a handler registered with on_message() will never see it.