What it means
The Telegram Bot API is a plain HTTPS interface. Every method is a URL of the form https://api.telegram.org/bot<token>/METHOD, every request is form-encoded or JSON, and every response is a JSON object with an ok boolean and either a result or an error_code and description.
Behind that URL, Telegram is running a real MTProto client on your behalf. It holds the connection, handles the encryption, resolves peers, manages access hashes, and translates the result into JSON. That is the whole value proposition: you get to write a Telegram integration with curl instead of implementing a bespoke binary protocol.
You get a bot by talking to @BotFather, which issues a token shaped like 123456789:AA.... The number before the colon is the bot's own user ID, which is why you can always tell a bot's ID by looking at its token, and why a leaked token is a leaked account. Tokens are revocable, which is the single biggest security advantage the Bot API has over a session string.
Two ways to receive updates
Bots do not maintain a persistent connection to your server. Telegram delivers events one of two ways, and enabling one disables the other.
Long polling with getUpdates: you ask for updates with an offset, the request hangs until something arrives or the timeout expires, and you acknowledge by passing the next offset on the following call. Updates are retained for 24 hours, so a bot that is offline overnight comes back to a backlog rather than to silence. It works from a laptop behind NAT, which is why it is the correct choice while developing.
Webhooks with setWebhook: Telegram POSTs each update to a URL you own. The endpoint has to be HTTPS on port 443, 80, 88 or 8443, with a certificate Telegram accepts (or a self-signed one you upload with the call). Webhooks push instead of pull, so they scale better and cut latency, and getWebhookInfo is the first place to look when a bot has gone quiet: it reports the pending update count and the last error message Telegram saw from your server.
One practical note that costs people hours: if your webhook endpoint returns a non-2xx status, Telegram retries, and the pending queue grows. A bot that "stopped working after a deploy" is very often a webhook pointed at a URL that now 502s, with a queue of thousands waiting behind it. See webhook for the general pattern.
The limits that actually bind
Telegram publishes some Bot API limits and enforces others by observation. The numbers in the table below are the ones that shape real architecture decisions. Two of them deserve emphasis.
The 20 MB download cap on getFile is asymmetric with what users can send. A customer can send your support bot a 200 MB screen recording, and your bot will receive the update, see the file metadata, and be unable to fetch the bytes. If your product handles user-supplied media, this alone can force you onto the local Bot API server or onto MTProto.
The 48-hour edit and delete window is the other one. A bot cannot edit or delete a message older than 48 hours, full stop. Any feature built on "we will clean that up later" needs to run inside the window or not exist.
What a bot fundamentally cannot do
These are not limits you can raise. They are consequences of what a bot account is.
- Start a conversation. The user must message the bot, add it to a group, or open it through a deep link first.
- Read history from before it joined. A bot added to a group today sees nothing that happened yesterday.
- Enumerate group members. There is no method for it. Admins yes, member count yes, member list no.
- Join a group by invite link. A human has to add it.
- See non-command group messages by default. Privacy mode is on until you turn it off in BotFather.
Everything on that list is available to a userbot, which is a real user account driven over MTProto. That is the actual trade: the Bot API gives you a supported, revocable, unbannable-for-volume identity that cannot do outbound, and a user account gives you full capability with real account risk. Most serious Telegram products end up running both.
Why it matters
Choosing between the Bot API and MTProto is the first architectural decision in any Telegram integration, and it is expensive to reverse, because the two speak different peer identifiers, deliver updates differently, and have entirely different failure modes.
The decision usually comes down to direction of contact. If people come to you, a bot is the right tool: support inboxes, order notifications, internal alerts, appointment reminders, payment flows, and anything with buttons, because inline keyboards and callback queries are bot-only features. If you need to go to people, or to read a group you do not own, no amount of Bot API engineering will get you there.
The second consideration is risk. A bot token is revocable and a bot is not going to get a phone number banned. A user account is a real person's identity, subject to flood waits, PEER_FLOOD, and permanent restriction. Teams that treat those as interchangeable tend to discover the difference at the worst possible moment.
Common mistakes
- Putting the token in a client-side bundle. The token is the account. It belongs on your server, and only there.
- Ignoring retry_after. A 429 tells you exactly how long to wait. Retrying immediately extends the penalty.
- Returning 500 from the webhook handler on business errors. Telegram will retry the same update forever. Acknowledge with a 200 and handle the failure in your own queue.
- Forgetting privacy mode. The bot works perfectly in a private chat and appears broken in groups, and nothing in the API tells you why.
- Assuming chat_id is the MTProto ID. It is not. See peer ID for the conversion.
- Building an outbound campaign on a bot. It cannot message strangers. This is discovered surprisingly late.
Related concepts
- MTProto: the protocol the Bot API is a managed wrapper around.
- Userbot: the other side of the trade, with full capability and full risk.
- Business connection: Telegram's sanctioned way to let a bot answer a real person's private chats.
- Peer ID: why a Bot API
chat_idlooks nothing like the MTProto ID for the same chat. - Forum topic: the
message_thread_ida bot must echo back to reply in the right thread. - Webhook: the delivery pattern, and how to make it reliable.
How Pinlyx handles it
Pinlyx runs both paths and routes each job to whichever one can actually perform it. Bot traffic arrives over a webhook, is acknowledged immediately, and is processed from an internal queue, so a slow downstream never turns into a growing pending-update backlog. Rate limits are respected on both sides: the Bot API client honours retry_after, and the MTProto sender handles FLOOD_WAIT with exponential back-off. Anything a bot can do, a bot does, because it carries no account risk. Anything that requires reaching a person who has not written first runs through a connected user account inside the Telegram CRM, under a rate limiter with per-account hourly and daily caps.