Getting started
About Pabal
What Pabal is and how it's built, what works today and what doesn't yet.
What is Pabal?
Pabal (파발, 擺撥) was the relay courier system of Joseon-era Korea, in which riders changed horses at relay stations to rush urgent news onward. Pabal.me is a messenger named after it: a Telegram-compatible messenger that an organization or community runs on its own server.
- You run the server yourself. Accounts, conversations and photos are all stored on the operator's server and database (PostgreSQL). The server program is called HunsTelegram (Java 21).
- It speaks Telegram's language as is. Between the app and the server it uses MTProto 2.0 (layer 216), just like Telegram, and between bots and the server the same HTTP Bot API as Telegram. That's why apps, libraries and bots built for Telegram connect to Pabal by changing only the address.
- It is a separate world, not connected to Telegram. Pabal accounts exist only on the Pabal server, and you can't exchange messages with Telegram users.
How it's built
About this diagram
- Three areas: on the left is what runs outside the server (apps, bot programs, browsers), in the middle are the server's two entrances, and on the right is the inside of the server. Bot programs run outside the server too, on the operator's or developer's own computer.
- There are only two entrances: the app connects directly to the MTProto port (8443) (MTProto encrypts on its own, so it needs no HTTPS), while the website and the Bot API come in over HTTPS (443).
- A bot connects in one of two ways: usually through the Bot API over HTTPS (solid line), or, if you prefer, over MTProto just like the app (blue dashed line). Either way it is the same bot account and the same message box.
- The red dashed line is the only arrow that points the other way: when a bot sets a webhook, the server sends new updates to the bot program's HTTPS address. Everything else is a request coming into the server from outside.
- There is one record: every change goes through the services and is kept in PostgreSQL's event store; only the original photos are stored as files. Messages sent from the app and messages sent by bots travel the same path, so pushes, chat lists and catching up after reconnecting work the same for everyone.
What works today, and what doesn't yet
| Feature | Status | Notes |
|---|---|---|
| Sign-up and sign-in (phone number + code) | Works | The operator chooses how codes are delivered: SMS, email or by an administrator |
| One-to-one chats, real-time delivery, multiple devices | Works | A device that was off catches up on what it missed when it's switched back on |
| Editing and deleting messages | Works | Shows up on the other person's screen right away |
| Basic groups (create, add members, remove members, name) | Works | Members are added directly from the group info |
| Sending photos, profile photos | Works | Stored in one size, the original |
| Bots — @BotFather, HTTP Bot API, webhooks, MTProto bots | Works | Buttons, callbacks, command menu, photos, groups |
| Admin page, operational settings | Works | Open only on the server's 127.0.0.1 |
| Website in 10 languages, username and invite link pages | Works | The developer docs too, in 10 languages |
| Channels, supergroups | Not yet | May not display properly in the app |
| Documents, videos, audio files, albums | Not yet | Rejected with MEDIA_INVALID when sent |
Formatted text (bold, italic), parse_mode for bots | Not yet | Sent as plain text. Commands, mentions, links and hashtags are highlighted automatically |
| Voice and video calls, secret chats | Not yet | |
| Two-step verification (cloud password) | Not yet | Rejected if you try to set it up |
| Mobile apps, push notifications | Not yet | For now, the macOS desktop app |
| Joining a group through an invite link | Not yet | Links can be created, but opening one doesn't make you a member |
Inline mode (@bot query), payments, games | Not yet |
Relationship with Telegram
Pabal is a separate server that follows Telegram's published protocol. It has nothing to do with Telegram the company, and it never connects to Telegram's servers.
- What's compatible: MTProto 2.0 (all four transports, the handshake, temporary key binding), the request and response formats of layer 216, and the HTTP Bot API's address format, requests, responses and error format. We confirmed this by connecting the official Telegram Desktop 6.2.6 without modifying it (changing only the server address and public key).
- What's different: accounts and data are separate for each server. User IDs, message IDs and file IDs only mean something within this server. Bot tokens you used on Telegram won't work; you need to get a new one from Pabal's @BotFather.
Link format
The app and the server build links with https://pabal.me/. Opening one in a browser shows a small page that opens the app.
| Link | Meaning | Address opened in the app |
|---|---|---|
pabal.me/<username> | Opens a chat with a person or bot | tg://resolve?domain=<username> |
pabal.me/+<invite code> | Group invite link (the app opens, but joining through a link doesn't work yet) | tg://join?invite=<invite code> |
pabal.me/joinchat/<invite code> | Invite link in the older format (same meaning) | tg://join?invite=<invite code> |
A username is 5–32 characters of letters, digits and underscores, starting with a letter (bot usernames end in bot). Names that match paths the site itself uses, such as docs, admin and health, can't be opened as links.
Security model
- App ↔ server: encrypted with MTProto 2.0. The app is built with the server's RSA public key inside it, so no other server can pretend to be the Pabal server. Conversations are like Telegram's "cloud chats", so the server can read their contents (this is not end-to-end encryption). That's why the server must be run by someone you can trust.
- Bot ↔ server: the Bot API is exposed over HTTPS only. A bot token is the bot's password — if it leaks, replace it with
/revokeat @BotFather. The old token, and any connections made with it, are cut off immediately. - Server → webhook: the server only sends requests to webhooks that use HTTPS and have a public address. Internal addresses such as private networks, loopback and cloud metadata are refused. A bot can use
secret_tokento check that a request really came from the Pabal server. - Administration: the admin page is open only on the server itself (127.0.0.1), and you need a token to see any data. Operators get in through an SSH tunnel.
- Storage: auth keys are stored as they are in the database, because the server needs them for decryption. Guard the database and its backups as carefully as the server's RSA private key.
Glossary
| Term | Meaning |
|---|---|
| MTProto | The encryption protocol between app and server, designed by Telegram. Pabal uses version 2.0. |
| Layer | The version of the request and response formats exchanged on top of MTProto. Pabal uses 216. |
| Auth key | A 2048-bit secret the app creates together with the server when it first connects. Sign-ins are attached to this key. |
| DC | Telegram's data center number. In Pabal, a single server handles all of DCs 1–5. |
| Updates, pts | Changes such as new messages, edits and deletions. pts is a per-user sequence number of changes that lets a device that was disconnected know what it missed. |
| Peer | The other side of a conversation — a person, a bot or a group. |
| Bot token | A string of the form <bot ID>:<secret>. Put it in the Bot API address to prove you are the bot. |
| Webhook | Instead of the bot coming to fetch new updates, the server sends them to the bot's HTTPS address. |