Docs développeurs
Français

API Pabal

API Pabal (MTProto)

Pour créer un client qui se connecte au serveur comme l'application : informations de connexion, clé publique du serveur, flux d'authentification, mises à jour, périmètre pris en charge.

L'application Pabal communique avec le serveur en MTProto 2.0. Consultez cette page si vous créez un programme qui se connecte de la même façon : une autre application, une automatisation qui tourne avec un compte utilisateur, un client de recherche. Pour créer un bot, la Bot API, plus simple, suffit.

Lisez aussi la documentation de Telegram

Pabal suit le protocole public de Telegram : pour la définition détaillée du protocole et des méthodes, la référence reste la documentation MTProto et celle des méthodes de l'API. Cette page décrit ce qui diffère et ce qui est pris en charge quand vous vous connectez à un serveur Pabal.

Informations de connexion

ÉlémentValeur
Adresse122.34.175.215
Port8443 (TCP)
DCDe 1 à 5, tous à la même adresse. Vous pouvez vous connecter à n'importe quel DC ; on utilise généralement le 2
ProtocoleMTProto 2.0, layer d'API 216
TransportsAbridged, Intermediate, Padded Intermediate, Full — chacun aussi en version obfusquée (obfuscated2)
Clé publique du serveurserver-key.pem · empreinte (fingerprint) 8724853375441383205
api_id · api_hashNon vérifiés. Mettez n'importe quelle valeur

Les transports HTTP et WebSocket ainsi que MTProxy ne sont pas encore disponibles. L'horloge de l'appareil client doit être à l'heure : les numéros de message MTProto sont dérivés de l'heure, et si l'horloge est très décalée, le serveur rejette les messages.

Clé publique du serveur

Lors de sa première connexion, un client MTProto chiffre l'échange de clé d'autorisation avec la clé publique RSA du serveur. Les clients Telegram intègrent la clé publique de Telegram : pour se connecter à Pabal, ils doivent intégrer cette clé à la place (ou en plus). C'est elle qui empêche un autre serveur de se faire passer pour le serveur Pabal.

-----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

Cette clé est générée une seule fois, au premier démarrage du serveur, et ne change plus. Vérifiez que la valeur Loaded RSA key … (fingerprint …) des journaux du serveur correspond à l'empreinte ci-dessus.

Se connecter avec Telethon

Exemple avec Telethon en Python : connexion à un compte utilisateur, puis envoi et réception de messages. Créez d'abord le compte en vous inscrivant depuis l'application (voir plus bas).

# pabal_client.py — pip install telethon==1.42.0
# server-key.pem (la clé publique du serveur téléchargée plus haut) dans le même dossier
import asyncio

from telethon import TelegramClient, events
from telethon.crypto import rsa

rsa.add_key(open("server-key.pem").read(), old=False)          # clé publique du serveur Pabal

client = TelegramClient("pabal", api_id=1, api_hash="0" * 32)  # connexion enregistrée dans 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("Numéro de téléphone (+336…) : "))   # code à saisir la première fois seulement
    me = await client.get_me()
    print(f"Connecté : {me.first_name} (id {me.id})")
    await client.send_message("BotFather", "/help")
    await client.run_until_disconnected()


asyncio.run(main())
  • Utilisez Telethon 1.42 : c'est la version qui parle la layer 216. Les versions plus récentes tentent de lire les réponses avec une layer plus élevée et échouent avec TypeNotFoundError.
  • Telethon bloque l'inscription de nouveaux comptes (sign_up()). Inscrivez-vous depuis l'application, ou appelez vous-même auth.signUp.
  • La connexion est enregistrée dans le fichier pabal.session : le code ne vous sera plus demandé les fois suivantes. Ce fichier est la clé de votre compte : protégez-le.

Flux de connexion

1 · Clé d'autorisation (une fois) req_pq_multi → req_DH_params set_client_DH_params Clé d'auth. 2048 bitsProtégée par la clé publique 2 · Connexion (une fois par clé d'autorisation) auth.sendCodeNuméro de téléphone sentCodeTypeSmsSMS ou remise par l'admin SetUpEmailRequiredMode e-mail → demande l'adresse account.sendVerifyEmailCodepurpose: loginSetup auth.signInphone_code ou code e-mail auth.authorizationConnexion réussie authorizationSignUpRequiredNouveau n° → auth.signUp(nom) Une fois le code reçu
Créer la clé d'autorisation, puis se connecter avec un code

Explication du diagramme

  • Deux étapes : en haut, la création de la clé d'autorisation qui servira au chiffrement (protocole) ; en bas, la connexion qui rattache un compte à cette clé (API). Les bibliothèques se chargent de l'étape du haut à votre place.
  • La connexion est rattachée à la clé d'autorisation : une fois la clé connectée, toutes les sessions ouvertes avec elle le sont aussi. Si vous perdez la clé (fichier de session supprimé), vous devez vous reconnecter.
  • C'est l'opérateur du serveur qui décide par où passe le code : pour les SMS ou la remise par l'administrateur, vous recevez sentCodeTypeSms ; pour l'e-mail, sentCodeTypeSetUpEmailRequired, et le client demande alors une adresse e-mail puis appelle account.sendVerifyEmailCode (rangée du milieu).
  • Les pointillés rouges sont le chemin d'un nouveau numéro : si le code est correct mais qu'aucun compte n'existe, vous recevez authorizationSignUpRequired ; appelez alors auth.signUp avec un nom, et l'inscription est terminée. L'inscription n'est possible qu'après avoir saisi le bon code.
  • Les bots se connectent en un seul appel à auth.importBotAuthorization (jeton du bot), au lieu de l'étape du bas.
ErreurQuand
PHONE_NUMBER_INVALIDNuméro incorrect, ou nouveau numéro alors que le serveur a fermé les inscriptions
PHONE_NUMBER_BANNEDNuméro bloqué par l'opérateur, ou numéro d'un compte suspendu (s'il a été supprimé alors qu'il était suspendu, 1 an par défaut — l'opérateur peut allonger ce délai ou le rendre illimité)
FLOOD_WAIT_n (420)Codes demandés trop souvent. Réessayez dans n secondes
PHONE_CODE_INVALIDCode incorrect (verrouillé au-delà du nombre d'essais autorisé)
PHONE_CODE_EXPIREDCode expiré ou verrouillé, ou phone_code_hash inconnu — recommencez à partir de sendCode
EMAIL_INVALID, EMAIL_NOT_ALLOWEDAdresse e-mail incorrecte / compte existant, mais ce n'est pas l'e-mail de connexion enregistré
AUTH_KEY_UNREGISTERED (401)Appel, avec une clé non connectée, d'une méthode qui exige une connexion
Numéros de test

Sur un serveur où l'opérateur a activé les numéros de test, les numéros de la forme +99966XYYYY se connectent sans aucun envoi réel de code, avec le code XXXXX (X répété cinq fois). Cette fonction est réservée aux serveurs de développement ; elle est désactivée sur les serveurs de production.

Recevoir les mises à jour

  • Temps réel : tant que la connexion est ouverte, le serveur envoie aussitôt les nouveaux messages, modifications et suppressions sous forme de updateShortMessage et updates. La session qui a envoyé une requête en reçoit le résultat dans la réponse RPC : elle ne reçoit donc pas la même chose une seconde fois en push.
  • pts : chaque changement reçoit un numéro d'ordre (pts), propre à chaque utilisateur. Si les pts reçus par le client présentent un trou, c'est qu'il a manqué quelque chose.
  • Rattrapage : mémorisez le pts actuel avec updates.getState ; à la reconnexion, updates.getDifference(pts, date, qts) renvoie les nouveaux messages et suppressions survenus entre-temps, avec les utilisateurs et groupes concernés. Si le pts du client est en avance sur celui du serveur (par exemple parce que les données du serveur ont été réinitialisées), vous recevez differenceTooLong : rechargez alors la liste des discussions.
  • Notifications push — Android : une application Android sans connexion est réveillée par un push Firebase. Une fois que l'application s'est enregistrée avec account.registerDevice (token_type 2 = jeton FCM, secret = clé d'appareil de 256 octets), le serveur chiffre les nouveaux messages et les appels avec cette clé d'appareil et les envoie via FCM ; réveillée, l'application se met à jour avec updates.getDifference. Les notifications push ne peuvent atteindre que des applications compilées avec le projet Firebase de l'opérateur du serveur.
  • Notifications push — iPhone : l'application iPhone enregistre deux choses avec la même requête — token_type 1 (jeton d'alerte APNs) et 9 (jeton VoIP PushKit) ; dans les deux cas, secret est la clé d'appareil de 256 octets du compte. Les nouveaux messages partent en alertes APNs : le seul texte visible par Apple est le nom de l'application et une phrase sans contenu comme « You have a new notification », tandis que le message, chiffré avec la clé d'appareil, voyage dans p ; l'extension de notification de l'application (Notification Service Extension) le déchiffre et l'affiche. Les appels arrivent par push VoIP et ouvrent l'écran d'appel CallKit (à partir des builds pour lesquels l'opérateur a activé la VoIP ; avant, sous forme d'alerte), et ce qui a été lu ou supprimé sur un autre appareil est signalé par des notifications push en arrière-plan. Les notifications push ne peuvent atteindre que des applications signées par la même équipe que la clé APNs de l'opérateur du serveur et portant le même bundle ID. Aux autres token_type, le serveur répond boolTrue sans rien envoyer.
  • Les bibliothèques comme Telethon gèrent tout cela automatiquement.

ID et pairs

CibleIDRemarque
PersonneÀ partir de 100001peerUser. @BotFather a l'ID 100000
BotMême numérotation que les personnesuser.bot = true. Le nombre au début du jeton est l'ID du bot
Groupe simpleÀ partir de 1000001peerChat. Dans la Bot API, il apparaît en négatif (-chat_id)
MessageUne seule numérotation pour tout le serveurDans une conversation 1:1, les deux copies portent le même numéro. Les requêtes qui ne prennent que des numéros de message, sans pair (messages.getMessages, messages.deleteMessages), désignent donc le même message pour les deux personnes. Seuls les canaux ont leur propre numérotation, à partir de 1

Enregistrez tel quel l'access_hash fourni par le serveur et réutilisez-le (il accompagne les résolutions de nom d'utilisateur, la liste des discussions et les mises à jour).

Fichiers

  • Téléversement : envoyez les morceaux avec upload.saveFilePart (512 Ko par morceau au maximum, 4 000 morceaux au maximum), puis référencez-les avec inputFileUploaded… Les fichiers de plus de 10 Mo passent par upload.saveBigFilePart : comme le nombre de morceaux est annoncé à l'avance, le serveur refuse avec FILE_TOO_BIG avant que tout soit envoyé si la taille dépasse ce qu'il accepte. Les morceaux sont écrits sur disque au fur et à mesure de leur arrivée, puis réassemblés en un seul fichier lorsqu'un message le référence.
  • Envoi : messages.sendMedia avec inputMediaUploadedPhoto (nouvelle photo), inputMediaPhoto (photo déjà présente sur le serveur), inputMediaUploadedDocument (nouveau fichier) ou inputMediaDocument (fichier déjà présent sur le serveur). Les autres médias renvoient MEDIA_INVALID. Vous pouvez aussi téléverser sans envoyer, avec messages.uploadMedia (le média renvoyé s'envoie ensuite tel quel) ; messages.sendMultiMedia est accepté, mais les éléments partent un par un, sans être regroupés (pas de grouped_id).
  • Réception : upload.getFile avec inputPhotoFileLocation (photo d'un message), inputDocumentFileLocation (fichier d'un message) ou inputPeerPhotoFileLocation (photo de profil). 1 Mo au maximum par appel. À la réception non plus, le fichier entier n'est pas chargé en mémoire : seule la portion demandée est lue.
  • Photo de profil : photos.uploadProfilePhoto, photos.updateProfilePhoto, photos.getUserPhotos, photos.deletePhotos.
  • Les photos ne sont stockées qu'en une seule taille, celle de l'original (aucune miniature n'est générée). Les fichiers, eux, sont conservés tels quels, et les documentAttribute* attachés par l'expéditeur sont transmis octet pour octet au destinataire : le serveur les relaie sans avoir besoin de comprendre la durée d'une vidéo ou la forme d'onde d'un enregistrement audio.

Périmètre pris en charge

Le serveur dispose de gestionnaires pour 469 méthodes de la layer 216, et tous savent lire les requêtes ; mais seules les méthodes ci-dessous ont été vérifiées de bout en bout avec de vrais clients. Les autres répondent dans le bon format, mais leur contenu peut être vide ou ne pas être enregistré.

DomaineMéthodes vérifiées
ConnexioninitConnection, invokeWithLayer, help.getConfig, auth.bindTempAuthKey (clé temporaire PFS), auth.exportAuthorization/importAuthorization
Authentificationauth.sendCode, auth.signIn, auth.signUp, auth.logOut, auth.importBotAuthorization, account.sendVerifyEmailCode
Utilisateurs et contactsusers.getUsers, users.getFullUser, contacts.resolveUsername, contacts.importContacts, contacts.search
Messagesmessages.sendMessage, messages.sendMedia (photos et fichiers), messages.getHistory, messages.getDialogs, messages.getMessages, messages.editMessage, messages.deleteMessages
Groupesmessages.createChat, messages.deleteChatUser, messages.editChatTitle (messages.addChatUser vérifié uniquement avec l'application officielle)
Botsmessages.getBotCallbackAnswer, messages.setBotCallbackAnswer, messages portant des boutons (reply_markup)
Mises à jourupdates.getState, updates.getDifference, push en temps réel
Fichiers et photosupload.saveFilePart, upload.saveBigFilePart (au-delà de 10 Mo), upload.getFile, photos.* (ci-dessus)

Nous avons aussi vérifié que Telegram Desktop 6.2.6 officiel fonctionne sans modification pour l'inscription, la connexion, les conversations, les photos, les groupes et la reconnexion. Le format de réponse des quelque 60 méthodes que l'application appelle au démarrage fait l'objet d'une vérification spécifique.

Ajouté depuis — la liste des appareils et leur déconnexion (account.getAuthorizations, account.resetAuthorization, auth.resetAuthorizations), l'export des données de l'application de bureau (account.initTakeoutSession, invokeWithTakeout, invokeWithMessagesRange, account.finishTakeoutSession — trois lancements par jour et par compte, au-delà 420 TAKEOUT_INIT_DELAY_n), le changement de numéro (account.sendChangePhoneCode, account.changePhone — 400 PHONE_CHANGE_DISABLED tant que l'opérateur ne l'a pas activé, BOT_METHOD_INVALID pour un bot) : vérifiés par les tests du serveur ; la vérification de bout en bout avec les vraies applications reste à faire.

Erreurs

Les erreurs arrivent sous la forme standard rpc_error (error_code + error_message). error_message est toujours composé de majuscules, de chiffres et de tirets bas (PEER_ID_INVALID), suivi si nécessaire de : explication.

CodeSignification
400Requête incorrecte — PEER_ID_INVALID, MESSAGE_ID_INVALID, MEDIA_INVALID, USERNAME_NOT_OCCUPIED …
401Connexion requise — AUTH_KEY_UNREGISTERED
403Pas d'autorisation — par exemple, un groupe dont vous n'êtes pas membre
406Pas pour l'instant — un appareil connecté depuis moins de 24 heures tente de déconnecter un autre appareil : FRESH_RESET_AUTHORISATION_FORBIDDEN
420FLOOD_WAIT_n — attendre n secondes
500Erreur interne du serveur
Erreur de transport -404Le serveur ne connaît pas cette clé d'autorisation — créez une nouvelle clé et reconnectez-vous (clé permanente), ou refaites la liaison (clé temporaire)

API montre

/api/watch/v1/ sur le serveur est un point d'entrée JSON sur HTTPS réservé à l'app Pabal pour Apple Watch. Il existe parce que la montre ne peut pas utiliser MTProto ; ce n'est pas une spécification publique et il est en préparation : il peut changer sans préavis. Pour créer un programme qui se connecte à Pabal, utilisez le MTProto décrit sur cette page. Les opérateurs de serveur peuvent consulter Installation du serveur — point d'entrée Apple Watch.

Ce qui n'existe pas encore

  • Canaux et supergroupes (channels.* répond, mais ils ne s'affichent pas correctement dans l'application), conversations secrètes, appels de groupe
  • Vidéos et messages vocaux qui se lisent dans l'application, albums affichés en un seul bloc (grouped_id), stickers, miniatures (les fichiers ne sont conservés qu'en original)
  • Validation en deux étapes (SRP) — impossible à configurer, et les opérations qui l'exigent sont refusées
  • Transports HTTP et WebSocket, MTProxy, envoi de msgs_ack, rotation périodique du sel serveur (un sel erroné reçoit bad_server_salt)
  • Répartition sur plusieurs serveurs — un seul serveur assure tous les DC de 1 à 5

Connecter l'application Telegram officielle à Pabal

L'application Telegram intègre l'adresse du serveur et la clé publique au moment de la compilation. Il faut donc modifier le code source et recompiler : un écran de réglages ne suffit pas. C'est ainsi qu'a été créée l'application Pabal (Pabal.app). Si vous êtes opérateur de serveur, consultez Installation du serveur — connecter l'application.