Telegram::JsonAPI - Telegram TDLib's JSON API


  use Telegram::JsonAPI qw(:all);


  my $res = td_execute('{"@type": "setLogVerbosityLevel", "new_verbosity_level": 1, "@extra": 1.01234}');
  # got $res = '{"@type":"ok","@extra":1.01234}';

  td_poll_log(sub {
    my($verbosity, $msg) = @_;
    print "got log ($verbosity) $msg\n";
  # this will clear all the buffered log once.

  my $client_id = td_create_client_id();
  td_send($client_id, '{"@type": "getAuthorizationState", "@extra": 1.01234}');
  # start loggin progress

  while(1) {
    my $msg = decode_json(td_receive(.1));
    # Wait for a JSON message for at most 0.1 second.
    # There will be a `@client_id` field, which contains $client_id.
    # If you have more than one client id simutaneously, you can distinguish them by this field.
    given( $msg->{'@type'} ) {
      when('updateAuthorizationState') {



This module integrated Telegram's TDLib JSON API. which is used to implement Telegram client app. The difference between an app and a bot is that an app will act as an normal user. And you need to authenticate it with a phone number.


None by default.

With tag :all, there are

$client_id = td_create_client_id()

Returns an opaque identifier of a new TDLib instance. The TDLib instance will not send updates until the first request is sent to it.

td_send($client_id, $json_request)

Sends request to the TDLib client.

$json_message = td_receive($timeout)

Receives incoming updates and request responses.

$json_message = td_execute($json_request)

Synchronously executes a TDLib request. A request can be executed synchronously, only if it is documented with "Can be called synchronously".

td_start_log($max_verbosity_level=1024, $buffer_size=1048576)

Start to keep log messages and prepare a buffer for them. They will be first stored in a buffer. Then use td_poll_log() to take them out.


Stop keeping log messages and wipe out the log buffer.

td_poll_log($cb->($verbosity, $message))

Fetch and clear the buffered log messages.


This is a short example which implemented user authentication and send a text message.

  use strict;
  use warnings;
  use feature qw(say switch);
  no warnings qw(experimental::smartmatch);

  use Telegram::JsonAPI qw(:all);
  use JSON::XS::ByteString qw(encode_json decode_json);


  my $client_id = td_create_client_id;

  td_send($client_id, encode_json({'@type' => 'getAuthorizationState', '@extra' => \1.01234}));

  while(1) {
    td_poll_log sub { say "got log: @_"; };
    my $msg = td_receive(1);
    if( defined $msg ) {
      say "recv: $msg";
      $msg = decode_json($msg);
      given($msg->{'@type'}) {
        when('updateAuthorizationState') {
          given( $msg->{authorization_state}{'@type'} ) {
            when('authorizationStateWaitTdlibParameters') {
              td_send($cid, encode_json({
                '@type' => 'setTdlibParameters',
                parameters => {
                  database_directory => 'tdlib', # path for TDLib to store session data
                  use_message_database => 1,
                  use_secret_chats => 1,
                  api_id => $api_id,     # $api_id and $api_hash could be retrieved from
                  api_hash => $api_hash, #
                  system_language_code => 'en',
                  device_model => 'Desktop',
                  application_version => '1.0',
                  enable_storage_optimizer => 1,
            when('authorizationStateWaitEncryptionKey') {
              td_send($cid, encode_json({
                '@type' => 'checkDatabaseEncryptionKey',
                encryption_key => '',
            when('authorizationStateWaitPhoneNumber') {
              say 'Please enter your phone number:';
              my $phone = <STDIN>;
              $phone =~ s/\s//g;
              td_send($cid, encode_json({
                '@type' => 'setAuthenticationPhoneNumber',
                phone_number => $phone,
            when('authorizationStateWaitCode') {
              say 'Please enter the authentication code you received:';
              my $code = <STDIN>;
              $code =~ s/\s//g;
              td_send($cid, encode_json({
                '@type' => 'checkAuthenticationCode',
                code => $code,
            when('authorizationStateWaitRegistration') {
              say 'Please enter your first name:';
              my $first_name = <STDIN>;
              $first_name =~ s/^\s+|\s+$//g;
              say 'Please enter your last name:';
              my $last_name = <STDIN>;
              $last_name =~ s/^\s+|\s+$//g;
              td_send($cid, encode_json({
                '@type' => 'registerUser',
                first_name => $first_name,
                last_name => $last_name,
            when('authorizationStateWaitPassword') {
              say 'Please enter your password:';
              my $password = <STDIN>;
              chomp $password;
              td_send($cid, encode_json({
                '@type' => 'checkAuthenticationPassword',
                password => $password,
            when('authorizationStateReady') {
              td_send($client_id, encode_json({
                '@type' => 'sendMessage',
                chat_id => $chat_id, # beside the chat list, you can also retrive the chat id from any incoming messages
                input_message_content => {
                  '@type' => 'inputMessageText',
                  text => {
                    '@type' => 'formattedText',
                    text => "Hello, every one.",


This module needs libtdjson. Hopefully your can install it from your OS package manager. Or you can get it from and build it on your own.



Getting started with TDLib

TDLib api list

What to put in the JSON requests and got from the JSON responses.


Cindy Wang (CindyLinz) <>


Copyright (C) 2022 by CindyLinz

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.30.2 or, at your option, any later version of Perl 5 you may have available.