Pabal API
Pabal API (MTProto)
For building clients that connect to the server the same way the app does: connection details, the server public key, the sign-in flow, updates and what's supported.
The Pabal app talks to the server over MTProto 2.0. Read this page when you're building a program that connects the same way โ another app, automation running on a user account, a research client. If you're building a bot, the simpler Bot API is enough.
Pabal follows Telegram's published protocol, so the detailed definitions of the protocol and methods are in the MTProto and API methods documentation. This page describes what's different when connecting to a Pabal server, and what's supported.
Connection details
| Item | Value |
|---|---|
| Address | 122.34.175.215 |
| Port | 8443 (TCP) |
| DC | DCs 1โ5 all share the same address. You can connect to any DC; 2 is the usual choice |
| Protocol | MTProto 2.0, API layer 216 |
| Transports | Abridged, Intermediate, Padded Intermediate, Full โ each also with obfuscation (obfuscated2) |
| Server public key | server-key.pem ยท fingerprint 8724853375441383205 |
| api_id ยท api_hash | Not checked. Use any values |
There's no HTTP transport, WebSocket transport or MTProxy yet. The client device's clock must be right โ MTProto message IDs are derived from the time, so if the clock is far off, the server drops the messages.
Server public key
When an MTProto client first connects, it encrypts the auth key exchange with the server's RSA public key. Telegram clients have Telegram's public key built in, so to connect to Pabal you have to put in this key instead (or as well). This key stops other servers from pretending to be the Pabal server.
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA4hH74xPQsUwr/pyXPdF4tVicYr6QbfeDrKC7mUOVrPLSL4FtmgGn
w+O4u6lVvOf3Udd1KY6+OL4fUZdMBlLzwsoGLoniiVR09dnvyXHE8LhQSS+i1LmI
oJbhQwXplLnUJf272fLXkD23e7ppKLkjYk+jeYObueCy5HYMSThklVeXEzbZVGZv
47o/mjU2vyFoRpa6wCIE4rpj1UIPtOMpekMI/TocIlGVJ+ch6cAVNxIDro53a1eG
/1oZRLQH4oViEGxeMMjBMY5gk5HPkZvjbqy4h8TjXEz7O5o0BRsSqG/OPtP/dRQV
X4ewPhj2WCU4e6l5X59ZKIcv4sQLOwClqQIDAQAB
-----END RSA PUBLIC KEY-----
curl -s -o server-key.pem https://pabal.me/docs/server-key.pem
This key is created once, when the server first starts, and never changes. Check that the Loaded RSA key โฆ (fingerprint โฆ) value in the server log matches the fingerprint above.
Connecting with Telethon
This example uses Python's Telethon to sign in to a user account and send and receive messages. Sign up in the app first to create the account (see below).
# pabal_client.py โ pip install telethon==1.42.0
# server-key.pem (the server public key downloaded above) in the same folder
import asyncio
from telethon import TelegramClient, events
from telethon.crypto import rsa
rsa.add_key(open("server-key.pem").read(), old=False) # the Pabal server's public key
client = TelegramClient("pabal", api_id=1, api_hash="0" * 32) # sign-in is saved in pabal.session
client.session.set_dc(2, "122.34.175.215", 8443)
@client.on(events.NewMessage(incoming=True))
async def show(event):
sender = await event.get_sender()
print(f"{sender.first_name}: {event.raw_text}")
async def main():
await client.start(phone=lambda: input("Phone number (+8210โฆ): ")) # enter the code once, the first time
me = await client.get_me()
print(f"Signed in: {me.first_name} (id {me.id})")
await client.send_message("BotFather", "/help")
await client.run_until_disconnected()
asyncio.run(main())
- Use Telethon 1.42. It's the version that speaks layer 216. Newer versions try to read responses with a higher layer and fail with
TypeNotFoundError. - Telethon blocks signing up new accounts (
sign_up()). Sign up in the app, or callauth.signUpdirectly. - The sign-in is saved in the
pabal.sessionfile, so you won't be asked for a code again. This file is the key to the account, so keep it safe.
Sign-in flow
About this diagram
- Two stages: the top one creates the auth key used for encryption (the protocol), and the bottom one attaches an account to that key by signing in (the API). Libraries handle the top stage for you.
- A sign-in is attached to the auth key: once a key is signed in, every session you open with it is signed in too. If you lose the key (by deleting the session file), you have to sign in again.
- The server operator decides how codes are delivered: for SMS or delivery by an administrator you get
sentCodeTypeSms; for email you getsentCodeTypeSetUpEmailRequired, and the client asks for an email address and callsaccount.sendVerifyEmailCode(the middle row). - The red dashed line is the path for a new number: if the code is right but there's no account,
authorizationSignUpRequiredcomes back; callauth.signUpwith a name and the sign-up is complete. Signing up is only possible after entering the right code. - Bots skip the bottom stage and sign in with a single
auth.importBotAuthorizationcall (with the bot token).
| Error | When |
|---|---|
PHONE_NUMBER_INVALID | The number is wrong, or it's a new number while the server has closed new sign-ups |
PHONE_NUMBER_BANNED | A number the operator has blocked |
FLOOD_WAIT_n (420) | Codes were requested too often. Try again after n seconds |
PHONE_CODE_INVALID | The code is wrong (after the set number of tries, it's locked) |
PHONE_CODE_EXPIRED | The code has expired or is locked, or the phone_code_hash is unknown โ start again from sendCode |
EMAIL_INVALID, EMAIL_NOT_ALLOWED | The email address is invalid / the account already exists and this isn't its registered sign-in email |
AUTH_KEY_UNREGISTERED (401) | A method that needs sign-in was called with a key that isn't signed in |
On a server where the operator has turned on test numbers, numbers of the form +99966XYYYY sign in with the code XXXXX (X five times), without any code actually being delivered. This is meant for development servers only, and it's off on production servers.
Receiving updates
- Real time: while the connection is open, the server immediately sends new messages, edits and deletions as
updateShortMessageandupdates. The session that sent a request gets the result as the RPC response, so the same thing isn't pushed to it a second time. - pts: each user's changes get a sequence number (pts). If there's a gap in the pts a client receives, it has missed something.
- Catching up: remember the current pts with
updates.getState, and when you reconnect, callupdates.getDifference(pts, date, qts)to get the new messages and deletions in between, along with the related users and groups. If the client's pts is ahead of the server's (for example, when the server's data has been reset), you getdifferenceTooLong; reload the chat list in that case. - Libraries such as Telethon take care of all this for you.
IDs and peers
| What | ID | Notes |
|---|---|---|
| People | From 100001 | peerUser. @BotFather is 100000 |
| Bots | Same numbering as people | user.bot = true. The number at the front of the token is the bot ID |
| Basic groups | From 1000001 | peerChat. In the Bot API they appear as negative numbers (-chat_id) |
| Messages | From 1 in each message box | In a one-to-one chat each participant has their own copy with their own number. The same message can have different numbers for the two people |
Store access_hash exactly as the server gives it to you and use it from there (it comes along with username lookups, chat lists and updates).
Files
- Uploading: upload parts with
upload.saveFilePartand reference them withinputFileUploadedโฆ.upload.saveBigFilePartfor large files doesn't exist yet, so the practical limit is 10 MB. - Sending:
messages.sendMediawithinputMediaUploadedPhoto(a new photo) orinputMediaPhoto(a photo already on the server). Other media giveMEDIA_INVALID. - Downloading:
upload.getFilewithinputPhotoFileLocation(message photos) orinputPeerPhotoFileLocation(profile photos). Up to 1 MB at a time. - Profile photos:
photos.uploadProfilePhoto,photos.updateProfilePhoto,photos.getUserPhotos,photos.deletePhotos. - Photos are stored in one size only, the original (no separate thumbnails are generated).
What's supported
The server has handlers for 408 layer 216 methods and can read requests for all of them, but the methods below are the ones verified end to end with real clients. The rest answer in the right format, but their contents may be empty or may not be recorded.
| Area | Verified methods |
|---|---|
| Connection | initConnection, invokeWithLayer, help.getConfig, auth.bindTempAuthKey (PFS temporary keys), auth.exportAuthorization/importAuthorization |
| Sign-in | auth.sendCode, auth.signIn, auth.signUp, auth.logOut, auth.importBotAuthorization, account.sendVerifyEmailCode |
| Users and contacts | users.getUsers, users.getFullUser, contacts.resolveUsername, contacts.importContacts, contacts.search |
| Messages | messages.sendMessage, messages.sendMedia (photos), messages.getHistory, messages.getDialogs, messages.getMessages, messages.editMessage, messages.deleteMessages |
| Groups | messages.createChat, messages.deleteChatUser, messages.editChatTitle (messages.addChatUser verified with the official app only) |
| Bots | messages.getBotCallbackAnswer, messages.setBotCallbackAnswer, messages with buttons (reply_markup) |
| Updates | updates.getState, updates.getDifference, real-time push |
| Files and photos | upload.saveFilePart, upload.getFile, photos.* (above) |
We have also confirmed that the official Telegram Desktop 6.2.6 works without modification for signing up, signing in, chats, photos, groups and reconnecting. The roughly 60 methods the app calls at startup have their response formats checked separately.
Errors
Errors arrive as a standard rpc_error (error_code + error_message). error_message is always made of uppercase letters, digits and underscores (PEER_ID_INVALID), followed by : description when needed.
| Code | Meaning |
|---|---|
400 | Bad request โ PEER_ID_INVALID, MESSAGE_ID_INVALID, MEDIA_INVALID, USERNAME_NOT_OCCUPIED โฆ |
401 | Sign-in required โ AUTH_KEY_UNREGISTERED |
403 | Not allowed โ for example, a group you're not a member of |
420 | FLOOD_WAIT_n โ wait n seconds |
500 | Internal server error |
Transport error -404 | The server doesn't know this auth key โ create a new key and sign in again (permanent key) or bind again (temporary key) |
Not available yet
- Channels and supergroups (
channels.*answers, but doesn't display properly in the app), secret chats, calls - Media other than photos,
upload.saveBigFilePart, thumbnails - Two-step verification (SRP) โ it can't be set up, and actions that require two-step verification are refused
- HTTP and WebSocket transports, MTProxy, sending
msgs_ack, replacingbad_server_salt - Splitting across several servers โ a single server handles all of DCs 1โ5
Connecting the official Telegram app to Pabal
The Telegram app builds the server address and public key into itself at build time. So instead of changing a setting, you have to modify the source and rebuild it. That's how the Pabal app (Pabal.app) was made. If you're a server operator, see Server installation โ connecting the app.