Update content of files

This commit is contained in:
GitHub Action 2024-06-08 15:25:05 +00:00
parent 0f71438c27
commit 72c175e0be
10 changed files with 1101 additions and 900 deletions

View file

@ -44,116 +44,139 @@
<div id="dev_page_content"><!-- scroll_nav -->
<p>Authorization is associated with a client&#39;s encryption key identifier: <strong>auth_key_id</strong>. No additional parameters need to be passed into methods following authorization. </p>
<p>To log in as a <a href="/bots">bot</a>, follow <a href="/api/bots">these instructions &raquo;</a>.</p>
<p>An alternative <a href="/api/qr-login">QR code-based login flow is also available &raquo;</a>.</p>
<h3><a class="anchor" name="sending-a-verification-code" href="#sending-a-verification-code"><i class="anchor-icon"></i></a>Sending a verification code</h3>
<p>Authorization is associated with a client's encryption key identifier: <strong>auth_key_id</strong>. No additional parameters need to be passed into methods following authorization. </p>
<p>To log in as a <a href="/bots">bot</a>, follow <a href="/api/bots">these instructions »</a>.</p>
<p>An alternative <a href="/api/qr-login">QR code-based login flow is also available »</a>.</p>
<h3><a class="anchor" href="#sending-a-verification-code" id="sending-a-verification-code" name="sending-a-verification-code"><i class="anchor-icon"></i></a>Sending a verification code</h3>
<p>Example implementations: <a href="https://github.com/DrKLO/Telegram/blob/master/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java">telegram for android</a>, <a href="https://github.com/tdlib/td/tree/master/td/telegram/SendCodeHelper.cpp">tdlib</a>.</p>
<p>To show a nicely formatted and validated phone number field, the <a href="/constructor/help.countriesList">help.countriesList</a> constructor can be obtained using the <a href="/method/help.getCountriesList">help.getCountriesList</a> method.<br>The <a href="/constructor/help.countriesList">help.countriesList</a> config and other configuration values are then used as described <a href="/api/config#country-information-and-login-phone-patterns">here &raquo;</a>. </p>
<p>Then, a text message containing an authorization code is sent to the user&#39;s phone using <a href="/method/auth.sendCode">auth.sendCode</a>.<br>However, this is not always the case, if future auth tokens are used: </p>
<h4><a class="anchor" name="future-auth-tokens" href="#future-auth-tokens"><i class="anchor-icon"></i></a>Future auth tokens</h4>
<p>When invoking <a href="/method/auth.logOut">auth.logOut</a> on a previously authorized session, the server may return a <code>future_auth_token</code>, which should be stored in the local database.<br>A <code>future_auth_token</code> is also contained in the <a href="/constructor/auth.authorization">auth.authorization</a> returned when logging in.<br>At all times, the future auth token database should contain at most 20 tokens: evict older tokens as new tokens are added to stay below this limit.<br>When invoking <a href="/method/auth.sendCode">auth.sendCode</a>, all future auth tokens present in the database should be provided to <code>codeSettings.logout_tokens</code>.<br>If any of the future auth tokens matches the account we&#39;re trying to login into and the token hasn&#39;t expired:</p>
<p>To show a nicely formatted and validated phone number field, the <a href="/constructor/help.countriesList">help.countriesList</a> constructor can be obtained using the <a href="/method/help.getCountriesList">help.getCountriesList</a> method.<br>
The <a href="/constructor/help.countriesList">help.countriesList</a> config and other configuration values are then used as described <a href="/api/config#country-information-and-login-phone-patterns">here »</a>. </p>
<p>Then, a text message containing an authorization code is sent to the user's phone using <a href="/method/auth.sendCode">auth.sendCode</a>.<br>
However, this is not always the case, if future auth tokens are used: </p>
<h4><a class="anchor" href="#future-auth-tokens" id="future-auth-tokens" name="future-auth-tokens"><i class="anchor-icon"></i></a>Future auth tokens</h4>
<p>When invoking <a href="/method/auth.logOut">auth.logOut</a> on a previously authorized session, the server may return a <code>future_auth_token</code>, which should be stored in the local database.<br>
A <code>future_auth_token</code> is also contained in the <a href="/constructor/auth.authorization">auth.authorization</a> returned when logging in.<br>
At all times, the future auth token database should contain at most 20 tokens: evict older tokens as new tokens are added to stay below this limit.<br>
When invoking <a href="/method/auth.sendCode">auth.sendCode</a>, all future auth tokens present in the database should be provided to <code>codeSettings.logout_tokens</code>.<br>
If any of the future auth tokens matches the account we're trying to login into and the token hasn't expired:</p>
<ul>
<li>If <a href="/api/srp">2FA</a> is not enabled, <a href="/method/auth.sendCode">auth.sendCode</a> will is directly return an <a href="/constructor/auth.sentCodeSuccess">auth.sentCodeSuccess</a> constructor with session info, indicating the session is authorized.</li>
<li>If <a href="/api/srp">2FA</a> is enabled, <a href="/method/auth.sendCode">auth.sendCode</a> will return a <code>SESSION_PASSWORD_NEEDED</code> RPC error, asking the user to <a href="#2fa">enter the 2FA password</a>, without sending any authorization code. </li>
</ul>
<p>Otherwise, the system will send an authorization code using the following logic:</p>
<h4><a class="anchor" name="code-types" href="#code-types"><i class="anchor-icon"></i></a>Code types</h4>
<pre><code>codeSettings#ad253d78 flags:# allow_flashcall:flags.0?true current_number:flags.1?true allow_app_hash:flags.4?true allow_missed_call:flags.5?true allow_firebase:flags.7?true logout_tokens:flags.6?Vector&lt;bytes&gt; token:flags.8?string app_sandbox:flags.8?Bool = CodeSettings;
<h4><a class="anchor" href="#code-types" id="code-types" name="code-types"><i class="anchor-icon"></i></a>Code types</h4>
<pre><code><a href='/constructor/codeSettings'>codeSettings</a>#ad253d78 flags:<a href='/type/%23'>#</a> allow_flashcall:flags.0?<a href='/constructor/true'>true</a> current_number:flags.1?<a href='/constructor/true'>true</a> allow_app_hash:flags.4?<a href='/constructor/true'>true</a> allow_missed_call:flags.5?<a href='/constructor/true'>true</a> allow_firebase:flags.7?<a href='/constructor/true'>true</a> logout_tokens:flags.6?<a href='/type/Vector%20t'>Vector</a>&lt;<a href='/type/bytes'>bytes</a>&gt; token:flags.8?<a href='/type/string'>string</a> app_sandbox:flags.8?<a href='/type/Bool'>Bool</a> = <a href='/type/CodeSettings'>CodeSettings</a>;
auth.sentCodeTypeApp#3dbb5986 length:int = auth.SentCodeType;
auth.sentCodeTypeSms#c000bba2 length:int = auth.SentCodeType;
auth.sentCodeTypeCall#5353e5a7 length:int = auth.SentCodeType;
auth.sentCodeTypeFlashCall#ab03c6d9 pattern:string = auth.SentCodeType;
auth.sentCodeTypeMissedCall#82006484 prefix:string length:int = auth.SentCodeType;
auth.sentCodeTypeEmailCode#f450f59b flags:# apple_signin_allowed:flags.0?true google_signin_allowed:flags.1?true email_pattern:string length:int reset_available_period:flags.3?int reset_pending_date:flags.4?int = auth.SentCodeType;
auth.sentCodeTypeSetUpEmailRequired#a5491dea flags:# apple_signin_allowed:flags.0?true google_signin_allowed:flags.1?true = auth.SentCodeType;
auth.sentCodeTypeFragmentSms#d9565c39 url:string length:int = auth.SentCodeType;
auth.sentCodeTypeFirebaseSms#e57b1432 flags:# nonce:flags.0?bytes receipt:flags.1?string push_timeout:flags.1?int length:int = auth.SentCodeType;
<a href='/constructor/auth.sentCodeTypeApp'>auth.sentCodeTypeApp</a>#3dbb5986 length:<a href='/type/int'>int</a> = <a href='/type/auth.SentCodeType'>auth.SentCodeType</a>;
<a href='/constructor/auth.sentCodeTypeSms'>auth.sentCodeTypeSms</a>#c000bba2 length:<a href='/type/int'>int</a> = <a href='/type/auth.SentCodeType'>auth.SentCodeType</a>;
<a href='/constructor/auth.sentCodeTypeCall'>auth.sentCodeTypeCall</a>#5353e5a7 length:<a href='/type/int'>int</a> = <a href='/type/auth.SentCodeType'>auth.SentCodeType</a>;
<a href='/constructor/auth.sentCodeTypeFlashCall'>auth.sentCodeTypeFlashCall</a>#ab03c6d9 pattern:<a href='/type/string'>string</a> = <a href='/type/auth.SentCodeType'>auth.SentCodeType</a>;
<a href='/constructor/auth.sentCodeTypeMissedCall'>auth.sentCodeTypeMissedCall</a>#82006484 prefix:<a href='/type/string'>string</a> length:<a href='/type/int'>int</a> = <a href='/type/auth.SentCodeType'>auth.SentCodeType</a>;
<a href='/constructor/auth.sentCodeTypeEmailCode'>auth.sentCodeTypeEmailCode</a>#f450f59b flags:<a href='/type/%23'>#</a> apple_signin_allowed:flags.0?<a href='/constructor/true'>true</a> google_signin_allowed:flags.1?<a href='/constructor/true'>true</a> email_pattern:<a href='/type/string'>string</a> length:<a href='/type/int'>int</a> reset_available_period:flags.3?<a href='/type/int'>int</a> reset_pending_date:flags.4?<a href='/type/int'>int</a> = <a href='/type/auth.SentCodeType'>auth.SentCodeType</a>;
<a href='/constructor/auth.sentCodeTypeSetUpEmailRequired'>auth.sentCodeTypeSetUpEmailRequired</a>#a5491dea flags:<a href='/type/%23'>#</a> apple_signin_allowed:flags.0?<a href='/constructor/true'>true</a> google_signin_allowed:flags.1?<a href='/constructor/true'>true</a> = <a href='/type/auth.SentCodeType'>auth.SentCodeType</a>;
<a href='/constructor/auth.sentCodeTypeFragmentSms'>auth.sentCodeTypeFragmentSms</a>#d9565c39 url:<a href='/type/string'>string</a> length:<a href='/type/int'>int</a> = <a href='/type/auth.SentCodeType'>auth.SentCodeType</a>;
<a href='/constructor/auth.sentCodeTypeFirebaseSms'>auth.sentCodeTypeFirebaseSms</a>#e57b1432 flags:<a href='/type/%23'>#</a> nonce:flags.0?<a href='/type/bytes'>bytes</a> receipt:flags.1?<a href='/type/string'>string</a> push_timeout:flags.1?<a href='/type/int'>int</a> length:<a href='/type/int'>int</a> = <a href='/type/auth.SentCodeType'>auth.SentCodeType</a>;
auth.sentCode#5e002502 flags:# type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode;
auth.sentCodeSuccess#2390fe44 authorization:auth.Authorization = auth.SentCode;
<a href='/constructor/auth.sentCode'>auth.sentCode</a>#5e002502 flags:<a href='/type/%23'>#</a> type:<a href='/type/auth.SentCodeType'>auth.SentCodeType</a> phone_code_hash:<a href='/type/string'>string</a> next_type:flags.1?<a href='/type/auth.CodeType'>auth.CodeType</a> timeout:flags.2?<a href='/type/int'>int</a> = <a href='/type/auth.SentCode'>auth.SentCode</a>;
<a href='/constructor/auth.sentCodeSuccess'>auth.sentCodeSuccess</a>#2390fe44 authorization:<a href='/type/auth.Authorization'>auth.Authorization</a> = <a href='/type/auth.SentCode'>auth.SentCode</a>;
---functions---
auth.sendCode#a677244f phone_number:string api_id:int api_hash:string settings:CodeSettings = auth.SentCode;
auth.resendCode#3ef1a9bf phone_number:string phone_code_hash:string = auth.SentCode;
<a href='/method/auth.sendCode'>auth.sendCode</a>#a677244f phone_number:<a href='/type/string'>string</a> api_id:<a href='/type/int'>int</a> api_hash:<a href='/type/string'>string</a> settings:<a href='/type/CodeSettings'>CodeSettings</a> = <a href='/type/auth.SentCode'>auth.SentCode</a>;
<a href='/method/auth.resendCode'>auth.resendCode</a>#3ef1a9bf phone_number:<a href='/type/string'>string</a> phone_code_hash:<a href='/type/string'>string</a> = <a href='/type/auth.SentCode'>auth.SentCode</a>;
auth.requestFirebaseSms#89464b50 flags:# phone_number:string phone_code_hash:string safety_net_token:flags.0?string ios_push_secret:flags.1?string = Bool;</code></pre>
<p>The <a href="/method/auth.sendCode">auth.sendCode</a> method has parameters for enabling/disabling use of flash calls and missed calls, and allows passing an SMS token that will be included in the sent SMS.<br>For example, the latter is required in newer versions of android, to use the <a href="https://developers.google.com/identity/sms-retriever/overview">android SMS receiver APIs</a>.</p>
<a href='/method/auth.requestFirebaseSms'>auth.requestFirebaseSms</a>#89464b50 flags:<a href='/type/%23'>#</a> phone_number:<a href='/type/string'>string</a> phone_code_hash:<a href='/type/string'>string</a> safety_net_token:flags.0?<a href='/type/string'>string</a> ios_push_secret:flags.1?<a href='/type/string'>string</a> = <a href='/type/Bool'>Bool</a>;</code></pre>
<p>The <a href="/method/auth.sendCode">auth.sendCode</a> method has parameters for enabling/disabling use of flash calls and missed calls, and allows passing an SMS token that will be included in the sent SMS.
For example, the latter is required in newer versions of android, to use the <a href="https://developers.google.com/identity/sms-retriever/overview">android SMS receiver APIs</a>.</p>
<p>The returned <a href="/constructor/auth.sentCode">auth.sentCode</a> object will contain multiple parameters:</p>
<table class="table">
<tbody>
<tr>
<td><strong>flags</strong></td>
<td align="center"><a href="/type/%23">#</a></td>
<td style="text-align: center;"><a href="/type/%23">#</a></td>
<td>Flags, see <a href="/mtproto/TL-combinators#conditional-fields">TL conditional fields</a></td>
</tr>
<tr>
<td><strong>type</strong></td>
<td align="center"><a href="/type/auth.SentCodeType">auth.SentCodeType</a></td>
<td style="text-align: center;"><a href="/type/auth.SentCodeType">auth.SentCodeType</a></td>
<td>Phone code type</td>
</tr>
<tr>
<td><strong>phone_code_hash</strong></td>
<td align="center"><a href="/type/string">string</a></td>
<td style="text-align: center;"><a href="/type/string">string</a></td>
<td>Phone code hash, to be stored and re-used in later method calls</td>
</tr>
<tr>
<td><strong>next_type</strong></td>
<td align="center"><a href="/mtproto/TL-combinators#conditional-fields">flags</a>.1?<a href="/type/auth.CodeType">auth.CodeType</a></td>
<td style="text-align: center;"><a href="/mtproto/TL-combinators#conditional-fields">flags</a>.1?<a href="/type/auth.CodeType">auth.CodeType</a></td>
<td>Phone code type that will be sent next, if the phone code is not received within <code>timeout</code> seconds: to send it use <a href="/method/auth.resendCode">auth.resendCode</a></td>
</tr>
<tr>
<td><strong>timeout</strong></td>
<td align="center"><a href="/mtproto/TL-combinators#conditional-fields">flags</a>.2?<a href="/type/int">int</a></td>
<td style="text-align: center;"><a href="/mtproto/TL-combinators#conditional-fields">flags</a>.2?<a href="/type/int">int</a></td>
<td>Timeout for reception of the phone code</td>
</tr>
</tbody>
</table>
<p>The system will automatically choose how to send the authorization code; there are multiple possible ways the code can arrive, signaled to the client via the <code>type</code> field of the <a href="/type/auth.SentCodeType">auth.SentCodeType</a> constructor. </p>
<p>Note that in some conditions when signing up or logging in using an SMS code/call, only the <a href="/constructor/auth.sentCodeTypeFirebaseSms">auth.sentCodeTypeFirebaseSms</a> code type may be used.<br>Currently, only official apps can make use of Firebase SMS authentication: this means that in some conditions, only the official applications can receive a login/signup code via SMS/call.<br>Third-party apps may log in using any of the other code delivery methods (Telegram codes, Fragment codes, email codes, future auth tokens, <a href="/api/qr-login">QR codes</a>).</p>
<p>Note that in some conditions when signing up or logging in using an SMS code/call, only the <a href="/constructor/auth.sentCodeTypeFirebaseSms">auth.sentCodeTypeFirebaseSms</a> code type may be used.<br>
Currently, only official apps can make use of Firebase SMS authentication: this means that in some conditions, only the official applications can receive a login/signup code via SMS/call.<br>
Third-party apps may log in using any of the other code delivery methods (Telegram codes, Fragment codes, email codes, future auth tokens, <a href="/api/qr-login">QR codes</a>).</p>
<ul>
<li><a href="/constructor/auth.sentCodeTypeSetUpEmailRequired">auth.sentCodeTypeSetUpEmailRequired</a>: if the user logins often enough, Telegram will ask the user to verify an email that will be used to send the login code.<br>See <a href="#email-verification">here &raquo;</a> for more info on the verification process.</li>
<li><a href="/constructor/auth.sentCodeTypeSetUpEmailRequired">auth.sentCodeTypeSetUpEmailRequired</a>: if the user logins often enough, Telegram will ask the user to verify an email that will be used to send the login code.<br>
See <a href="#email-verification">here »</a> for more info on the verification process.</li>
<li><a href="/constructor/auth.sentCodeTypeEmailCode">auth.sentCodeTypeEmailCode</a>: the code was sent to the configured login email.</li>
<li><a href="/constructor/auth.sentCodeTypeFragmentSms">auth.sentCodeTypeFragmentSms</a>: the code was sent via <a href="https://fragment.com">fragment.com</a>: open the specified <code>url</code> to log into the <a href="https://fragment.com">Fragment</a> platform with your wallet and view the code. </li>
<li><a href="/constructor/auth.sentCodeTypeApp">auth.sentCodeTypeApp</a>: the code was sent as a Telegram service notification to all other logged-in sessions.</li>
<li><a href="/constructor/auth.sentCodeTypeFirebaseSms">auth.sentCodeTypeFirebaseSms</a>: firebase login flow, only for official apps. <ul>
<li>On Android, can only be received if the <a href="/constructor/codeSettings">codeSettings</a>.<code>allow_firebase</code> flag is set.<br>The client must pass the received <a href="/constructor/auth.sentCodeTypeFirebaseSms">auth.sentCodeTypeFirebaseSms</a>.<code>nonce</code> to the <a href="https://developer.android.com/training/safetynet/attestation">SafetyNet Attestation API</a>, and then pass the obtained JWS object to <a href="/method/auth.requestFirebaseSms">auth.requestFirebaseSms</a>.<code>safety_net_token</code>, along with the <code>phone_number</code> and the <code>phone_code_hash</code>.<br>If the method returns <a href="/constructor/boolTrue">boolTrue</a>, the code will be sent via SMS; otherwise, the <code>next_type</code> authentication method must be used, with <a href="/method/auth.resendCode">auth.resendCode</a>.</li>
<li>On iOS, can only be received if the device token for Apple Push was passed to <a href="/constructor/codeSettings">codeSettings</a>.<code>token</code>.<br>The client then waits for a new push notification for <a href="/constructor/auth.sentCodeTypeFirebaseSms">auth.sentCodeTypeFirebaseSms</a>.<code>push_timeout</code> seconds.<br>If a push notification isn&#39;t received within <code>push_timeout</code> seconds, the <code>next_type</code> authentication method must be used, with <a href="/method/auth.resendCode">auth.resendCode</a>.<br>If a push notification is received with <code>receipt</code> and <code>ios_push_secret</code> fields, and the value of the <code>receipt</code> field matches <a href="/constructor/codeSettings">codeSettings</a>.<code>receipt</code>, the value of <code>ios_push_secret</code> is passed to <a href="/method/auth.requestFirebaseSms">auth.requestFirebaseSms</a>.<code>ios_push_secret</code>, along with the <code>phone_number</code> and the <code>phone_code_hash</code>.<br>If the method returns <a href="/constructor/boolTrue">boolTrue</a>, the code will be sent via SMS; otherwise, the <code>next_type</code> authentication method must be used, with <a href="/method/auth.resendCode">auth.resendCode</a>.</li>
<li>On Android, can only be received if the <a href="/constructor/codeSettings">codeSettings</a>.<code>allow_firebase</code> flag is set.<br>
The client must pass the received <a href="/constructor/auth.sentCodeTypeFirebaseSms">auth.sentCodeTypeFirebaseSms</a>.<code>nonce</code> to the <a href="https://developer.android.com/training/safetynet/attestation">SafetyNet Attestation API</a>, and then pass the obtained JWS object to <a href="/method/auth.requestFirebaseSms">auth.requestFirebaseSms</a>.<code>safety_net_token</code>, along with the <code>phone_number</code> and the <code>phone_code_hash</code>.<br>
If the method returns <a href="/constructor/boolTrue">boolTrue</a>, the code will be sent via SMS; otherwise, the <code>next_type</code> authentication method must be used, with <a href="/method/auth.resendCode">auth.resendCode</a>.</li>
<li>On iOS, can only be received if the device token for Apple Push was passed to <a href="/constructor/codeSettings">codeSettings</a>.<code>token</code>.<br>
The client then waits for a new push notification for <a href="/constructor/auth.sentCodeTypeFirebaseSms">auth.sentCodeTypeFirebaseSms</a>.<code>push_timeout</code> seconds.<br>
If a push notification isn't received within <code>push_timeout</code> seconds, the <code>next_type</code> authentication method must be used, with <a href="/method/auth.resendCode">auth.resendCode</a>.<br>
If a push notification is received with <code>receipt</code> and <code>ios_push_secret</code> fields, and the value of the <code>receipt</code> field matches <a href="/constructor/codeSettings">codeSettings</a>.<code>receipt</code>, the value of <code>ios_push_secret</code> is passed to <a href="/method/auth.requestFirebaseSms">auth.requestFirebaseSms</a>.<code>ios_push_secret</code>, along with the <code>phone_number</code> and the <code>phone_code_hash</code>.<br>
If the method returns <a href="/constructor/boolTrue">boolTrue</a>, the code will be sent via SMS; otherwise, the <code>next_type</code> authentication method must be used, with <a href="/method/auth.resendCode">auth.resendCode</a>.</li>
</ul>
</li>
<li><a href="/constructor/auth.sentCodeTypeSms">auth.sentCodeTypeSms</a>: the code was sent via SMS.</li>
<li><a href="/constructor/auth.sentCodeTypeCall">auth.sentCodeTypeCall</a>: the user will receive a phone call and a synthesized voice will tell the user the verification code to input.</li>
<li><a href="/constructor/auth.sentCodeTypeFlashCall">auth.sentCodeTypeFlashCall</a>: the code will be sent via a flash phone call, that will be closed immediately.<br>In this case, the phone code will then be the phone number itself, just make sure that the phone number matches the specified pattern (see <a href="/constructor/auth.sentCodeTypeFlashCall">auth.sentCodeTypeFlashCall</a>).</li>
<li><a href="/constructor/auth.sentCodeTypeMissedCall">auth.sentCodeTypeMissedCall</a>: the code will be sent via a flash phone call, that will be closed immediately.<br>The last digits of the phone number that calls are the code that must be entered manually by the user.</li>
<li><a href="#future-auth-tokens">Future auth tokens &raquo;</a></li>
<li><a href="/constructor/auth.sentCodeTypeFlashCall">auth.sentCodeTypeFlashCall</a>: the code will be sent via a flash phone call, that will be closed immediately.<br>
In this case, the phone code will then be the phone number itself, just make sure that the phone number matches the specified pattern (see <a href="/constructor/auth.sentCodeTypeFlashCall">auth.sentCodeTypeFlashCall</a>).</li>
<li><a href="/constructor/auth.sentCodeTypeMissedCall">auth.sentCodeTypeMissedCall</a>: the code will be sent via a flash phone call, that will be closed immediately.<br>
The last digits of the phone number that calls are the code that must be entered manually by the user.</li>
<li><a href="#future-auth-tokens">Future auth tokens »</a></li>
</ul>
<p>If the message takes too long (<code>timeout</code> seconds) to arrive at the phone, the <a href="/method/auth.resendCode">auth.resendCode</a> method may be invoked to resend a code of type <code>next_type</code>.<br>If the same happens again, you can use <a href="/method/auth.resendCode">auth.resendCode</a> with the <code>next_type</code> returned by the previous call to <a href="/method/auth.resendCode">auth.resendCode</a>.<br>To cancel the verification code use <a href="/method/auth.cancelCode">auth.cancelCode</a>.</p>
<h3><a class="anchor" name="email-verification" href="#email-verification"><i class="anchor-icon"></i></a>Email verification</h3>
<pre><code>auth.sentCodeTypeSetUpEmailRequired#a5491dea flags:# apple_signin_allowed:flags.0?true google_signin_allowed:flags.1?true = auth.SentCodeType;
<p>If the message takes too long (<code>timeout</code> seconds) to arrive at the phone, the <a href="/method/auth.resendCode">auth.resendCode</a> method may be invoked to resend a code of type <code>next_type</code>.
If the same happens again, you can use <a href="/method/auth.resendCode">auth.resendCode</a> with the <code>next_type</code> returned by the previous call to <a href="/method/auth.resendCode">auth.resendCode</a>.
To cancel the verification code use <a href="/method/auth.cancelCode">auth.cancelCode</a>.</p>
<h3><a class="anchor" href="#email-verification" id="email-verification" name="email-verification"><i class="anchor-icon"></i></a>Email verification</h3>
<pre><code><a href='/constructor/auth.sentCodeTypeSetUpEmailRequired'>auth.sentCodeTypeSetUpEmailRequired</a>#a5491dea flags:<a href='/type/%23'>#</a> apple_signin_allowed:flags.0?<a href='/constructor/true'>true</a> google_signin_allowed:flags.1?<a href='/constructor/true'>true</a> = <a href='/type/auth.SentCodeType'>auth.SentCodeType</a>;
emailVerifyPurposeLoginSetup#4345be73 phone_number:string phone_code_hash:string = EmailVerifyPurpose;
<a href='/constructor/emailVerifyPurposeLoginSetup'>emailVerifyPurposeLoginSetup</a>#4345be73 phone_number:<a href='/type/string'>string</a> phone_code_hash:<a href='/type/string'>string</a> = <a href='/type/EmailVerifyPurpose'>EmailVerifyPurpose</a>;
emailVerificationCode#922e55a9 code:string = EmailVerification;
emailVerificationGoogle#db909ec2 token:string = EmailVerification;
emailVerificationApple#96d074fd token:string = EmailVerification;
<a href='/constructor/emailVerificationCode'>emailVerificationCode</a>#922e55a9 code:<a href='/type/string'>string</a> = <a href='/type/EmailVerification'>EmailVerification</a>;
<a href='/constructor/emailVerificationGoogle'>emailVerificationGoogle</a>#db909ec2 token:<a href='/type/string'>string</a> = <a href='/type/EmailVerification'>EmailVerification</a>;
<a href='/constructor/emailVerificationApple'>emailVerificationApple</a>#96d074fd token:<a href='/type/string'>string</a> = <a href='/type/EmailVerification'>EmailVerification</a>;
account.sentEmailCode#811f854f email_pattern:string length:int = account.SentEmailCode;
<a href='/constructor/account.sentEmailCode'>account.sentEmailCode</a>#811f854f email_pattern:<a href='/type/string'>string</a> length:<a href='/type/int'>int</a> = <a href='/type/account.SentEmailCode'>account.SentEmailCode</a>;
account.emailVerifiedLogin#e1bb0d61 email:string sent_code:auth.SentCode = account.EmailVerified;
<a href='/constructor/account.emailVerifiedLogin'>account.emailVerifiedLogin</a>#e1bb0d61 email:<a href='/type/string'>string</a> sent_code:<a href='/type/auth.SentCode'>auth.SentCode</a> = <a href='/type/account.EmailVerified'>account.EmailVerified</a>;
emailVerifyPurposeLoginChange#527d22eb = EmailVerifyPurpose;
account.emailVerified#2b96cd1b email:string = account.EmailVerified;
<a href='/constructor/emailVerifyPurposeLoginChange'>emailVerifyPurposeLoginChange</a>#527d22eb = <a href='/type/EmailVerifyPurpose'>EmailVerifyPurpose</a>;
<a href='/constructor/account.emailVerified'>account.emailVerified</a>#2b96cd1b email:<a href='/type/string'>string</a> = <a href='/type/account.EmailVerified'>account.EmailVerified</a>;
---functions---
account.sendVerifyEmailCode#98e037bb purpose:EmailVerifyPurpose email:string = account.SentEmailCode;
account.verifyEmail#32da4cf purpose:EmailVerifyPurpose verification:EmailVerification = account.EmailVerified;
auth.resetLoginEmail#7e960193 phone_number:string phone_code_hash:string = auth.SentCode;</code></pre>
<p>Telegram may return a <a href="/constructor/auth.sentCodeTypeSetUpEmailRequired">auth.sentCodeTypeSetUpEmailRequired</a> code type in the <a href="/constructor/auth.sentCode">auth.sentCode</a> constructor returned by <a href="/method/auth.sendCode">auth.sendCode</a>.<br>In this case, clients should ask the user to verify an email address that will be used to receive the login code as follows: </p>
<a href='/method/account.sendVerifyEmailCode'>account.sendVerifyEmailCode</a>#98e037bb purpose:<a href='/type/EmailVerifyPurpose'>EmailVerifyPurpose</a> email:<a href='/type/string'>string</a> = <a href='/type/account.SentEmailCode'>account.SentEmailCode</a>;
<a href='/method/account.verifyEmail'>account.verifyEmail</a>#32da4cf purpose:<a href='/type/EmailVerifyPurpose'>EmailVerifyPurpose</a> verification:<a href='/type/EmailVerification'>EmailVerification</a> = <a href='/type/account.EmailVerified'>account.EmailVerified</a>;
<a href='/method/auth.resetLoginEmail'>auth.resetLoginEmail</a>#7e960193 phone_number:<a href='/type/string'>string</a> phone_code_hash:<a href='/type/string'>string</a> = <a href='/type/auth.SentCode'>auth.SentCode</a>;</code></pre>
<p>Telegram may return a <a href="/constructor/auth.sentCodeTypeSetUpEmailRequired">auth.sentCodeTypeSetUpEmailRequired</a> code type in the <a href="/constructor/auth.sentCode">auth.sentCode</a> constructor returned by <a href="/method/auth.sendCode">auth.sendCode</a>.<br>
In this case, clients should ask the user to verify an email address that will be used to receive the login code as follows: </p>
<ul>
<li><p>If the <code>google_signin_allowed</code> or <code>apple_signin_allowed</code> flags are set, users can directly verify their email with Google/Apple ID as specified <a href="https://developers.google.com/identity/sign-in/android/sign-in">here (Google ID) &raquo;</a> and <a href="https://developer.apple.com/documentation/sign_in_with_apple">here (Apple ID) &raquo;</a>.<br>After obtaining the ID token, call <a href="/method/account.verifyEmail">account.verifyEmail</a>, providing the following parameters:</p>
<li>
<p>If the <code>google_signin_allowed</code> or <code>apple_signin_allowed</code> flags are set, users can directly verify their email with Google/Apple ID as specified <a href="https://developers.google.com/identity/sign-in/android/sign-in">here (Google ID) »</a> and <a href="https://developer.apple.com/documentation/sign_in_with_apple">here (Apple ID) »</a>.<br>
After obtaining the ID token, call <a href="/method/account.verifyEmail">account.verifyEmail</a>, providing the following parameters:</p>
<ul>
<li><code>purpose</code> - A <a href="/constructor/emailVerifyPurposeLoginSetup">emailVerifyPurposeLoginSetup</a> constructor</li>
<li><code>purpose.phone_number</code> - The phone number used with <a href="/method/auth.sendCode">auth.sendCode</a></li>
@ -161,9 +184,10 @@ auth.resetLoginEmail#7e960193 phone_number:string phone_code_hash:string = auth.
<li><code>verification</code> - <a href="/constructor/emailVerificationGoogle">emailVerificationGoogle</a> or <a href="/constructor/emailVerificationApple">emailVerificationApple</a></li>
<li><code>verification.token</code> - The ID token returned by the Google ID API.</li>
</ul>
<p>On success, the <a href="/method/account.verifyEmail">account.verifyEmail</a> method will return a <a href="/constructor/account.emailVerifiedLogin">account.emailVerifiedLogin</a> constructor with an <a href="/constructor/auth.sentCode">auth.sentCode</a> constructor that should be handled <a href="#code-types">as usual &raquo;</a>. </p>
<p>On success, the <a href="/method/account.verifyEmail">account.verifyEmail</a> method will return a <a href="/constructor/account.emailVerifiedLogin">account.emailVerifiedLogin</a> constructor with an <a href="/constructor/auth.sentCode">auth.sentCode</a> constructor that should be handled <a href="#code-types">as usual »</a>. </p>
</li>
<li><p>Otherwise, ask the user to enter an email address and then call <a href="/method/account.sendVerifyEmailCode">account.sendVerifyEmailCode</a>, providing the following parameters:</p>
<li>
<p>Otherwise, ask the user to enter an email address and then call <a href="/method/account.sendVerifyEmailCode">account.sendVerifyEmailCode</a>, providing the following parameters:</p>
<ul>
<li><code>email</code> - The email address</li>
<li><code>purpose</code> - A <a href="/constructor/emailVerifyPurposeLoginSetup">emailVerifyPurposeLoginSetup</a> constructor</li>
@ -178,42 +202,44 @@ auth.resetLoginEmail#7e960193 phone_number:string phone_code_hash:string = auth.
<li><code>verification</code> - <a href="/constructor/emailVerificationCode">emailVerificationCode</a></li>
<li><code>verification.code</code> - The verification code received by the user.</li>
</ul>
<p>On success, the <a href="/method/account.verifyEmail">account.verifyEmail</a> method will return a <a href="/constructor/account.emailVerifiedLogin">account.emailVerifiedLogin</a> constructor with an <a href="/constructor/auth.sentCode">auth.sentCode</a> constructor that should be handled <a href="#code-types">as usual &raquo;</a>. </p>
<p>On success, the <a href="/method/account.verifyEmail">account.verifyEmail</a> method will return a <a href="/constructor/account.emailVerifiedLogin">account.emailVerifiedLogin</a> constructor with an <a href="/constructor/auth.sentCode">auth.sentCode</a> constructor that should be handled <a href="#code-types">as usual »</a>. </p>
</li>
</ul>
<p>If the user cannot access their email address, an email reset may be requested using <a href="/method/auth.resetLoginEmail">auth.resetLoginEmail</a>. </p>
<p>To change the login email after login, pass <a href="/constructor/emailVerifyPurposeLoginChange">emailVerifyPurposeLoginChange</a> as <code>purpose</code>, following the exact same Google ID/Apple ID/email code login flow as above: on success, the <a href="/method/account.verifyEmail">account.verifyEmail</a> method will return an <a href="/constructor/account.emailVerified">account.emailVerified</a> constructor.</p>
<h3><a class="anchor" name="sign-in-sign-up" href="#sign-in-sign-up"><i class="anchor-icon"></i></a>Sign in/sign up</h3>
<h3><a class="anchor" href="#sign-in-sign-up" id="sign-in-sign-up" name="sign-in-sign-up"><i class="anchor-icon"></i></a>Sign in/sign up</h3>
<p>When user enters verification code, the <a href="/method/auth.signIn">auth.signIn</a> method must be used to validate it and possibly sign user in.</p>
<p>If the code was entered correctly, but the method returns <a href="/constructor/auth.authorizationSignUpRequired">auth.authorizationSignUpRequired</a>, it means that account with this phone number doesn&#39;t exist yet: user needs to provide basic information, accept terms of service and then the new user registration method (<a href="/method/auth.signUp">auth.signUp</a>) must be invoked.</p>
<h3><a class="anchor" name="2fa" href="#2fa"><i class="anchor-icon"></i></a>2FA</h3>
<p>When trying to sign in using <a href="/method/auth.signIn">auth.signIn</a>, an <a href="/method/auth.signIn#possible-errors">error 400 SESSION_PASSWORD_NEEDED</a> may be returned, if the user has two-factor authentication enabled.<br>In this case, instructions for <a href="/api/srp">SRP 2FA authentication</a> must be followed.</p>
<p>If the code was entered correctly, but the method returns <a href="/constructor/auth.authorizationSignUpRequired">auth.authorizationSignUpRequired</a>, it means that account with this phone number doesn't exist yet: user needs to provide basic information, accept terms of service and then the new user registration method (<a href="/method/auth.signUp">auth.signUp</a>) must be invoked.</p>
<h3><a class="anchor" href="#2fa" id="2fa" name="2fa"><i class="anchor-icon"></i></a>2FA</h3>
<p>When trying to sign in using <a href="/method/auth.signIn">auth.signIn</a>, an <a href="/method/auth.signIn#possible-errors">error 400 SESSION_PASSWORD_NEEDED</a> may be returned, if the user has two-factor authentication enabled.
In this case, instructions for <a href="/api/srp">SRP 2FA authentication</a> must be followed.</p>
<p>To set up two-factor authorization on an already authorized account, follow the <a href="/api/srp">SRP 2FA authentication docs</a>.</p>
<h3><a class="anchor" name="confirming-login" href="#confirming-login"><i class="anchor-icon"></i></a>Confirming login</h3>
<pre><code>authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true password_pending:flags.2?true encrypted_requests_disabled:flags.3?true call_requests_disabled:flags.4?true unconfirmed:flags.5?true hash:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization;
<h3><a class="anchor" href="#confirming-login" id="confirming-login" name="confirming-login"><i class="anchor-icon"></i></a>Confirming login</h3>
<pre><code><a href='/constructor/authorization'>authorization</a>#ad01d61d flags:<a href='/type/%23'>#</a> current:flags.0?<a href='/constructor/true'>true</a> official_app:flags.1?<a href='/constructor/true'>true</a> password_pending:flags.2?<a href='/constructor/true'>true</a> encrypted_requests_disabled:flags.3?<a href='/constructor/true'>true</a> call_requests_disabled:flags.4?<a href='/constructor/true'>true</a> unconfirmed:flags.5?<a href='/constructor/true'>true</a> hash:<a href='/type/long'>long</a> device_model:<a href='/type/string'>string</a> platform:<a href='/type/string'>string</a> system_version:<a href='/type/string'>string</a> api_id:<a href='/type/int'>int</a> app_name:<a href='/type/string'>string</a> app_version:<a href='/type/string'>string</a> date_created:<a href='/type/int'>int</a> date_active:<a href='/type/int'>int</a> ip:<a href='/type/string'>string</a> country:<a href='/type/string'>string</a> region:<a href='/type/string'>string</a> = <a href='/type/Authorization'>Authorization</a>;
account.authorizations#4bff8ea0 authorization_ttl_days:int authorizations:Vector&lt;Authorization&gt; = account.Authorizations;
<a href='/constructor/account.authorizations'>account.authorizations</a>#4bff8ea0 authorization_ttl_days:<a href='/type/int'>int</a> authorizations:<a href='/type/Vector%20t'>Vector</a>&lt;<a href='/type/Authorization'>Authorization</a>&gt; = <a href='/type/account.Authorizations'>account.Authorizations</a>;
updateNewAuthorization#8951abef flags:# unconfirmed:flags.0?true hash:long date:flags.0?int device:flags.0?string location:flags.0?string = Update;
<a href='/constructor/updateNewAuthorization'>updateNewAuthorization</a>#8951abef flags:<a href='/type/%23'>#</a> unconfirmed:flags.0?<a href='/constructor/true'>true</a> hash:<a href='/type/long'>long</a> date:flags.0?<a href='/type/int'>int</a> device:flags.0?<a href='/type/string'>string</a> location:flags.0?<a href='/type/string'>string</a> = <a href='/type/Update'>Update</a>;
---functions---
account.getAuthorizations#e320c158 = account.Authorizations;
<a href='/method/account.getAuthorizations'>account.getAuthorizations</a>#e320c158 = <a href='/type/account.Authorizations'>account.Authorizations</a>;
account.changeAuthorizationSettings#40f48462 flags:# confirmed:flags.3?true hash:long encrypted_requests_disabled:flags.0?Bool call_requests_disabled:flags.1?Bool = Bool;
<a href='/method/account.changeAuthorizationSettings'>account.changeAuthorizationSettings</a>#40f48462 flags:<a href='/type/%23'>#</a> confirmed:flags.3?<a href='/constructor/true'>true</a> hash:<a href='/type/long'>long</a> encrypted_requests_disabled:flags.0?<a href='/type/Bool'>Bool</a> call_requests_disabled:flags.1?<a href='/type/Bool'>Bool</a> = <a href='/type/Bool'>Bool</a>;
account.resetAuthorization#df77f3bc hash:long = Bool;</code></pre>
<p>When logging in, other logged-in sessions will receive an <a href="/constructor/updateNewAuthorization">updateNewAuthorization</a> update.<br>If the <code>unconfirmed</code> flag is set, clients should display a notification, asking the user if they recognize the session. </p>
<p>If the user clicks on the Yes button, invoke <a href="/method/account.changeAuthorizationSettings">account.changeAuthorizationSettings</a> with the new session&#39;s <code>hash</code> and the <code>confirmed</code> flag set, confirming the specified session. </p>
<p>If the user clicks on the No button, invoke <a href="/method/account.resetAuthorization">account.resetAuthorization</a> with the new session&#39;s <code>hash</code>, logging out the specified session. </p>
<p>If no action is taken by the user, the session will be autoconfirmed <code>authorization_autoconfirm_period</code> seconds after login (see the associated <a href="/api/config#authorization-autoconfirm-period">client configuration parameter &raquo;</a>). </p>
<h3><a class="anchor" name="invalidating-login-codes" href="#invalidating-login-codes"><i class="anchor-icon"></i></a>Invalidating login codes</h3>
<p>Telegram&#39;s servers will automatically invalidate login codes if they are sent by the user to another Telegram chat, either by forwarding them or by sending them inside of a message: however, clients should also manually and immediately invalidate login codes if the user attempts to screenshot or forward a message sent by the login notification service user (ID <code>777000</code>) containing login codes. </p>
<a href='/method/account.resetAuthorization'>account.resetAuthorization</a>#df77f3bc hash:<a href='/type/long'>long</a> = <a href='/type/Bool'>Bool</a>;</code></pre>
<p>When logging in, other logged-in sessions will receive an <a href="/constructor/updateNewAuthorization">updateNewAuthorization</a> update.<br>
If the <code>unconfirmed</code> flag is set, clients should display a notification, asking the user if they recognize the session. </p>
<p>If the user clicks on the Yes button, invoke <a href="/method/account.changeAuthorizationSettings">account.changeAuthorizationSettings</a> with the new session's <code>hash</code> and the <code>confirmed</code> flag set, confirming the specified session. </p>
<p>If the user clicks on the No button, invoke <a href="/method/account.resetAuthorization">account.resetAuthorization</a> with the new session's <code>hash</code>, logging out the specified session. </p>
<p>If no action is taken by the user, the session will be autoconfirmed <code>authorization_autoconfirm_period</code> seconds after login (see the associated <a href="/api/config#authorization-autoconfirm-period">client configuration parameter »</a>). </p>
<h3><a class="anchor" href="#invalidating-login-codes" id="invalidating-login-codes" name="invalidating-login-codes"><i class="anchor-icon"></i></a>Invalidating login codes</h3>
<p>Telegram's servers will automatically invalidate login codes if they are sent by the user to another Telegram chat, either by forwarding them or by sending them inside of a message: however, clients should also manually and immediately invalidate login codes if the user attempts to screenshot or forward a message sent by the login notification service user (ID <code>777000</code>) containing login codes. </p>
<p>If an incoming message that is:</p>
<ul>
<li>Sent by the login notification service user (ID <code>777000</code>)</li>
<li>AND is a text message (not a media)</li>
<li>AND contains one or more login codes, defined as a sequence of 5 to 7 decimal digits, optionally interleaved with or followed by any number of <code>-</code> characters (<a href="https://github.com/tdlib/td/blob/07c1d53a6d3cb1fad58d2822e55eef6d57363581/td/telegram/MessagesManager.cpp#L6513">example implementation &raquo;</a>)</li>
<li>AND contains one or more login codes, defined as a sequence of 5 to 7 decimal digits, optionally interleaved with or followed by any number of <code>-</code> characters (<a href="https://github.com/tdlib/td/blob/07c1d53a6d3cb1fad58d2822e55eef6d57363581/td/telegram/MessagesManager.cpp#L6513">example implementation »</a>)</li>
</ul>
<p>Is either:</p>
<ul>
@ -223,8 +249,8 @@ account.resetAuthorization#df77f3bc hash:long = Bool;</code></pre>
<p><a href="/method/account.invalidateSignInCodes">account.invalidateSignInCodes</a> should be invoked, passing the extracted login <code>codes</code> (excluding any <code>-</code> characters). </p>
<pre><code>---functions---
account.invalidateSignInCodes#ca8ae8ba codes:Vector&lt;string&gt; = Bool;</code></pre>
<h3><a class="anchor" name="test-accounts" href="#test-accounts"><i class="anchor-icon"></i></a>Test Accounts</h3>
<a href='/method/account.invalidateSignInCodes'>account.invalidateSignInCodes</a>#ca8ae8ba codes:<a href='/type/Vector%20t'>Vector</a>&lt;<a href='/type/string'>string</a>&gt; = <a href='/type/Bool'>Bool</a>;</code></pre>
<h3><a class="anchor" href="#test-accounts" id="test-accounts" name="test-accounts"><i class="anchor-icon"></i></a>Test Accounts</h3>
<p>Each phone number is limited to only a certain amount of logins per day (e.g. 5, but this is subject to change) after which the API will return a FLOOD error until the next day. This might not be enough for testing the implementation of User Authorization flows in client applications.</p>
<p>There are several reserved phone number prefixes for testing that your application handles redirects between DCs, sign up, sign in and 2FA flows correctly. These numbers are only available on <strong>Test DCs</strong> (their IP addresses for TCP transport are available in <a href="https://my.telegram.org/apps">API development tools</a> panel after <a href="https://core.telegram.org/api/obtaining_api_id#obtaining-api-id">api_id was obtained</a>, <a href="https://core.telegram.org/mtproto/transports#uri-format">URI format</a> for HTTPS/WebSocket transport).</p>
<p>If you wish to emulate an application of a user associated with DC number X, it is sufficient to specify the phone number as <code>99966XYYYY</code>, where YYYY are random numbers, when registering the user. A user like this would always get XXXXX as the login confirmation code (the DC number, repeated five times). Note that the value of X must be in the range of 1-3 because there are only 3 Test DCs. When the flood limit is reached for any particular test number, just choose another number (changing the YYYY random part).</p>
@ -233,8 +259,8 @@ account.invalidateSignInCodes#ca8ae8ba codes:Vector&lt;string&gt; = Bool;</code>
<blockquote>
<p>To help you with working on production DCs, logins with the same phone number with which the <code>api_id</code> was registered have more generous flood limits.</p>
</blockquote>
<h3><a class="anchor" name="we-are-authorized" href="#we-are-authorized"><i class="anchor-icon"></i></a>We are authorized</h3>
<p>As a result of authorization, the client key, <strong>auth_key_id</strong>, becomes associated with the user, and each subsequent API call with this key will be executed with that user&#39;s identity. The authorization method itself returns the relevant user. It is best to immediately store the User ID locally in a binding with the key.</p>
<h3><a class="anchor" href="#we-are-authorized" id="we-are-authorized" name="we-are-authorized"><i class="anchor-icon"></i></a>We are authorized</h3>
<p>As a result of authorization, the client key, <strong>auth_key_id</strong>, becomes associated with the user, and each subsequent API call with this key will be executed with that user's identity. The authorization method itself returns the relevant user. It is best to immediately store the User ID locally in a binding with the key.</p>
<p>Only a small portion of the API methods are available to <strong>unauthorized</strong> users:</p>
<ul>
<li><a href="/method/auth.sendCode">auth.sendCode</a></li>
@ -255,8 +281,7 @@ account.invalidateSignInCodes#ca8ae8ba codes:Vector&lt;string&gt; = Bool;</code>
<li><a href="/method/langpack.getLanguages">langpack.getLanguages</a></li>
<li><a href="/method/langpack.getLanguage">langpack.getLanguage</a></li>
</ul>
<p>Other methods will result in an error: <a href="/api/errors#401-unauthorized"><strong>401 UNAUTHORIZED</strong></a>.</p>
</div>
<p>Other methods will result in an error: <a href="/api/errors#401-unauthorized"><strong>401 UNAUTHORIZED</strong></a>.</p></div>
</div>

View file

@ -49,7 +49,7 @@
<p>Nested entities are supported.</p>
<h3><a class="anchor" href="#entity-length" id="entity-length" name="entity-length"><i class="anchor-icon"></i></a>Entity length</h3>
<p>Special care must be taken to consider the length of strings when generating message entities as the number of <a href="https://en.wikipedia.org/wiki/UTF-16">UTF-16</a> code units, even if the message itself must be encoded using UTF-8. </p>
<p>Example implementations: <a href="https://github.com/tdlib/td/tree/master/td/telegram/MessageEntity.cpp">tdlib</a>, <a href="https://github.com/danog/MadelineProto/blob/v8/src/TL/Conversion/DOMEntities.php">MadelineProto</a>.</p>
<p>Example implementations: <a href="https://github.com/tdlib/td/tree/master/td/telegram/MessageEntity.cpp">tdlib</a>, <a href="https://github.com/danog/telegram-entities/blob/master/src/Entities.php">MadelineProto</a>.</p>
<h4><a class="anchor" href="#unicode-codepoints-and-encoding" id="unicode-codepoints-and-encoding" name="unicode-codepoints-and-encoding"><i class="anchor-icon"></i></a>Unicode codepoints and encoding</h4>
<p>A <a href="https://en.wikipedia.org/wiki/Unicode">Unicode</a> <a href="https://en.wikipedia.org/wiki/Code_point">code point</a> is a number ranging from <code>0x0</code> to <code>0x10FFFF</code>, usually represented using <code>U+0000</code> to <code>U+10FFFF</code> syntax.<br>
Unicode defines a codespace of 1,112,064 assignable code points within the <code>U+0000</code> to <code>U+10FFFF</code> range.<br>
@ -85,7 +85,7 @@ for byte in text {
}
}</code></pre>
<p><strong>Note</strong>: the <em>length</em> of an entity <strong>must not</strong> include the length of trailing newlines or whitespaces, <code>rtrim</code> entities before computing their length: however, the next <em>offset</em> <strong>must</strong> include the length of newlines or whitespaces that precede it. </p>
<p>Example implementations: <a href="https://github.com/tdlib/td/tree/master/td/telegram/MessageEntity.cpp">tdlib</a>, <a href="https://github.com/danog/MadelineProto/blob/v8/src/TL/Conversion/DOMEntities.php">MadelineProto</a>.</p>
<p>Example implementations: <a href="https://github.com/tdlib/td/tree/master/td/telegram/MessageEntity.cpp">tdlib</a>, <a href="https://github.com/danog/telegram-entities/blob/master/src/Entities.php">MadelineProto</a>.</p>
<h3><a class="anchor" href="#allowed-entities" id="allowed-entities" name="allowed-entities"><i class="anchor-icon"></i></a>Allowed entities</h3>
<p>For example the following HTML/Markdown aliases for message entities can be used:</p>
<ul>

View file

@ -48,10 +48,10 @@
<ul>
<li><a href="/bots/features">Detailed Guide to Bot Features</a></li>
<li><a href="/bots/api">Full API Reference for Developers</a></li>
<li><a href="/bots/tutorial">Basic Tutorial: From @BotFather to &#39;Hello World&#39;</a></li>
<li><a href="/bots/tutorial">Basic Tutorial: From @BotFather to 'Hello World'</a></li>
</ul>
<p>The <strong>Telegram Bot Platform</strong> hosts more than <strong>10 million</strong> bots and is <strong>free</strong> for both users and developers.</p>
<h3><a class="anchor" name="what-can-you-do-with-bots" href="#what-can-you-do-with-bots"><i class="anchor-icon"></i></a>What Can You Do with Bots?</h3>
<h3><a class="anchor" href="#what-can-you-do-with-bots" id="what-can-you-do-with-bots" name="what-can-you-do-with-bots"><i class="anchor-icon"></i></a>What Can You Do with Bots?</h3>
<ul>
<li><a href="#replace-entire-websites">Replace Entire Websites</a></li>
<li><a href="#manage-your-business">Manage Your Business</a></li>
@ -62,115 +62,107 @@
<li><a href="#build-social-networks">Build Social Networks</a></li>
<li><a href="#anything-else">Anything Else!</a></li>
</ul>
<h4><a class="anchor" name="replace-entire-websites" href="#replace-entire-websites"><i class="anchor-icon"></i></a>Replace Entire Websites</h4>
<h4><a class="anchor" href="#replace-entire-websites" id="replace-entire-websites" name="replace-entire-websites"><i class="anchor-icon"></i></a>Replace Entire Websites</h4>
<p>Telegram bots can host <a href="/bots/webapps">Mini Apps</a> built with <em>JavaScript</em>. This allows for <strong>infinitely flexible</strong> interfaces that can power everything from online stores to arcade games. Unlike websites, bots support <a href="/api/url-authorization">seamless authorization</a> and notifications through Telegram out of the box.</p>
<div class="blog_video_player_wrap" style="max-width: 600px; margin: 20px auto 20px;">
<video class="blog_video_player tl_blog_vid_autoplay" onclick="videoTogglePlay(this)" autoplay loop controls muted poster="/file/464001434/100bf/eWprjdgzEbE.100386/644bbea83084f44c8f" style="max-width: 600px;" title="console.log('Vive la révolution')" alt="Bot Revolution">
<source src="/file/464001679/11aa9/KQx_BlPVXRo.4922145.mp4/c65433c8ac11a347a8" type="video/mp4">
</video>
</source></video>
</div>
<blockquote>
<p>Try <a href="https://t.me/durgerkingbot">@DurgerKingBot</a> or check out the <a href="/bots/webapps">dedicated guide to Web Apps</a> to build your own.</p>
<p>Try <a href="https://t.me/durgerkingbot">@DurgerKingBot</a>  or check out the <a href="/bots/webapps">dedicated guide to Web Apps</a> to build your own.</p>
</blockquote>
<h4><a class="anchor" name="manage-your-business" href="#manage-your-business"><i class="anchor-icon"></i></a>Manage Your Business</h4>
<h4><a class="anchor" href="#manage-your-business" id="manage-your-business" name="manage-your-business"><i class="anchor-icon"></i></a>Manage Your Business</h4>
<p><a href="https://telegram.org/blog/telegram-business">Telegram Business</a> users can connect Telegram bots to process and answer messages <strong>on their behalf</strong>, via their personal account. This allows businesses to <strong>seamlessly integrate</strong> any existing tools and workflows, or add new AI assistants to <strong>increase productivity</strong>.</p>
<p>As we continue to expand the set of <strong>free tools</strong> <a href="https://core.telegram.org/bots">available to bots</a> through this integration, we encourage all developers to <strong>innovate</strong> and <strong>develop</strong> useful applications and services for <strong>businesses</strong> on Telegram.</p>
<div class="blog_video_player_wrap" style="max-width: 600px; margin: 20px auto 20px;">
<video class="blog_video_player tl_blog_vid_autoplay" onclick="videoTogglePlay(this)" autoplay loop controls muted poster="/file/400780400238/1/x875tPT245w.58064/1b426d3eda0a923c03" style="max-width: 600px;" title="" alt="Chatbots for Business">
<source src="/file/400780400382/1/BVN6m4W5a6w.4289566.mp4/9dc47caab261eaade4" type="video/mp4">
</video>
</source></video>
</div>
<blockquote>
<p>Developers can turn on <a href="https://core.telegram.org/bots/features#bots-for-business">Business Mode</a> in <a href="https://t.me/BotFather">@BotFather</a> if their bot supports <a href="https://core.telegram.org/bots/api#businessconnection">integration</a> with Telegram Business accounts.</p>
</blockquote>
<h5><a class="anchor" name="receive-payments" href="#receive-payments"><i class="anchor-icon"></i></a>Receive Payments</h5>
<p>Bots can sell all kinds of goods and services on Telegram to anyone in the world. <a href="https://telegram.org/blog/telegram-stars">Telegram Stars</a> allow users to securely and effortlessly buy <strong>digital products</strong> via in-app purchases. In addition, <strong>physical products</strong> can be purchased through more than 20 <a href="https://core.telegram.org/bots/payments#supported-payment-providers">integrated payment providers</a>.</p>
<h5><a class="anchor" href="#receive-payments" id="receive-payments" name="receive-payments"><i class="anchor-icon"></i></a>Receive Payments</h5>
<p>Bots can sell all kinds of goods and services on Telegram  to anyone in the world. <a href="https://telegram.org/blog/telegram-stars">Telegram Stars</a> allow users to securely and effortlessly buy <strong>digital products</strong> via in-app purchases. In addition, <strong>physical products</strong> can be purchased through more than 20 <a href="https://core.telegram.org/bots/payments#supported-payment-providers">integrated payment providers</a>.</p>
<div class="blog_video_player_wrap" style="max-width: 600px; margin: 20px auto 20px;">
<video class="blog_video_player tl_blog_vid_autoplay" onclick="videoTogglePlay(this)" autoplay loop controls muted poster="/file/464001866/10889/GZJM7zyZ6UE.105798/32d6a4d1d4f0b13355" style="max-width: 600px;" title="If your pizza place can't deliver a clone army, you're buying pizza from the wrong shop." alt="Video: Ordering a pizza through a Telegram channel">
<source src="/file/464001417/10bf1/nIRBV1iB0NY.3878528.mp4/c95b8092ce1ece10ef" type="video/mp4">
</video>
</source></video>
</div>
<blockquote>
<p>Try <a href="https://t.me/shopbot">@ShopBot</a> or check out our dedicated guides for <a href="https://core.telegram.org/bots/payments-stars">digital</a> and <a href="https://core.telegram.org/bots/payments">physical</a> products to build your own.</p>
</blockquote>
<h4><a class="anchor" name="create-custom-tools" href="#create-custom-tools"><i class="anchor-icon"></i></a>Create Custom Tools</h4>
<h4><a class="anchor" href="#create-custom-tools" id="create-custom-tools" name="create-custom-tools"><i class="anchor-icon"></i></a>Create Custom Tools</h4>
<p>Increase your productivity by creating bots for <strong>specific tasks</strong> like converting files, managing chats or fetching todays forecast. Users can chat directly with bots, or add them to groups and channels to introduce extra features.</p>
<div class="blog_video_player_wrap" style="max-width: 600px; margin: 20px auto 20px;">
<video class="blog_video_player tl_blog_vid_autoplay" onclick="videoTogglePlay(this)" autoplay loop controls muted poster="/file/464001084/12c1d/eNLdXm8moqA.134736/e28dd8ea6d49eee57d" style="max-width: 600px;" title="" alt="Custom tools">
<source src="/file/464001127/10a99/GC0dSHYQTb0.3621529.mp4/75439f14147e13b6fb" type="video/mp4">
</video>
</source></video>
</div>
<blockquote>
<p>Try <a href="https://t.me/quizbot">@QuizBot</a> to combine several quiz-style polls into a <a href="https://telegram.org/tour/quizbot">proper quiz</a>.</p>
</blockquote>
<h4><a class="anchor" name="integrate-with-other-services" href="#integrate-with-other-services"><i class="anchor-icon"></i></a>Integrate with Other Services</h4>
<p>Many popular platforms already have official Telegram bots, which allow users to comfortably access content in one app or perform quick searches using <a href="/bots/inline">inline mode</a>.</p>
<h4><a class="anchor" href="#integrate-with-other-services" id="integrate-with-other-services" name="integrate-with-other-services"><i class="anchor-icon"></i></a>Integrate with Other Services</h4>
<p>Many popular platforms already have official Telegram bots, which allow users to comfortably access content in one app  or perform quick searches using <a href="/bots/inline">inline mode</a>.</p>
<div style="max-width: 600px; margin: 20px auto 20px;">
<a href="/file/464001186/11e04/7XO37b9iccE.133932/a29f8bf593af567fcc" target="_blank"><img src="/file/464001186/11e04/7XO37b9iccE.133932/a29f8bf593af567fcc" title="Gmail bot" class="dev_page_image" style="max-width: 600px;" /></a>
<a href="/file/464001186/11e04/7XO37b9iccE.133932/a29f8bf593af567fcc" target="_blank"><img src="/file/464001186/11e04/7XO37b9iccE.133932/a29f8bf593af567fcc" title="Gmail bot" class="dev_page_image" style="max-width: 600px;"></a>
</div>
<blockquote>
<p>Try <a href="https://t.me/gmailbot">@GMailBot</a>, <a href="https://t.me/githubbot">@GitHubBot</a>, <a href="https://t.me/bing">@Bing</a>, <a href="https://t.me/youtube">@YouTube</a>, <a href="https://t.me/wiki">@wiki</a> and more.</p>
</blockquote>
<h4><a class="anchor" name="host-games" href="#host-games"><i class="anchor-icon"></i></a>Host Games</h4>
<h4><a class="anchor" href="#host-games" id="host-games" name="host-games"><i class="anchor-icon"></i></a>Host Games</h4>
<p>Using <a href="/bots/games">HTML5</a>, developers can create immersive single or multi-player games that allow users to <strong>team up</strong> or <strong>compete</strong> for the highest score.</p>
<div class="blog_video_player_wrap" style="max-width: 600px; margin: 20px auto 20px;">
<video class="blog_video_player tl_blog_vid_autoplay" onclick="videoTogglePlay(this)" autoplay loop controls muted poster="/file/464001988/109f0/_Bu1DzRXl1o.145338/e58b7165e08ecbb936" style="max-width: 600px;" title="" alt="">
<source src="/file/464001693/1044a/rZXmc2EPIqY.3678215.mp4/94b37cec71e8e6287e" type="video/mp4">
</video>
</source></video>
</div>
<blockquote>
<p>Try <a href="https://t.me/gamee">@Gamee</a> and <a href="https://t.me/gamebot">@GameBot</a> or check out the <a href="/bots/games">HTML5 Games Manual</a> to build your own. </p>
<p>Try <a href="https://t.me/gamee">@Gamee</a> and <a href="https://t.me/gamebot">@GameBot</a>  or check out the <a href="/bots/games">HTML5 Games Manual</a> to build your own. </p>
</blockquote>
<h4><a class="anchor" name="build-social-networks" href="#build-social-networks"><i class="anchor-icon"></i></a>Build Social Networks</h4>
<h4><a class="anchor" href="#build-social-networks" id="build-social-networks" name="build-social-networks"><i class="anchor-icon"></i></a>Build Social Networks</h4>
<p>Bots can serve as an intermediary to connect users based on shared interests, location, and more. Coordinate meetups, show local services, or help people sell second-hand items.</p>
<div class="blog_video_player_wrap" style="max-width: 600px; margin: 20px auto 20px;">
<video class="blog_video_player tl_blog_vid_autoplay" onclick="videoTogglePlay(this)" autoplay loop controls muted poster="/file/464001041/10ebf/BPN6BLcuS8I.137509/fd81647baa51b928a2" style="max-width: 600px;" title="" alt="">
<source src="/file/464001262/106bf/TVxoe4U0kIY.2116862.mp4/db7dfd397afbe2a61c" type="video/mp4">
</video>
</source></video>
</div>
<h4><a class="anchor" name="anything-else" href="#anything-else"><i class="anchor-icon"></i></a>Anything Else</h4>
<h4><a class="anchor" href="#anything-else" id="anything-else" name="anything-else"><i class="anchor-icon"></i></a>Anything Else</h4>
<p>The possibilities for bots are endless from simple scripts to complex mini apps. Whether youre a beginner or professional programmer, you can create personalized tools with the help of the <a href="/bots/api">Bot Platform</a>.</p>
<hr>
<h3><a class="anchor" name="how-do-bots-work" href="#how-do-bots-work"><i class="anchor-icon"></i></a>How Do Bots Work?</h3>
<h3><a class="anchor" href="#how-do-bots-work" id="how-do-bots-work" name="how-do-bots-work"><i class="anchor-icon"></i></a>How Do Bots Work?</h3>
<blockquote>
<p>For a detailed explanation of Bot Features, see <a href="/bots/features">this guide</a> </p>
</blockquote>
<p>Telegram bots are special accounts that do not need a phone number to set up. Bots are connected to their owners server, which processes inputs and requests from users.</p>
<p>Telegrams intermediary server handles all encryption and communication with the Telegram API. Developers communicate with this server via an easy HTTPS-interface with a simplified version of the <a href="/api">Telegram API</a> known as the <a href="/bots/api">Bot API</a>.</p>
<h4><a class="anchor" name="how-are-bots-different-from-users" href="#how-are-bots-different-from-users"><i class="anchor-icon"></i></a>How Are Bots Different from Users?</h4>
<h4><a class="anchor" href="#how-are-bots-different-from-users" id="how-are-bots-different-from-users" name="how-are-bots-different-from-users"><i class="anchor-icon"></i></a>How Are Bots Different from Users?</h4>
<p>Bots are able to process inputs and requests in ways that user accounts cant, but there are several differences between a bot and a normal user.</p>
<ul>
<li>Bots dont have last seen or online statuses instead they show a bot label in the chat.</li>
<li>Bots have limited cloud storage older messages may be removed by the server shortly after they have been processed.</li>
<li>Bots can&#39;t start conversations with users. A user must either add them to a group or send them a message first. People can search for your bots username or start a chat via its unique t.me/bot_username link.</li>
<li>Bots can't start conversations with users. A user must either add them to a group or send them a message first. People can search for your bots username or start a chat via its unique t.me/bot_username link.</li>
<li>By default, bots added to groups <strong>only see relevant messages</strong> in the chat (see <a href="/bots/features#privacy-mode">Privacy Mode</a>).</li>
<li>Bots never eat, sleep or complain (unless expressly programmed otherwise).</li>
</ul>
<h4><a class="anchor" name="bot-links" href="#bot-links"><i class="anchor-icon"></i></a>Bot Links</h4>
<h4><a class="anchor" href="#bot-links" id="bot-links" name="bot-links"><i class="anchor-icon"></i></a>Bot Links</h4>
<p>Bot usernames normally require a bot suffix, but some bots dont have them such as <a href="https://t.me/stickers">@stickers</a>, <a href="https://t.me/gif">@gif</a>, <a href="https://t.me/wiki">@wiki</a> or <a href="https://t.me/bing">@bing</a>. </p>
<p>Anyone can <a href="https://telegram.org/blog/shareable-folders-custom-wallpapers#bot-links-and-telegram-premium-on-fragment">assign collectible usernames</a> to bots, including those without the &#39;bot&#39; suffix.</p>
<h3><a class="anchor" name="how-do-i-create-a-bot" href="#how-do-i-create-a-bot"><i class="anchor-icon"></i></a>How Do I Create a Bot?</h3>
<p>Anyone can <a href="https://telegram.org/blog/shareable-folders-custom-wallpapers#bot-links-and-telegram-premium-on-fragment">assign collectible usernames</a> to bots, including those without the 'bot' suffix.</p>
<h3><a class="anchor" href="#how-do-i-create-a-bot" id="how-do-i-create-a-bot" name="how-do-i-create-a-bot"><i class="anchor-icon"></i></a>How Do I Create a Bot?</h3>
<p>Creating Telegram bots is super-easy, but you will need at least some skills in <strong>computer programming</strong>. </p>
<p>Creating a bot is streamlined by Telegrams Bot API, which gives the tools and framework required to integrate your code. To get started, message <a href="https://t.me/botfather">@BotFather</a> on Telegram to register your bot and receive its authentication token.</p>
<blockquote>
<p>Your <strong>bot token</strong> is its unique identifier store it in a <strong>secure place</strong>, and only share it with people who need direct access to the bot. Everyone who has your token will have <strong>full control</strong> over your bot.</p>
</blockquote>
<h4><a class="anchor" name="what-next" href="#what-next"><i class="anchor-icon"></i></a>What Next?</h4>
<h4><a class="anchor" href="#what-next" id="what-next" name="what-next"><i class="anchor-icon"></i></a>What Next?</h4>
<p>We recommend that you check out our guide to <a href="/bots/features">Bot Features</a> to see what you can teach your bot to do:</p>
<ul>
<li><a href="/bots/features">Detailed Guide to Bot Features</a></li>
<li><a href="/bots/api">Full API Reference for Developers</a></li>
<li><a href="/bots/tutorial">Basic Tutorial: From @BotFather to &#39;Hello World&#39;</a></li>
<li><a href="/bots/tutorial">Basic Tutorial: From @BotFather to 'Hello World'</a></li>
<li><a href="/bots/samples">Code Examples</a></li>
</ul>
</div>
</ul></div>
</div>

View file

@ -49,7 +49,7 @@
<li><a href="/bots">A General Bot Platform Overview</a></li>
<li><a href="/bots/api">Full API Reference for Developers</a></li>
</ul>
<h3><a class="anchor" name="what-features-do-bots-have" href="#what-features-do-bots-have"><i class="anchor-icon"></i></a>What features do bots have?</h3>
<h3><a class="anchor" href="#what-features-do-bots-have" id="what-features-do-bots-have" name="what-features-do-bots-have"><i class="anchor-icon"></i></a>What features do bots have?</h3>
<ul>
<li><a href="#inputs"><strong>Inputs</strong></a><ul>
<li><a href="#inputs">Text</a></li>
@ -84,22 +84,21 @@
<li><a href="#botfather"><strong>BotFather, creating and managing bots</strong></a></li>
</ul>
<hr>
<h3><a class="anchor" name="inputs" href="#inputs"><i class="anchor-icon"></i></a>Inputs</h3>
<p>Users can send <strong>messages of all types</strong> to bots, including text, files, locations, stickers, voice messages and even <a href="/bots/api#dice">dice</a> if they&#39;re feeling lucky. However, Telegram bots offer many other tools for building flexible interfaces tailored to your specific needs:</p>
<h3><a class="anchor" href="#inputs" id="inputs" name="inputs"><i class="anchor-icon"></i></a>Inputs</h3>
<p>Users can send <strong>messages of all types</strong> to bots, including text, files, locations, stickers, voice messages and even <a href="/bots/api#dice">dice</a> if they're feeling lucky. However, Telegram bots offer many other tools for building flexible interfaces tailored to your specific needs:</p>
<ul>
<li><a href="#commands">Commands</a> that are highlighted in messages and can be selected from a list after typing <code>/</code>.</li>
<li><a href="#keyboards">Keyboards</a> that replace the user&#39;s keyboard with predefined answer options.</li>
<li><a href="#keyboards">Keyboards</a> that replace the user's keyboard with predefined answer options.</li>
<li><a href="#inline-keyboards">Buttons</a> that are shown next to messages from the bot.</li>
</ul>
<p>For even more flexibility, <a href="#web-apps">Web Apps</a> support 100% custom interfaces with JavaScript. </p>
<div>
<a href="/file/464001858/11318/ahAJjwERIX8.164875/ce1372cbf73e3ea94e" target="_blank"><img src="/file/464001858/11318/ahAJjwERIX8.164875/ce1372cbf73e3ea94e" title="Inputs" class="dev_page_image" width=70% /></a>
<a href="/file/464001858/11318/ahAJjwERIX8.164875/ce1372cbf73e3ea94e" target="_blank"><img src="/file/464001858/11318/ahAJjwERIX8.164875/ce1372cbf73e3ea94e" title="Inputs" class="dev_page_image" width="70%"></a>
</div>
<blockquote>
<p><strong>Note:</strong> Telegram bots can support <a href="#language-support">multiple languages</a> that adapt to the users&#39; language settings in the app.</p>
<p><strong>Note:</strong> Telegram bots can support <a href="#language-support">multiple languages</a> that adapt to the users' language settings in the app.</p>
</blockquote>
<h4><a class="anchor" name="commands" href="#commands"><i class="anchor-icon"></i></a>Commands</h4>
<h4><a class="anchor" href="#commands" id="commands" name="commands"><i class="anchor-icon"></i></a>Commands</h4>
<p>A command is a simple <code>/keyword</code> that tells the bot what to do. Telegram apps will:</p>
<ul>
<li><strong>Highlight</strong> commands in messages. When the user taps a highlighted command, that command is immediately sent again.</li>
@ -114,61 +113,58 @@
<li>/newlocation </li>
<li>/newrule </li>
</ul>
<p>Commands should be <strong>as specific as possible</strong> for example <code>/newlocation</code> or <code>/newrule</code> <strong>is better</strong> than a <code>/new</code> command that then requires an additional parameter from the user like &quot;<em>location</em>“ or ”<em>rule</em>&quot;.</p>
<p>Commands should be <strong>as specific as possible</strong> for example <code>/newlocation</code> or <code>/newrule</code> <strong>is better</strong> than a <code>/new</code> command that then requires an additional parameter from the user like "<em>location</em>" or "<em>rule</em>".</p>
<div>
<a href="/file/464001775/10227/HCr0XgSUHrg.119089/c17ff5d34fe528361e" target="_blank"><img src="/file/464001775/10227/HCr0XgSUHrg.119089/c17ff5d34fe528361e" title="Commands" class="dev_page_image"
width=44% /></a>
<a href="/file/464001775/10227/HCr0XgSUHrg.119089/c17ff5d34fe528361e" target="_blank"><img src="/file/464001775/10227/HCr0XgSUHrg.119089/c17ff5d34fe528361e" title="Commands" class="dev_page_image" width="44%"></a>
</div>
<blockquote>
<p>We require <strong>all developers</strong> to support several <a href="#global-commands">Global Commands</a> to make sure Telegram bots offer a consistent and user-friendly experience.</p>
</blockquote>
<h5><a class="anchor" name="command-scopes" href="#command-scopes"><i class="anchor-icon"></i></a>Command Scopes</h5>
<p>Your bot is able to <strong>show different commands</strong> to different users and groups you can control this using <a href="/bots/api#botcommandscope">scopes</a>. For example, your bot could show additional commands to group admins or translate the list based on the users <a href="/bots/api#user">language_code</a>.</p>
<h5><a class="anchor" href="#command-scopes" id="command-scopes" name="command-scopes"><i class="anchor-icon"></i></a>Command Scopes</h5>
<p>Your bot is able to <strong>show different commands</strong> to different users and groups  you can control this using <a href="/bots/api#botcommandscope">scopes</a>. For example, your bot could show additional commands to group admins or translate the list based on the users <a href="/bots/api#user">language_code</a>.</p>
<blockquote>
<p>Keep in mind that Bot API <a href="/bots/api#update">updates</a> <strong>will not contain any information</strong> about the scope of a command sent by the user in fact, they may contain commands that dont exist at all in your bot. Your backend should <strong>always</strong> verify that received commands are valid and that the user was authorized to use them regardless of scope.</p>
</blockquote>
<blockquote>
<p>Bots with privacy mode enabled will only receive commands in groups under special conditions, <a href="#privacy-mode">see here</a>.</p>
</blockquote>
<h4><a class="anchor" name="keyboards" href="#keyboards"><i class="anchor-icon"></i></a>Keyboards</h4>
<h4><a class="anchor" href="#keyboards" id="keyboards" name="keyboards"><i class="anchor-icon"></i></a>Keyboards</h4>
<p>Bots are able to interpret free text input from users, but offering <strong>specific suggestions</strong> is often more intuitive this is where <strong>custom keyboards</strong> can be extremely useful.</p>
<p>Whenever your bot sends a message, it can <strong>display a special keyboard</strong> with predefined reply options (see <a href="/bots/api#replykeyboardmarkup">ReplyKeyboardMarkup</a>). Telegram apps that receive the message will display your keyboard to the user. Using any of the buttons will immediately send the respective text. This way you can drastically <strong>simplify</strong> and <strong>streamline</strong> user interaction with your bot.</p>
<div>
<a href="/file/464001950/1191a/2RwpmgU-swU.123554/b50478c124d5914c23" target="_blank"><img src="/file/464001950/1191a/2RwpmgU-swU.123554/b50478c124d5914c23" title="Keyboards" class="dev_page_image" width=44% /></a>
<a href="/file/464001950/1191a/2RwpmgU-swU.123554/b50478c124d5914c23" target="_blank"><img src="/file/464001950/1191a/2RwpmgU-swU.123554/b50478c124d5914c23" title="Keyboards" class="dev_page_image" width="44%"></a>
</div>
<blockquote>
<p>Check out the <a href="/bots/api#replykeyboardmarkup">one_time_keyboard</a> parameter to automatically hide your bot&#39;s keyboard as soon as it&#39;s been used.</p>
<p>Check out the <a href="/bots/api#replykeyboardmarkup">one_time_keyboard</a> parameter to automatically hide your bot's keyboard as soon as it's been used.</p>
</blockquote>
<p>You can also <strong>customize the text placeholder</strong> in the input field by setting the <code>input_field_placeholder</code> parameter.</p>
<h4><a class="anchor" name="inline-keyboards" href="#inline-keyboards"><i class="anchor-icon"></i></a>Inline Keyboards</h4>
<p>There are times when you&#39;d prefer to do things <strong>without sending any messages</strong> to the chat like when a user is changing settings, toggling options or navigating search results. In such cases, you can use <a href="/bots/api#inlinekeyboardmarkup">Inline Keyboards</a> that are shown directly below their relevant messages.</p>
<p>Unlike with custom reply keyboards, pressing buttons on inline keyboards <strong>doesn&#39;t send messages to the chat</strong>. Instead, inline keyboards support buttons that can work behind the scenes or open different interfaces: <a href="/bots/api#inlinekeyboardbutton">callback buttons</a>, <a href="/bots/api#inlinekeyboardbutton">URL buttons</a>, <a href="/bots/api#inlinekeyboardbutton">switch-to-inline buttons</a>, <a href="/bots/api#inlinekeyboardbutton">game buttons</a> and <a href="/bots/api#inlinekeyboardbutton">payment buttons</a>. </p>
<h4><a class="anchor" href="#inline-keyboards" id="inline-keyboards" name="inline-keyboards"><i class="anchor-icon"></i></a>Inline Keyboards</h4>
<p>There are times when you'd prefer to do things <strong>without sending any messages</strong> to the chat like when a user is changing settings, toggling options or navigating search results. In such cases, you can use <a href="/bots/api#inlinekeyboardmarkup">Inline Keyboards</a> that are shown directly below their relevant messages.</p>
<p>Unlike with custom reply keyboards, pressing buttons on inline keyboards <strong>doesn't send messages to the chat</strong>. Instead, inline keyboards support buttons that can work behind the scenes or open different interfaces: <a href="/bots/api#inlinekeyboardbutton">callback buttons</a>, <a href="/bots/api#inlinekeyboardbutton">URL buttons</a>, <a href="/bots/api#inlinekeyboardbutton">switch-to-inline buttons</a>, <a href="/bots/api#inlinekeyboardbutton">game buttons</a> and <a href="/bots/api#inlinekeyboardbutton">payment buttons</a>. </p>
<div>
<a href="/file/464001863/110f3/I47qTXAD9Z4.120010/e0ea04f66357b640ec" target="_blank"><img src="/file/464001863/110f3/I47qTXAD9Z4.120010/e0ea04f66357b640ec" title="Inline Keyboard" class="dev_page_image" width=44% /></a>
<a href="/file/464001863/110f3/I47qTXAD9Z4.120010/e0ea04f66357b640ec" target="_blank"><img src="/file/464001863/110f3/I47qTXAD9Z4.120010/e0ea04f66357b640ec" title="Inline Keyboard" class="dev_page_image" width="44%"></a>
</div>
<blockquote>
<p>To provide a <strong>better user experience</strong>, consider <a href="/bots/api#editmessagereplymarkup">editing your keyboard</a> when the user toggles a setting button or navigates to a new page this is both <strong>faster</strong> and <strong>smoother</strong> than sending a whole new message and deleting the previous one.</p>
</blockquote>
<h4><a class="anchor" name="menu-button" href="#menu-button"><i class="anchor-icon"></i></a>Menu Button</h4>
<p>In all bot chats, a menu button appears near the message field. By default, tapping this button <strong>opens a menu</strong> that can hold some or all of a bot&#39;s commands, including a short description for each. Users can then <strong>select a command from the menu</strong> without needing to type it out.</p>
<h4><a class="anchor" href="#menu-button" id="menu-button" name="menu-button"><i class="anchor-icon"></i></a>Menu Button</h4>
<p>In all bot chats, a menu button appears near the message field. By default, tapping this button <strong>opens a menu</strong> that can hold some or all of a bot's commands, including a short description for each. Users can then <strong>select a command from the menu</strong> without needing to type it out.</p>
<p>You can set different texts of the menu button and its command descriptions for various <strong>individual users</strong> or <strong>groups of users</strong> for example, showing translated text based on the users language, as explained <a href="#commands">here</a>.</p>
<div class="blog_video_player_wrap" style="max-width: 400px; margin: 20px auto 20px;">
<video class="blog_video_player tl_blog_vid_autoplay" onclick="videoTogglePlay(this)" autoplay="" loop="" controls="" muted="" poster="/file/464001581/11d85/f42u9c5Wncg.133752/b5a95b7f1221032d7d" style="max-width: 400px;" title="Bot Menu Button" alt="Video: Bot Menu Button">
<source src="/file/464001555/10fbd/jvTuV2Ke7WQ.1916669.mp4/a056de323645db409d" type="video/mp4">
</video>
</source></video>
</div>
<p>The <strong>menu button</strong> can alternatively be used to launch a <a href="#web-apps">Web App</a>.</p>
<h4><a class="anchor" name="global-commands" href="#global-commands"><i class="anchor-icon"></i></a>Global Commands</h4>
<h4><a class="anchor" href="#global-commands" id="global-commands" name="global-commands"><i class="anchor-icon"></i></a>Global Commands</h4>
<p>To make basic interactions more uniform, we ask all developers to support a few <strong>basic commands</strong>. Telegram apps will have interface shortcuts for these commands.</p>
<ul>
<li>/start - begins the interaction with the user, like sending an introductory message. This command can also be used to pass additional parameters to the bot (see <a href="#deep-linking">Deep Linking</a>).</li>
<li>/help - returns a help message, like a short text about what your bot can do and a list of commands.</li>
<li>/settings - (if applicable) shows the bot&#39;s settings for this user and suggests commands to edit them.</li>
<li>/settings - (if applicable) shows the bot's settings for this user and suggests commands to edit them.</li>
</ul>
<p>Users will see a <strong>Start</strong> button the first time they open a chat with your bot. <strong>Help</strong> and <strong>Settings</strong> links will be available in the menu on the bot&#39;s profile page if you add them in <a href="https://t.me/botfather">@BotFather</a>.</p>
<h3><a class="anchor" name="chat-and-user-selection" href="#chat-and-user-selection"><i class="anchor-icon"></i></a>Chat and User Selection</h3>
<p>Users will see a <strong>Start</strong> button the first time they open a chat with your bot. <strong>Help</strong> and <strong>Settings</strong> links will be available in the menu on the bot's profile page if you add them in <a href="https://t.me/botfather">@BotFather</a>.</p>
<h3><a class="anchor" href="#chat-and-user-selection" id="chat-and-user-selection" name="chat-and-user-selection"><i class="anchor-icon"></i></a>Chat and User Selection</h3>
<p>Bots can present the user with a <strong>friendly</strong> and <strong>intuitive</strong> interface that lists any number of groups, channels or other users according to a custom set of <strong>criteria</strong>. Tapping on a chat will send its identifier to the bot in a service message and seamlessly close the interface.</p>
<p>A group management bot is the <strong>perfect example</strong>: an admin could select a chat the bot should manage, and then select a user it should promote this would happen without ever typing any text.</p>
<p>Here is a <strong>quick start guide</strong> to use this feature:</p>
@ -176,66 +172,65 @@ width=44% /></a>
<li>Pick a set of criteria and store them in a <a href="https://core.telegram.org/bots/api#keyboardbuttonrequestchat">KeyboardButtonRequestChat</a> object (or <a href="https://core.telegram.org/bots/api#keyboardbuttonrequestuser">KeyboardButtonRequestUser</a> for users).</li>
<li>Create a <a href="https://core.telegram.org/bots/api#keyboardbutton">KeyboardButton</a> and store the criteria under <code>request_chat</code> or <code>request_user</code> respectively.</li>
<li>Send a <a href="https://core.telegram.org/bots/api#replykeyboardmarkup">ReplyKeyboardMarkup</a> that contains the button you just created.</li>
<li>When the user selects a chat, you&#39;ll receive its identifier in a <code>chat_shared</code> or <code>user_shared</code> service message.</li>
<li>When the user selects a chat, you'll receive its identifier in a <code>chat_shared</code> or <code>user_shared</code> service message.</li>
</ul>
<div class="blog_video_player_wrap" style="max-width: 400px; margin: 20px auto 20px;">
<video class="blog_video_player tl_blog_vid_autoplay" onclick="videoTogglePlay(this)" loop="" muted="" poster="/file/464001277/1132d/dAINJNWL9jw.34909/08eaf646c24be49a87" style="max-width: 400px;" title="Select Chats For Bots" alt="Select Chats For Bots" vindex="1" preload="auto">
<source src="/file/464001095/11121/M6HpBwtivTE.1913043.mp4/0514a29affa78a6dca" type="video/mp4">
</video>
</source></video>
</div>
<blockquote>
<p>Keep in mind that the bot may not be able to use the identifier it receives if the corresponding chat or user is not already known or accessible by some other means.</p>
</blockquote>
<hr>
<h3><a class="anchor" name="interactions" href="#interactions"><i class="anchor-icon"></i></a>Interactions</h3>
<h3><a class="anchor" href="#interactions" id="interactions" name="interactions"><i class="anchor-icon"></i></a>Interactions</h3>
<p>In addition to sending commands and messages to the chat with the bot, there are several ways of interacting with them without opening any specific chat or group.</p>
<ul>
<li><a href="#inline-requests"><strong>Inline mode</strong></a> allows sending requests to bots right from the input field from any chat on Telegram.</li>
<li><a href="#deep-linking"><strong>Deep linking</strong></a> allows special links that send certain parameters to the bot when opened.</li>
<li><a href="#attachment-menu"><strong>Attachment menu</strong></a> integration makes it possible to use bots from the attachment menu in chats.</li>
</ul>
<h4><a class="anchor" name="inline-requests" href="#inline-requests"><i class="anchor-icon"></i></a>Inline Requests</h4>
<p>Users can interact with your bot via <strong>inline queries</strong> straight from the message field <strong>in any chat</strong>. All they need to do is start a message with your bot&#39;s <em>@username</em> and enter a keyword.</p>
<h4><a class="anchor" href="#inline-requests" id="inline-requests" name="inline-requests"><i class="anchor-icon"></i></a>Inline Requests</h4>
<p>Users can interact with your bot via <strong>inline queries</strong> straight from the message field <strong>in any chat</strong>. All they need to do is start a message with your bot's <em>@username</em> and enter a keyword.</p>
<p>Having received the query, your bot can return some results. As soon as the user selects one, it is sent to the <strong>relevant chat</strong>. This way, people can request and send content from your bot in any of their chats, groups or channels.</p>
<p>Remember that inline functionality has to be enabled via <a href="https://t.me/botfather">@BotFather</a>, or your bot will not receive inline <a href="/bots/api#update">Updates</a>.</p>
<div>
<a href="/file/464001466/10e4a/r4FKyQ7gw5g.134366/f2606a53d683374703" target="_blank"><img src="/file/464001466/10e4a/r4FKyQ7gw5g.134366/f2606a53d683374703" title="Inline Mode" class="dev_page_image" width=51%/></a>
<a href="/file/464001466/10e4a/r4FKyQ7gw5g.134366/f2606a53d683374703" target="_blank"><img src="/file/464001466/10e4a/r4FKyQ7gw5g.134366/f2606a53d683374703" title="Inline Mode" class="dev_page_image" width="51%/"></a>
</div>
<blockquote>
<p>Examples of inline bots include <a href="https://gif.t.me">@gif</a>, <a href="https://bing.t.me">@bing</a> and <a href="https://wiki.t.me">@wiki</a>. <a href="#web-apps">Web App</a> bots can also be used inline try typing <a href="https://durgerkingbot.t.me">@durgerkingbot</a> in any chat.</p>
</blockquote>
<h4><a class="anchor" name="deep-linking" href="#deep-linking"><i class="anchor-icon"></i></a>Deep Linking</h4>
<p>Telegram bots have a deep linking mechanism that allows <strong>additional parameters</strong> to be passed to the bot on startup. It could be a command that launches the bot or an authentication token to connect the user&#39;s Telegram account to their account on another platform.</p>
<h4><a class="anchor" href="#deep-linking" id="deep-linking" name="deep-linking"><i class="anchor-icon"></i></a>Deep Linking</h4>
<p>Telegram bots have a deep linking mechanism that allows <strong>additional parameters</strong> to be passed to the bot on startup. It could be a command that launches the bot or an authentication token to connect the user's Telegram account to their account on another platform.</p>
<p>Each bot has a link that <strong>opens a conversation</strong> with it in Telegram <code>https://t.me/&lt;bot_username&gt;</code>. Parameters can be added directly to this link to let your bot work with additional information on the fly, without any user input.</p>
<blockquote>
<p>A-Z, a-z, 0-9, _ and - are allowed. We recommend using base64url to encode parameters with binary and other types of content. The parameter can be up to 64 characters long.</p>
</blockquote>
<p><strong>Private Chats</strong><br>In private chats, you can use the <code>start</code> parameter to automatically pass any value to your bot whenever a user presses the link. For example, you could use:</p>
<p><strong>Private Chats</strong>
In private chats, you can use the <code>start</code> parameter to automatically pass any value to your bot whenever a user presses the link. For example, you could use:</p>
<pre><code>https://t.me/your_bot?start=airplane</code></pre>
<p>When someone opens a chat with your bot via this link, you will receive:</p>
<pre><code>/start airplane</code></pre>
<p><strong>Groups</strong><br>In groups, you can add the parameter <code>startgroup</code> to this link. For example:</p>
<p><strong>Groups</strong>
In groups, you can add the parameter <code>startgroup</code> to this link. For example:</p>
<pre><code>https://t.me/your_bot?startgroup=spaceship</code></pre>
<p>Following a link with this parameter prompts the user to select a group to add the bot to the resulting update will contain text in the form:</p>
<pre><code>/start@your_bot spaceship</code></pre>
<blockquote>
<p><a href="#web-apps">Web Apps</a> also support deep linking, for more information check out our <a href="/bots/webapps#adding-bots-to-the-attachment-menu">dedicated guide</a>.</p>
</blockquote>
<h4><a class="anchor" name="attachment-menu" href="#attachment-menu"><i class="anchor-icon"></i></a>Attachment Menu</h4>
<h4><a class="anchor" href="#attachment-menu" id="attachment-menu" name="attachment-menu"><i class="anchor-icon"></i></a>Attachment Menu</h4>
<p>Certain bots can be added directly to a users <strong>attachment menu</strong> giving them easy access to the bot in any chat. Currently, this option is restricted to certain <a href="/bots/webapps#launching-web-apps-from-the-attachment-menu">approved bots</a>, but may be expanded later.</p>
<div class="blog_video_player_wrap" style="max-width: 400px; margin: 20px auto 20px;">
<video class="blog_video_player tl_blog_vid_autoplay" onclick="videoTogglePlay(this)" autoplay="" loop="" controls="" muted="" poster="/file/464001491/11651/uwMWNdO29NE.215169/1b37285bbd8fc81244" style="max-width: 400px;" title="Attachment Menu" alt="Video: Bot Attachment Menu">
<source src="/file/464001177/11b03/ruSbBLQiLJ8.928268.mp4/d9ad95048d23f3cc3f" type="video/mp4">
</video>
</source></video>
</div>
<blockquote>
<p>Try adding <a href="https://t.me/durgerkingbot?startattach">@DurgerKingBot</a> to your attachment menu.</p>
</blockquote>
<hr>
<h3><a class="anchor" name="integration" href="#integration"><i class="anchor-icon"></i></a>Integration</h3>
<h3><a class="anchor" href="#integration" id="integration" name="integration"><i class="anchor-icon"></i></a>Integration</h3>
<p>There are various ways of futher integrating bots with Telegram and other services.</p>
<ul>
<li>Use <a href="#web-apps">Web Apps</a> to replace any website.</li>
@ -245,7 +240,7 @@ width=44% /></a>
<li>Create gaming bots by integrating <a href="#html5-games">HTML5 Games</a>.</li>
<li>Help users create and manage <a href="#stickers-and-custom-emoji">Telegram Stickers</a>.</li>
</ul>
<h3><a class="anchor" name="web-apps" href="#web-apps"><i class="anchor-icon"></i></a>Web Apps</h3>
<h3><a class="anchor" href="#web-apps" id="web-apps" name="web-apps"><i class="anchor-icon"></i></a>Web Apps</h3>
<p>Bots can easily process <strong>complex inputs</strong> of any kind and <strong>dynamic interaction flows</strong> via <a href="webapps">Web Apps</a>. With this unique feature, you can develop any number of flexible, streamlined interfaces in <strong>JavaScript</strong>.</p>
<blockquote>
<p>Web Apps are covered in detail in our <a href="webapps">dedicated guide</a> you should read it carefully to learn the wide variety of features they can offer.</p>
@ -253,11 +248,10 @@ width=44% /></a>
<div class="blog_video_player_wrap" style="max-width: 400px; margin: 20px auto 20px;">
<video class="blog_video_player tl_blog_vid_autoplay" onclick="videoTogglePlay(this)" autoplay="" loop="" controls="" muted="" poster="/file/464001434/100bf/eWprjdgzEbE.100386/644bbea83084f44c8f" style="max-width: 400px;" title="Attachment Menu" alt="Video: Bot Attachment Menu">
<source src="/file/464001679/11aa9/KQx_BlPVXRo.4922145.mp4/c65433c8ac11a347a8" type="video/mp4">
</video>
</source></video>
</div>
<p>If you develop a <strong>Web App</strong>, be sure to follow our <a href="webapps#design-guidelines">design guidelines</a> you&#39;ll want your custom interface to <strong>seamlessly integrate</strong> into the app to provide users the best possible experience.</p>
<h4><a class="anchor" name="bots-for-business" href="#bots-for-business"><i class="anchor-icon"></i></a>Bots for Business</h4>
<p>If you develop a <strong>Web App</strong>, be sure to follow our <a href="webapps#design-guidelines">design guidelines</a> you'll want your custom interface to <strong>seamlessly integrate</strong> into the app to provide users the best possible experience.</p>
<h4><a class="anchor" href="#bots-for-business" id="bots-for-business" name="bots-for-business"><i class="anchor-icon"></i></a>Bots for Business</h4>
<p>Bots can enable <strong>Business Mode</strong>, allowing <a href="https://telegram.org/blog/telegram-business">Telegram Business</a> subscribers to connect them to their account to streamline and automate private chat management and interactions with their clients.</p>
<p>The <strong>account owner</strong> can specify which chats your bot can access within those chats, the bot will receive all updates normally supported by the <a href="https://core.telegram.org/bots/api">Bot API</a>, except messages sent by itself and other bots. Depending on the business connection settings, your bot may also be able to <strong>send messages</strong> and do other actions on behalf of the account owner in chats that were active in the last 24h.</p>
<p>Here is a quick start guide to integrate your bot with Telegram Business:</p>
@ -268,25 +262,23 @@ width=44% /></a>
<li>Check your bots write permissions via <code>can_reply</code> in the latest <a href="https://core.telegram.org/bots#businessconnection">BusinessConnection</a> update.</li>
<li>If allowed to, use the <code>business_connection_id</code> field in <a href="https://core.telegram.org/bots/api#sendmessage">sendMessage</a>, <a href="https://core.telegram.org/bots/api#sendchataction">sendChatAction</a> and other send methods to communicate on behalf of the Business user.</li>
</ul>
<p>Users who <strong>connect your bot</strong> to their account will see a <strong>quick action bar</strong> at the top of each managed chat tapping on “Manage Bot” will redirect them to your bot, which will receive a deep link message in the format <code>/start bizChat&lt;user_chat_id&gt;</code>.</p>
<p>Users who <strong>connect your bot</strong> to their account will see a <strong>quick action bar</strong> at the top of each managed chat tapping on "Manage Bot" will redirect them to your bot, which will receive a deep link message in the format <code>/start bizChat&lt;user_chat_id&gt;</code>.</p>
<div class="blog_video_player_wrap" style="max-width: 600px; margin: 20px auto 20px;">
<video class="blog_video_player tl_blog_vid_autoplay" onclick="videoTogglePlay(this)" autoplay loop controls muted poster="/file/400780400238/1/x875tPT245w.58064/1b426d3eda0a923c03" style="max-width: 600px;" title="" alt="Chatbots for Business">
<source src="/file/400780400382/1/BVN6m4W5a6w.4289566.mp4/9dc47caab261eaade4" type="video/mp4">
</video>
</source></video>
</div>
<blockquote>
<p>Please keep in mind that operating bots on Telegram is subject to the <a href="https://telegram.org/tos/bot-developers">Telegram Bot Developer Terms of Service</a>. Specifically, for Telegram Business, make sure you have read and understood <a href="https://telegram.org/tos/bot-developers#5-4-telegram-business">Section 5.4</a>.</p>
</blockquote>
<h3><a class="anchor" name="payments" href="#payments"><i class="anchor-icon"></i></a>Payments</h3>
<h3><a class="anchor" href="#payments" id="payments" name="payments"><i class="anchor-icon"></i></a>Payments</h3>
<blockquote>
<p>If your bot or mini app sells <strong>digital goods and services</strong>, be sure to carry out the payment in <a href="https://telegram.org/blog/telegram-stars">Telegram Stars</a> by specifying <code>XTR</code> as currency. In compliance with third-party store policies, Telegram does not support the sale of digital goods and services using other currencies.</p>
</blockquote>
<p>Telegram bots can accept payments with a sleek, streamlined interface that collects all necessary data from the user. Telegram <strong>doesn&#39;t collect</strong> any payment data like the user&#39;s credit card information and sends it directly to one of the supported <a href="payments#supported-payment-providers">payment providers</a>.</p>
<p>Telegram bots can accept payments with a sleek, streamlined interface that collects all necessary data from the user. Telegram <strong>doesn't collect</strong> any payment data like the user's credit card information and sends it directly to one of the supported <a href="payments#supported-payment-providers">payment providers</a>.</p>
<p>Here is a <strong>quick start guide</strong> to implement payments:</p>
<ul>
<li>Pick a <a href="payments#supported-payment-providers">provider</a> and obtain the <a href="payments#getting-a-token">proper token</a> as well as a <strong>test token</strong> from the &quot;<strong>Stripe TEST MODE</strong>&quot; provider.</li>
<li>Pick a <a href="payments#supported-payment-providers">provider</a> and obtain the <a href="payments#getting-a-token">proper token</a> as well as a <strong>test token</strong> from the "<strong>Stripe TEST MODE</strong>" provider.</li>
<li>Implement payments via the <a href="/bots/api#payments">appropriate API methods</a>.</li>
<li>Test your implementation by using your <strong>test token</strong> along with a <a href="https://stripe.com/docs/testing#cards">test credit card</a>.</li>
</ul>
@ -303,38 +295,37 @@ width=44% /></a>
<li><a href="/bots/payments">Guide for physical goods and services</a></li>
</ul>
<div>
<a href="/file/464001393/101fc/SB_bFCLR0tg.130549/7ecf91aaa44737e8cb" target="_blank"><img src="/file/464001393/101fc/SB_bFCLR0tg.130549/7ecf91aaa44737e8cb" title="Payments" class="dev_page_image" width=50% /></a>
<a href="/file/464001393/101fc/SB_bFCLR0tg.130549/7ecf91aaa44737e8cb" target="_blank"><img src="/file/464001393/101fc/SB_bFCLR0tg.130549/7ecf91aaa44737e8cb" title="Payments" class="dev_page_image" width="50%"></a>
</div>
<blockquote>
<p>Telegram does not directly process the payments, does not store data about orders and does not collect any fees. Invoices are forwarded directly to the payment provider.<br>For this reason, disputes must be solved between the user, the bot developer and the payment provider. You can read more about this in the <a href="https://telegram.org/privacy#7-third-party-payment-services">Privacy Policy</a>.</p>
<p>Telegram does not directly process the payments, does not store data about orders and does not collect any fees. Invoices are forwarded directly to the payment provider.
For this reason, disputes must be solved between the user, the bot developer and the payment provider. You can read more about this in the <a href="https://telegram.org/privacy#7-third-party-payment-services">Privacy Policy</a>.</p>
</blockquote>
<h3><a class="anchor" name="web-login" href="#web-login"><i class="anchor-icon"></i></a>Web Login</h3>
<h3><a class="anchor" href="#web-login" id="web-login" name="web-login"><i class="anchor-icon"></i></a>Web Login</h3>
<p>Telegram offers a <strong>flexible</strong>, <strong>lightweight</strong> and <strong>free</strong> framework to authenticate users on any website and app. This can be used to bridge your platform with Telegram, providing a smooth experience to your users. You can also freely rely on this framework to implement a <strong>fast</strong> and <strong>signup-free</strong> login on your site, regardless of its connection to Telegram.</p>
<h4><a class="anchor" name="widgets" href="#widgets"><i class="anchor-icon"></i></a>Widgets</h4>
<h4><a class="anchor" href="#widgets" id="widgets" name="widgets"><i class="anchor-icon"></i></a>Widgets</h4>
<p>The Telegram login widget is a <strong>simple and secure way to authorize users</strong> on your website.</p>
<ol>
<li>Choose a bot ideally its name and profile pic <strong>should match</strong> the website title and logo.</li>
<li>Use the <code>/setdomain</code> command in <a href="https://t.me/botfather">@BotFather</a> to pair the bot with your website domain. </li>
<li>Configure your widget using <a href="/widgets/login#widget-configuration">our dedicated tool</a> and embed it on your website.</li>
</ol>
<h4><a class="anchor" name="inline-login" href="#inline-login"><i class="anchor-icon"></i></a>Inline Login</h4>
<p>When users open your website via an <strong>inline button</strong>, you can use the <a href="/bots/api#loginurl">login_url</a> parameter as an alternative to login widgets. This way, you&#39;ll be able to <a href="https://telegram.org/blog/privacy-discussions-web-bots#meet-seamless-web-bots">seamlessly authorize</a> them on your website or app before the page even loads.</p>
<h4><a class="anchor" href="#inline-login" id="inline-login" name="inline-login"><i class="anchor-icon"></i></a>Inline Login</h4>
<p>When users open your website via an <strong>inline button</strong>, you can use the <a href="/bots/api#loginurl">login_url</a> parameter as an alternative to login widgets. This way, you'll be able to <a href="https://telegram.org/blog/privacy-discussions-web-bots#meet-seamless-web-bots">seamlessly authorize</a> them on your website or app before the page even loads.</p>
<div>
<a href="/file/464001287/105ea/23bO4ntH4tc.43741/c9624e36c3462b6540" target="_blank"><img src="/file/464001287/105ea/23bO4ntH4tc.43741/c9624e36c3462b6540" width=50% title="Login Widget" class="dev_page_image" /></a>
<a href="/file/464001287/105ea/23bO4ntH4tc.43741/c9624e36c3462b6540" target="_blank"><img src="/file/464001287/105ea/23bO4ntH4tc.43741/c9624e36c3462b6540" width="50%" title="Login Widget" class="dev_page_image"></a>
</div>
<blockquote>
<p>Make sure to review our <a href="/widgets/login#checking-authorization">guide</a> on authenticating the received data as well as our <a href="https://gist.github.com/anonymous/6516521b1fb3b464534fbc30ea3573c2">sample code</a>.</p>
</blockquote>
<h3><a class="anchor" name="html5-games" href="#html5-games"><i class="anchor-icon"></i></a>HTML5 Games</h3>
<h3><a class="anchor" href="#html5-games" id="html5-games" name="html5-games"><i class="anchor-icon"></i></a>HTML5 Games</h3>
<p>Bots can serve as <strong>standalone gaming platforms</strong> with our <a href="/bots/api#games">HTML5 Gaming API</a> you can develop multiplayer or single-player games and let your users have fun comparing <strong>ranks</strong>, <strong>scores</strong> and much more.</p>
<p>To get started, follow these simple steps:</p>
<ul>
<li>Send the <code>/newgame</code> command to <a href="https://t.me/botfather">@BotFather</a></li>
<li>Provide a <strong>description text</strong>, an <strong>image</strong> or an <strong>optional gif</strong> to showcase its gameplay</li>
<li>Send the game to users via the <a href="/bots/api#sendgame">sendGame</a> method or via an <a href="/bots/api#inlinequeryresultgame">inline query</a></li>
<li>When someone wants to play, you&#39;ll receive the appropriate <code>game_short_name</code> in a <a href="/bots/api#callbackquery">CallbackQuery</a></li>
<li>When someone wants to play, you'll receive the appropriate <code>game_short_name</code> in a <a href="/bots/api#callbackquery">CallbackQuery</a></li>
<li>To launch the game, provide the <strong>HTML5 Game URL</strong> as the <code>url</code> param of <a href="/bots/api#answercallbackquery">answerCallbackQuery</a></li>
</ul>
<p>Then, to handle <strong>highscores</strong>:</p>
@ -348,49 +339,50 @@ width=44% /></a>
<li><a href="/bots/api#games">HTML5 Games Bot API Docs</a></li>
</ul>
<div>
<a href="/file/464001558/11b92/y_Fu9QQWtj0.141959/dc9db48f66800bf271" target="_blank"><img src="/file/464001558/11b92/y_Fu9QQWtj0.141959/dc9db48f66800bf271" title="Games" width=50% class="dev_page_image" /></a>
<a href="/file/464001558/11b92/y_Fu9QQWtj0.141959/dc9db48f66800bf271" target="_blank"><img src="/file/464001558/11b92/y_Fu9QQWtj0.141959/dc9db48f66800bf271" title="Games" width="50%" class="dev_page_image"></a>
</div>
<blockquote>
<p>Check out <a href="https://t.me/gamebot">@GameBot</a> and <a href="https://t.me/gamee">@gamee</a> for examples of what you can do using our Gaming Platform.</p>
</blockquote>
<h3><a class="anchor" name="stickers-and-custom-emoji" href="#stickers-and-custom-emoji"><i class="anchor-icon"></i></a>Stickers and Custom Emoji</h3>
<h3><a class="anchor" href="#stickers-and-custom-emoji" id="stickers-and-custom-emoji" name="stickers-and-custom-emoji"><i class="anchor-icon"></i></a>Stickers and Custom Emoji</h3>
<p><a href="https://core.telegram.org/stickers">Stickers</a> and <a href="https://telegram.org/blog/custom-emoji">Custom Emoji</a> are a distinctive Telegram feature used by millions of users to share artwork every day. Stickers and custom emoji take many forms ranging from <strong>basic images</strong> to smooth <strong>vector animations</strong> and high-detail <strong>.WEBM videos</strong>.</p>
<p>All these formats are supported by our <a href="api#stickers">Bot API</a>, which allows bots to <strong>create</strong>, <strong>edit</strong>, <strong>delete</strong> and <strong>share</strong> new artwork packs on the fly. Telegram&#39;s <a href="https://core.telegram.org/import-stickers">Import API</a> lets users <strong>migrate packs</strong> from other platforms and sticker apps.</p>
<p><strong>Creating a new pack</strong><br>To create a <strong>new pack</strong>, simply:</p>
<p>All these formats are supported by our <a href="api#stickers">Bot API</a>, which allows bots to <strong>create</strong>, <strong>edit</strong>, <strong>delete</strong> and <strong>share</strong> new artwork packs on the fly. Telegram's <a href="https://core.telegram.org/import-stickers">Import API</a> lets users <strong>migrate packs</strong> from other platforms and sticker apps.</p>
<p><strong>Creating a new pack</strong>
To create a <strong>new pack</strong>, simply:</p>
<ul>
<li><strong>Prepare</strong> your artwork following our <a href="https://core.telegram.org/stickers">technical requirements</a>.</li>
<li><strong>Create</strong> a new sticker pack via <a href="api#createnewstickerset">createStickerSet</a>. Set <code>sticker_type</code> to <em>regular</em> to create a sticker pack or to <em>custom emoji</em> to create a pack of custom emoji. Attach the <a href="api#file">files</a> you wish to include in the pack as an array of <a href="https://core.telegram.org/bots#inputsticker">InputSticker</a></li>
<li>You can use <a href="api#addstickertoset">addStickerToSet</a> to add stickers or emoji later on.</li>
</ul>
<p><strong>Additional features</strong><br>Regular stickers and custom emoji support <strong>keywords</strong> that users can type to quickly find the respective artwork this can be useful when a sticker doesn&#39;t have obvious ties to a specific emoji. You can use the <code>keywords</code> parameter in <a href="https://core.telegram.org/bots#inputsticker">InputSticker</a> to specify them.</p>
<p><strong>Additional features</strong>
Regular stickers and custom emoji support <strong>keywords</strong> that users can type to quickly find the respective artwork this can be useful when a sticker doesn't have obvious ties to a specific emoji. You can use the <code>keywords</code> parameter in <a href="https://core.telegram.org/bots#inputsticker">InputSticker</a> to specify them.</p>
<p>Custom emoji additionally support <strong>adaptive colors</strong> they will always match the current context (e.g., white on photos, accent color when used as status, etc.); to enable this feature, use the <code>needs_repainting</code> parameter in <a href="api#createnewstickerset">createStickerSet</a>.</p>
<p>Once you&#39;re done creating and sharing your artwork, don&#39;t forget to check out our <a href="api#stickers">remaining sticker methods</a> to find out how to <a href="api#setstickersetthumb">edit</a>, <a href="api#deletestickerfromset">delete</a> and even <a href="api#setstickerpositioninset">reorder</a> your pack. </p>
<p>Once you're done creating and sharing your artwork, don't forget to check out our <a href="api#stickers">remaining sticker methods</a> to find out how to <a href="api#setstickersetthumb">edit</a>, <a href="api#deletestickerfromset">delete</a> and even <a href="api#setstickerpositioninset">reorder</a> your pack. </p>
<blockquote>
<p>Note that these methods will only work on packs <strong>created by the bot that is calling them</strong>.</p>
</blockquote>
<h3><a class="anchor" name="language-support" href="#language-support"><i class="anchor-icon"></i></a>Language Support</h3>
<h3><a class="anchor" href="#language-support" id="language-support" name="language-support"><i class="anchor-icon"></i></a>Language Support</h3>
<p>Bots can tailor their interfaces to <strong>support multiple languages</strong> updating inputs and information on the fly. A users <a href="/bots/api#user">language_code</a> is included in every relevant <a href="/bots/api#update">update</a> as an <a href="https://en.wikipedia.org/wiki/IETF_language_tag">IETF language tag</a>, allowing bots to adapt accordingly. </p>
<p>We recommend that you follow our guidelines to provide <strong>the best user experience</strong>.</p>
<ul>
<li>Your interfaces, texts and <a href="/bots/api#answerinlinequery">inline results</a> should adapt seamlessly to the <em>language_code</em>, without user intervention.</li>
<li>Connected <a href="/bots/webapps">WebApps</a> will receive the user&#39;s <em>language_code</em> your HTML page should account for it.</li>
<li>Connected <a href="/bots/webapps">WebApps</a> will receive the user's <em>language_code</em> your HTML page should account for it.</li>
<li><a href="/bots/games">HTML5 Games</a> can obtain language information if you specify it as a <a href="/bots/games#using-url-parameters">URL parameter</a>. You can generate this parameter from the <em>language_code</em> field in the <a href="/bots/api#user">User</a> object served with the initial game <a href="/bots/api#callbackquery">CallbackQuery</a>.</li>
<li>The bot&#39;s <strong>Name</strong>, <strong>Description</strong> and <strong>About text</strong> can be natively localized with the respective <a href="https://core.telegram.org/bots/api#setmydescription">methods</a>.</li>
<li>The bot's <strong>Name</strong>, <strong>Description</strong> and <strong>About text</strong> can be natively localized with the respective <a href="https://core.telegram.org/bots/api#setmydescription">methods</a>.</li>
<li>Command lists can also be specified for individual languages more on this <a href="#commands">here</a>.</li>
</ul>
<div class="blog_video_player_wrap" style="max-width: 400px; margin: 20px auto 20px;">
<video class="blog_video_player tl_blog_vid_autoplay" onclick="videoTogglePlay(this)" autoplay="" loop="" controls="" muted="" poster="/file/464001822/10cd0/EvtvjnhA-kA.132475/e285952b505535d85a" style="max-width: 400px;" title="Language Support" alt="Video: Language Support">
<source src="/file/464001083/105cd/NF4ViAHfTJc.3601652.mp4/0fd787953c11a6371d" type="video/mp4">
</video>
</source></video>
</div>
<blockquote>
<p>The <em>language_code</em> is an <strong>optional field</strong> it could be empty.<br>If you target the general public, your code should always fall back to either the last recorded language tag or English (in this order) when the field is missing for a specific user. </p>
<p>The <em>language_code</em> is an <strong>optional field</strong> it could be empty.
If you target the general public, your code should always fall back to either the last recorded language tag or English (in this order) when the field is missing for a specific user. </p>
</blockquote>
<hr>
<h3><a class="anchor" name="bot-management" href="#bot-management"><i class="anchor-icon"></i></a>Bot Management</h3>
<h4><a class="anchor" name="privacy-mode" href="#privacy-mode"><i class="anchor-icon"></i></a>Privacy Mode</h4>
<h3><a class="anchor" href="#bot-management" id="bot-management" name="bot-management"><i class="anchor-icon"></i></a>Bot Management</h3>
<h4><a class="anchor" href="#privacy-mode" id="privacy-mode" name="privacy-mode"><i class="anchor-icon"></i></a>Privacy Mode</h4>
<p>Bots are frequently added to groups to perform basic tasks or assist moderators like automatically posting company announcements or even celebrating birthdays. By default, <strong>all bots</strong> added to groups run in Privacy Mode and only see relevant messages and commands:</p>
<ul>
<li>Commands explicitly meant for them (e.g., <code>/command@this_bot</code>).</li>
@ -404,21 +396,20 @@ width=44% /></a>
<li>All messages from private chats.</li>
<li>All messages from channels where they are a member.</li>
</ul>
<p>Privacy mode is <strong>enabled by default</strong> for all bots, except bots that were added to a group as admins (bot admins always receive <strong>all messages</strong>). It can be disabled so that the bot receives all messages like an ordinary user (the bot will need to be re-added to the group for this change to take effect). We only recommend doing this in cases where it is <strong>absolutely necessary</strong> for your bot to work. In most cases, using the force reply option for the bot&#39;s messages should be more than enough.</p>
<p>Privacy mode is <strong>enabled by default</strong> for all bots, except bots that were added to a group as admins (bot admins always receive <strong>all messages</strong>). It can be disabled so that the bot receives all messages like an ordinary user (the bot will need to be re-added to the group for this change to take effect). We only recommend doing this in cases where it is <strong>absolutely necessary</strong> for your bot to work. In most cases, using the force reply option for the bot's messages should be more than enough.</p>
<div>
<a href="/file/464001338/107af/JdbERa0BATg.62371/28977e9a96aed3860a" target="_blank"><img src="/file/464001338/107af/JdbERa0BATg.62371/28977e9a96aed3860a" title="Privacy Mode" class="dev_page_image" width=50%/></a>
<a href="/file/464001338/107af/JdbERa0BATg.62371/28977e9a96aed3860a" target="_blank"><img src="/file/464001338/107af/JdbERa0BATg.62371/28977e9a96aed3860a" title="Privacy Mode" class="dev_page_image" width="50%/"></a>
</div>
<blockquote>
<p>This mode not only increases user privacy, but also makes the bot more efficient by reducing the number of inputs it needs to process. Users can always see a bots current privacy setting in the list of group members.</p>
</blockquote>
<h3><a class="anchor" name="testing-your-bot" href="#testing-your-bot"><i class="anchor-icon"></i></a>Testing your bot</h3>
<h3><a class="anchor" href="#testing-your-bot" id="testing-your-bot" name="testing-your-bot"><i class="anchor-icon"></i></a>Testing your bot</h3>
<p>You can quickly test your bot <strong>without interfering</strong> with its users by simply running another instance of your code on a different bot account. To do so, create a <em>new bot</em> via <a href="https://t.me/botfather">@BotFather</a>, obtain its token and use it in the testing instance of your code.</p>
<p>All further testing and debugging can happen privately on the new bot, without affecting the original instance.</p>
<blockquote>
<p>If you need to share file references across bots, note that the <code>file_id</code> field is tied to a single bot id, so your test instance cannot use a shared <code>file_id</code> database to quickly send media files must be individually reuploaded.</p>
</blockquote>
<h4><a class="anchor" name="dedicated-test-environment" href="#dedicated-test-environment"><i class="anchor-icon"></i></a>Dedicated test environment</h4>
<h4><a class="anchor" href="#dedicated-test-environment" id="dedicated-test-environment" name="dedicated-test-environment"><i class="anchor-icon"></i></a>Dedicated test environment</h4>
<p>Telegram also offers a dedicated <strong>test environment</strong> suitable for more advanced testing. Bots and users in this environment generally have more flexible restrictions for example:</p>
<ul>
<li>When working with the test environment, you may use HTTP links without TLS to test your <a href="https://core.telegram.org/bots/features#web-apps">Web Apps</a> or <a href="https://core.telegram.org/bots/features#web-login">Web Login</a>.</li>
@ -426,55 +417,62 @@ width=44% /></a>
<blockquote>
<p><strong>Flood limits</strong> are not raised in the test environment, and may at times be stricter. To minimize how this impacts your bot, you should make sure that it handles errors with retry policies and does not depend on hardcoded limit values.</p>
</blockquote>
<h4><a class="anchor" name="creating-a-bot-in-the-test-environment" href="#creating-a-bot-in-the-test-environment"><i class="anchor-icon"></i></a>Creating a bot in the test environment</h4>
<h4><a class="anchor" href="#creating-a-bot-in-the-test-environment" id="creating-a-bot-in-the-test-environment" name="creating-a-bot-in-the-test-environment"><i class="anchor-icon"></i></a>Creating a bot in the test environment</h4>
<p>The test environment is <strong>completely separate</strong> from the main environment, so you will need to create a new user account and a new bot with <a href="https://t.me/botfather">@BotFather</a>.</p>
<p>To create an account and log in, use either of the following:</p>
<ul>
<li><strong>iOS</strong>: tap 10 times on the Settings icon &gt; Accounts &gt; Login to another account &gt; Test.</li>
<li><strong>Telegram Desktop</strong>: open ☰ Settings &gt; Shift + Alt + Right click &#39;Add Account&#39; and select &#39;Test Server&#39;.</li>
<li><strong>macOS</strong>: click the Settings icon 10 times to open the Debug Menu, ⌘ + click &#39;Add Account&#39; and log in via phone number.</li>
<li><strong>Telegram Desktop</strong>: open ☰ Settings &gt; Shift + Alt + Right click 'Add Account' and select 'Test Server'.</li>
<li><strong>macOS</strong>: click the Settings icon 10 times to open the Debug Menu, ⌘ + click 'Add Account' and log in via phone number.</li>
</ul>
<p>After logging in, simply <a href="#creating-a-new-bot">create a new bot</a> following the standard procedure and send your requests to the Test Bot API in this format:</p>
<pre><code>https://api.telegram.org/bot&lt;token&gt;/test/METHOD_NAME</code></pre>
<blockquote>
<p>When working with the test environment, you may use HTTP links without TLS in the <code>url</code> field of both <a href="/bots/api#loginurl">LoginUrl</a> and <a href="/bots/api#webappinfo">WebAppInfo</a>.</p>
</blockquote>
<h4><a class="anchor" name="status-alerts" href="#status-alerts"><i class="anchor-icon"></i></a>Status alerts</h4>
<h4><a class="anchor" href="#status-alerts" id="status-alerts" name="status-alerts"><i class="anchor-icon"></i></a>Status alerts</h4>
<p>Millions choose Telegram for its speed. To best benefit users, your bot also <strong>needs to be responsive</strong>. In order to help developers keep their bots in shape, <a href="https://t.me/botfather">@BotFather</a> will send <strong>status alerts</strong> if it sees something is wrong.</p>
<p>We check the number of replies and the <em>request/response</em> conversion rate for popular bots (~300 requests per minute, this value may change in the future). If your bot returns an <strong>abnormally low number</strong>, you will receive a notification from <a href="https://t.me/botfather">@BotFather</a>.</p>
<h5><a class="anchor" name="responding-to-alerts" href="#responding-to-alerts"><i class="anchor-icon"></i></a>Responding to alerts</h5>
<h5><a class="anchor" href="#responding-to-alerts" id="responding-to-alerts" name="responding-to-alerts"><i class="anchor-icon"></i></a>Responding to alerts</h5>
<p>By default, <strong>you will only get one alert per bot per hour</strong>. </p>
<p>Each alert has the following buttons:</p>
<ul>
<li><strong>Fixed</strong> - Use this if you found an issue with your bot and fixed it. If you press the fix button, we will resume sending alerts in the regular way so that you can see if your fix worked within 5-10 minutes instead of having to wait for an hour.</li>
<li><strong>Support</strong> - Use this to open a chat with <a href="https://t.me/botsupport">@BotSupport</a> if you don&#39;t see any issues with your bot or if you think the problem is on our side.</li>
<li><strong>Mute for 8h/1w</strong> - Use this if you can&#39;t fix your bot at the moment. This will disable all alerts for the bot in question for the specified period of time. <strong>We do not recommend</strong> using this option since your users may migrate to a more stable bot. You can unmute alerts in your bot&#39;s settings via <a href="https://t.me/botfather">@BotFather</a>.</li>
<li><strong>Support</strong> - Use this to open a chat with <a href="https://t.me/botsupport">@BotSupport</a> if you don't see any issues with your bot or if you think the problem is on our side.</li>
<li><strong>Mute for 8h/1w</strong> - Use this if you can't fix your bot at the moment. This will disable all alerts for the bot in question for the specified period of time. <strong>We do not recommend</strong> using this option since your users may migrate to a more stable bot. You can unmute alerts in your bot's settings via <a href="https://t.me/botfather">@BotFather</a>.</li>
</ul>
<h5><a class="anchor" name="monitored-issues" href="#monitored-issues"><i class="anchor-icon"></i></a>Monitored issues</h5>
<h5><a class="anchor" href="#monitored-issues" id="monitored-issues" name="monitored-issues"><i class="anchor-icon"></i></a>Monitored issues</h5>
<p>We currently notify you about the following issues:</p>
<ul>
<li><p><strong>Too few private messages are sent.</strong> Value: <strong>{value}</strong> - Your bot is sending far fewer messages than it did in previous weeks. This is useful for newsletter-style bots that send messages without prompts from users. The larger the value, the more significant the difference.</p>
<li>
<p><strong>Too few private messages are sent.</strong> Value: <strong>{value}</strong> - Your bot is sending far fewer messages than it did in previous weeks. This is useful for newsletter-style bots that send messages without prompts from users. The larger the value, the more significant the difference.</p>
</li>
<li><p><strong>Too few replies to incoming private messages</strong>. Conversion rate: <strong>{value}</strong> - Your bot is not replying to all messages that are being sent to it (the request/response conversion rate for your bot was too low for at least two of the last three 5-minute periods). </p>
<li>
<p><strong>Too few replies to incoming private messages</strong>. Conversion rate: <strong>{value}</strong> - Your bot is not replying to all messages that are being sent to it (the request/response conversion rate for your bot was too low for at least two of the last three 5-minute periods). </p>
</li>
</ul>
<blockquote>
<p>To provide a good user experience, please respond to all messages that are sent to your bot. Respond to message updates by calling send… methods (e.g. <a href="/bots/api#sendmessage">sendMessage</a>).</p>
</blockquote>
<ul>
<li><strong>Too few answers to inline queries</strong>. Conversion rate: <strong>{value}</strong> - Your bot is not replying to all inline queries that are being sent to it, calculated in the same way as above. Respond to <code>inline_query</code> updates by calling <a href="/bots/api#answerinlinequery">answerInlineQuery</a>.</li>
<li>
<p><strong>Too few answers to inline queries</strong>. Conversion rate: <strong>{value}</strong> - Your bot is not replying to all inline queries that are being sent to it, calculated in the same way as above. Respond to <code>inline_query</code> updates by calling <a href="/bots/api#answerinlinequery">answerInlineQuery</a>.</p>
</li>
<li>
<p><strong>Too few answers to callback queries</strong>. Conversion rate: <strong>{value}</strong></p>
</li>
<li>
<p><strong>Too few answers to callback game queries</strong>. Conversion rate: <strong>{value}</strong> - Your bot is not replying to all callback queries that are being sent to it (with or without games), calculated in the same way as above. Respond to <code>callback_query</code> updates by calling <a href="/bots/api#answercallbackquery">answerCallbackQuery</a>.</p>
</li>
</ul>
<ul>
<li><strong>Too few answers to callback queries</strong>. Conversion rate: <strong>{value}</strong></li>
<li><strong>Too few answers to callback game queries</strong>. Conversion rate: <strong>{value}</strong> - Your bot is not replying to all callback queries that are being sent to it (with or without games), calculated in the same way as above. Respond to <code>callback_query</code> updates by calling <a href="/bots/api#answercallbackquery">answerCallbackQuery</a>.</li>
</ul>
<h4><a class="anchor" name="local-bot-api" href="#local-bot-api"><i class="anchor-icon"></i></a>Local Bot API</h4>
<p>You can host and work with <strong>your own instance</strong> of our open-source <a href="/bots/api">Bot API</a>.<br>The <strong>source code</strong> is available <a href="https://github.com/tdlib/telegram-bot-api">here</a>, along with a quick <a href="https://github.com/tdlib/telegram-bot-api#installation">installation guide</a>.</p>
<h4><a class="anchor" href="#local-bot-api" id="local-bot-api" name="local-bot-api"><i class="anchor-icon"></i></a>Local Bot API</h4>
<p>You can host and work with <strong>your own instance</strong> of our open-source <a href="/bots/api">Bot API</a>.
The <strong>source code</strong> is available <a href="https://github.com/tdlib/telegram-bot-api">here</a>, along with a quick <a href="https://github.com/tdlib/telegram-bot-api#installation">installation guide</a>.</p>
<p>After <strong>installing the server</strong>, remember to use the <a href="/bots/api#logout">logOut</a> method before <strong>redirecting requests</strong> to your new local API URL.</p>
<blockquote>
<p>Your local instance runs on port <code>8081</code> by default and will only accept HTTP requests, so a TLS termination proxy has to be used to handle remote HTTPS requests.</p>
</blockquote>
<p>By hosting our API locally you&#39;ll gain access to <strong>some upgrades</strong>, including:</p>
<p>By hosting our API locally you'll gain access to <strong>some upgrades</strong>, including:</p>
<table class="table">
<thead>
<tr>
@ -506,31 +504,36 @@ width=44% /></a>
</tbody>
</table>
<blockquote>
<p>You can find an exhaustive list <a href="/bots/api#using-a-local-bot-api-server">here</a>.<br>All limits may be subject to change in the future, so make sure to follow <a href="https://t.me/botnews">@BotNews</a>.</p>
<p>You can find an exhaustive list <a href="/bots/api#using-a-local-bot-api-server">here</a>.
All limits may be subject to change in the future, so make sure to follow <a href="https://t.me/botnews">@BotNews</a>.</p>
</blockquote>
<hr>
<h3><a class="anchor" name="botfather" href="#botfather"><i class="anchor-icon"></i></a>BotFather</h3>
<h3><a class="anchor" href="#botfather" id="botfather" name="botfather"><i class="anchor-icon"></i></a>BotFather</h3>
<p>Below is a detailed guide to using <a href="https://t.me/botfather">@BotFather</a>, Telegrams tool for <strong>creating</strong> and <strong>managing</strong> bots.</p>
<h4><a class="anchor" name="creating-a-new-bot" href="#creating-a-new-bot"><i class="anchor-icon"></i></a>Creating a new bot</h4>
<h4><a class="anchor" href="#creating-a-new-bot" id="creating-a-new-bot" name="creating-a-new-bot"><i class="anchor-icon"></i></a>Creating a new bot</h4>
<p>Use the <code>/newbot</code> command to create a new bot. <a href="https://t.me/botfather">@BotFather</a> will ask you for a name and username, then generate an authentication token for your new bot.</p>
<ul>
<li><p>The <strong>name</strong> of your bot is displayed in contact details and elsewhere.</p>
<li>
<p>The <strong>name</strong> of your bot is displayed in contact details and elsewhere.</p>
</li>
<li><p>The <strong>username</strong> is a short name, used in search, mentions and t.me links. Usernames are 5-32 characters long and not case sensitive but may only include Latin characters, numbers, and underscores. Your bot&#39;s username must end in &#39;bot, like &#39;tetris_bot&#39; or &#39;TetrisBot&#39;.</p>
<li>
<p>The <strong>username</strong> is a short name, used in search, mentions and t.me links. Usernames are 5-32 characters long and not case sensitive but may only include Latin characters, numbers, and underscores. Your bot's username must end in 'bot, like 'tetris_bot' or 'TetrisBot'.</p>
</li>
<li><p>The <strong>token</strong> is a string, like <code>110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw</code>, which is required to authorize the bot and send requests to the Bot API. Keep your token secure and store it safely, it can be used by anyone to control your bot. </p>
<li>
<p>The <strong>token</strong> is a string, like <code>110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw</code>, which is required to authorize the bot and send requests to the Bot API. Keep your token secure and store it safely, it can be used by anyone to control your bot. </p>
</li>
</ul>
<blockquote>
<p>Unlike the bots name, the username cannot be changed later so choose it carefully.<br>When sending a request to api.telegram.org, remember to prefix the word bot to your token.</p>
<p>Unlike the bots name, the username cannot be changed later so choose it carefully.
When sending a request to api.telegram.org, remember to prefix the word bot to your token.</p>
</blockquote>
<h4><a class="anchor" name="about-text-description-and-profile-media" href="#about-text-description-and-profile-media"><i class="anchor-icon"></i></a>About text, description and profile media</h4>
<p>When new users open your bot, they will be met with a helpful description in a box titled “What can this bot do?”.</p>
<h4><a class="anchor" href="#about-text-description-and-profile-media" id="about-text-description-and-profile-media" name="about-text-description-and-profile-media"><i class="anchor-icon"></i></a>About text, description and profile media</h4>
<p>When new users open your bot, they will be met with a helpful description in a box titled "What can this bot do?".</p>
<p>Properly <a href="#edit-bots">setting this field</a> in <a href="https://t.me/botfather">@BotFather</a> allows everyone to immediately get an idea of what your bot can do your description should be <strong>brief</strong>, <strong>to the point</strong> and <strong>on topic</strong>.</p>
<blockquote>
<p>You can also add a photo or video to this field with <code>Edit Description Picture</code> in <a href="https://t.me/botfather">@BotFather</a>.</p>
</blockquote>
<p>Additionally, just like normal users, bots also come with a <strong>short bio</strong> available on their profile. If you didn&#39;t specify this field while first creating your bot, you can set it at any time with the <code>/setabouttext</code> command in <a href="https://t.me/botfather">@BotFather</a>. Users can interact with many bots and they won&#39;t have access to their description after starting them having a quick reminder of the bot&#39;s purpose can be very useful.</p>
<p>Additionally, just like normal users, bots also come with a <strong>short bio</strong> available on their profile. If you didn't specify this field while first creating your bot, you can set it at any time with the <code>/setabouttext</code> command in <a href="https://t.me/botfather">@BotFather</a>. Users can interact with many bots and they won't have access to their description after starting them having a quick reminder of the bot's purpose can be very useful.</p>
<blockquote>
<p>Note that both the <strong>Description</strong> and the <strong>About text</strong> can be <a href="https://core.telegram.org/bots/api#setmydescription">natively localized</a> each user will automatically see the correct translation for their language.</p>
</blockquote>
@ -538,36 +541,38 @@ width=44% /></a>
<blockquote>
<p>Starting from April 21, 2023 (<a href="https://telegram.org/blog/shareable-folders-custom-wallpapers">Telegram 9.6</a>), you can edit your bot directly from its profile page including setting a custom <strong>profile video</strong>.</p>
</blockquote>
<h4><a class="anchor" name="generating-an-authentication-token" href="#generating-an-authentication-token"><i class="anchor-icon"></i></a>Generating an authentication token</h4>
<h4><a class="anchor" href="#generating-an-authentication-token" id="generating-an-authentication-token" name="generating-an-authentication-token"><i class="anchor-icon"></i></a>Generating an authentication token</h4>
<p>If your existing token is <strong>compromised</strong> or <strong>you lost it</strong> for some reason, use the <code>/token</code> command to generate a new one.</p>
<h4><a class="anchor" name="transfer-ownership" href="#transfer-ownership"><i class="anchor-icon"></i></a>Transfer ownership</h4>
<p>You can transfer ownership of your bot <strong>to another user</strong>.<br>To do this, send <code>/mybots</code>, select your bot, then <em>transfer ownership</em>.<br>You can only transfer a bot to users who have interacted with it at least once.</p>
<h4><a class="anchor" href="#transfer-ownership" id="transfer-ownership" name="transfer-ownership"><i class="anchor-icon"></i></a>Transfer ownership</h4>
<p>You can transfer ownership of your bot <strong>to another user</strong>.
To do this, send <code>/mybots</code>, select your bot, then <em>transfer ownership</em>.
You can only transfer a bot to users who have interacted with it at least once.</p>
<blockquote>
<p>Transferring ownership will give full control of the bot to another user they will be able to access the bots messages and even delete it. The transfer is permanent, so please consider it carefully.</p>
</blockquote>
<h4><a class="anchor" name="botfather-commands" href="#botfather-commands"><i class="anchor-icon"></i></a>BotFather commands</h4>
<h4><a class="anchor" href="#botfather-commands" id="botfather-commands" name="botfather-commands"><i class="anchor-icon"></i></a>BotFather commands</h4>
<p>The remaining commands are pretty self-explanatory:</p>
<ul>
<li>/mybots returns a list of your bots with handy controls to edit their settings.</li>
<li>/mygames does the same for your games.</li>
</ul>
<h4><a class="anchor" name="edit-bots" href="#edit-bots"><i class="anchor-icon"></i></a>Edit bots</h4>
<h4><a class="anchor" href="#edit-bots" id="edit-bots" name="edit-bots"><i class="anchor-icon"></i></a>Edit bots</h4>
<p>To edit your bot, you have two options.</p>
<p>You can use the available commands:</p>
<ul>
<li>/setname change your bot&#39;s <strong>name</strong>.</li>
<li>/setdescription change the bot&#39;s <strong>description</strong> (short text up to 512 characters). Users will see this text at the beginning of the conversation with the bot, titled &#39;<em>What can this bot do?</em>&#39;.</li>
<li>/setabouttext change the bot&#39;s <strong>about info</strong>, a shorter text up to 120 characters. Users will see this text on the bot&#39;s profile page. When they share your bot with someone, this text is sent together with the link.</li>
<li>/setuserpic change the bot&#39;s <strong>profile picture</strong>. </li>
<li>/setname change your bot's <strong>name</strong>.</li>
<li>/setdescription change the bot's <strong>description</strong> (short text up to 512 characters). Users will see this text at the beginning of the conversation with the bot, titled '<em>What can this bot do?</em>'.</li>
<li>/setabouttext change the bot's <strong>about info</strong>, a shorter text up to 120 characters. Users will see this text on the bot's profile page. When they share your bot with someone, this text is sent together with the link.</li>
<li>/setuserpic change the bot's <strong>profile picture</strong>. </li>
<li>/setcommands change the list of <strong>commands</strong> supported by your bot. Users will see these commands as suggestions when they type <code>/</code> in the chat with your bot. See <a href="#commands">commands</a> for more info.</li>
<li>/setdomain link a <strong>website domain</strong> to your bot. See the <a href="#login-widget">login widget</a> section.</li>
<li>/deletebot delete your bot and <strong>free its username</strong>. Cannot be undone.</li>
</ul>
<p>Or you can use the <code>/mybots</code> command, tap on your bot and use the modern inline interface to edit it.</p>
<blockquote>
<p>Starting from April 21, 2023 (<a href="https://telegram.org/blog/shareable-folders-custom-wallpapers">Telegram 9.6</a>), you can edit your bot&#39;s public-facing info directly from its profile page including setting a custom <strong>profile video</strong>.</p>
<p>Starting from April 21, 2023 (<a href="https://telegram.org/blog/shareable-folders-custom-wallpapers">Telegram 9.6</a>), you can edit your bot's public-facing info directly from its profile page including setting a custom <strong>profile video</strong>.</p>
</blockquote>
<h4><a class="anchor" name="edit-settings" href="#edit-settings"><i class="anchor-icon"></i></a>Edit settings</h4>
<h4><a class="anchor" href="#edit-settings" id="edit-settings" name="edit-settings"><i class="anchor-icon"></i></a>Edit settings</h4>
<ul>
<li>/setinline toggle <strong>inline mode</strong> for your bot.</li>
<li>/setinlinegeo request <strong>location data</strong> to provide location-based inline results.</li>
@ -575,7 +580,7 @@ width=44% /></a>
<li>/setinlinefeedback toggle whether the API should <strong>send updates about the results</strong> chosen by users. See an in-depth explanation <a href="/bots/inline#collecting-feedback">here</a>.</li>
<li>/setprivacy set which messages your bot will receive when added to a group. See <a href="#privacy-mode">privacy-mode</a> for more info.</li>
</ul>
<h4><a class="anchor" name="manage-games" href="#manage-games"><i class="anchor-icon"></i></a>Manage games</h4>
<h4><a class="anchor" href="#manage-games" id="manage-games" name="manage-games"><i class="anchor-icon"></i></a>Manage games</h4>
<ul>
<li>/newgame create a new game.</li>
<li>/listgames see a list of your games.</li>
@ -589,9 +594,8 @@ width=44% /></a>
<p>With this information, you are ready to proceed to our <a href="/bots/api">Full API Reference for Developers</a>.</p>
<ul>
<li>If you have any questions, check out our <a href="/bots/faq">Bot FAQ</a>.</li>
<li>If you&#39;re experiencing issues with our API, please contact <a href="https://t.me/botsupport">@BotSupport</a> on Telegram.</li>
</ul>
</div>
<li>If you're experiencing issues with our API, please contact <a href="https://t.me/botsupport">@BotSupport</a> on Telegram.</li>
</ul></div>
</div>

View file

@ -47,195 +47,341 @@
</blockquote>
<p>This page lists some libraries and frameworks <strong>developed by the Telegram community</strong> you should take care to report any bugs you may find to the respective developers, as these projects are not maintained by Telegram.</p>
<p>Ping us on <a href="https://telegram.me/botsupport">@BotSupport</a> if you would like your library to appear on this page.</p>
<h4><a class="anchor" name="php" href="#php"><i class="anchor-icon"></i></a>PHP</h4>
<h4><a class="anchor" href="#php" id="php" name="php"><i class="anchor-icon"></i></a>PHP</h4>
<ul>
<li><p><strong>Nutgram</strong>. The Telegram bot framework that doesn&#39;t drive you nuts.<br><a href="https://github.com/nutgram/nutgram">https://github.com/nutgram/nutgram</a></p>
<li>
<p><strong>Nutgram</strong>. The Telegram bot framework that doesn't drive you nuts.
<a href="https://github.com/nutgram/nutgram">https://github.com/nutgram/nutgram</a></p>
</li>
<li><p><strong>Telegraph</strong>. A Laravel package for fluently interacting with Telegram Bots.<br><a href="https://github.com/def-studio/telegraph">https://github.com/def-studio/telegraph</a></p>
<li>
<p><strong>Telegraph</strong>. A Laravel package for fluently interacting with Telegram Bots.
<a href="https://github.com/def-studio/telegraph">https://github.com/def-studio/telegraph</a></p>
</li>
<li><p><strong>tgWebValid</strong>. Library for Telegram Web App User Validation and Telegram Login Widget for PHP.<br><a href="https://github.com/CrazyTapok-bit/tgWebValid">https://github.com/CrazyTapok-bit/tgWebValid</a></p>
<li>
<p><strong>tgWebValid</strong>. Library for Telegram Web App User Validation and Telegram Login Widget for PHP.
<a href="https://github.com/CrazyTapok-bit/tgWebValid">https://github.com/CrazyTapok-bit/tgWebValid</a></p>
</li>
<li><p><strong>BPT</strong>. A simple library for working with Telegram Api.<br><a href="https://github.com/BPTproto/BPT">https://github.com/BPTproto/BPT</a><br><a href="https://github.com/BPTproto/BPT-Multi">https://github.com/BPTproto/BPT-Multi</a></p>
<li>
<p><strong>BPT</strong>. A simple library for working with Telegram Api.
<a href="https://github.com/BPTproto/BPT">https://github.com/BPTproto/BPT</a>
<a href="https://github.com/BPTproto/BPT-Multi">https://github.com/BPTproto/BPT-Multi</a></p>
</li>
<li><p><strong>LaraGram</strong>. An advanced framework for Telegram Bot development.<br><a href="https://github.com/laraXgram/LaraGram">https://github.com/laraXgram/LaraGram</a></p>
<li>
<p><strong>LaraGram</strong>. An advanced framework for Telegram Bot development.
<a href="https://github.com/laraXgram/LaraGram">https://github.com/laraXgram/LaraGram</a></p>
</li>
<li><p><strong>BotAPI</strong>. SDK for the Telegram Bot API.<br><a href="https://github.com/TelegramSDK/BotAPI">https://github.com/TelegramSDK/BotAPI</a></p>
<li>
<p><strong>BotAPI</strong>. SDK for the Telegram Bot API.
<a href="https://github.com/TelegramSDK/BotAPI">https://github.com/TelegramSDK/BotAPI</a></p>
</li>
<li><p><strong>TuriBot</strong>. A simple way to communicate with Telegram APIs in PHP.<br><a href="https://github.com/davtur19/TuriBot">https://github.com/davtur19/TuriBot</a></p>
<li>
<p><strong>TuriBot</strong>. A simple way to communicate with Telegram APIs in PHP.
<a href="https://github.com/davtur19/TuriBot">https://github.com/davtur19/TuriBot</a></p>
</li>
<li><p><strong>TelegramBotsApi</strong>. SDK for Telegram Bot API.<br><a href="https://github.com/kuvardin/TelegramBotsApi">https://github.com/kuvardin/TelegramBotsApi</a></p>
<li>
<p><strong>TelegramBotsApi</strong>. SDK for Telegram Bot API.
<a href="https://github.com/kuvardin/TelegramBotsApi">https://github.com/kuvardin/TelegramBotsApi</a></p>
</li>
<li><p><strong>PHP Telegram Bot</strong>. PHP Telegram Bot based on the official Telegram Bot API.<br><a href="https://github.com/php-telegram-bot/core">https://github.com/php-telegram-bot/core</a></p>
<li>
<p><strong>PHP Telegram Bot</strong>. PHP Telegram Bot based on the official Telegram Bot API.
<a href="https://github.com/php-telegram-bot/core">https://github.com/php-telegram-bot/core</a></p>
</li>
<li><p><strong>Telegram Bot PHP</strong>. A library that makes using Telegram Bot API much easier.<br><a href="https://github.com/telegram-bot-php/core">https://github.com/telegram-bot-php/core</a></p>
<li>
<p><strong>Telegram Bot PHP</strong>. A library that makes using Telegram Bot API much easier.
<a href="https://github.com/telegram-bot-php/core">https://github.com/telegram-bot-php/core</a></p>
</li>
<li><p><strong>PHP Telegram API</strong>. A complete async capable Telegram Bot API implementation for PHP7.<br><a href="https://github.com/unreal4u/telegram-api">https://github.com/unreal4u/telegram-api</a></p>
<li>
<p><strong>PHP Telegram API</strong>. A complete async capable Telegram Bot API implementation for PHP7.
<a href="https://github.com/unreal4u/telegram-api">https://github.com/unreal4u/telegram-api</a></p>
</li>
<li><p><strong>Bot API PHP SDK</strong>. Telegram Bot API PHP SDK. Supports Laravel out of the box.<br><a href="https://github.com/irazasyed/telegram-bot-sdk">https://github.com/irazasyed/telegram-bot-sdk</a></p>
<li>
<p><strong>Bot API PHP SDK</strong>. Telegram Bot API PHP SDK. Supports Laravel out of the box.
<a href="https://github.com/irazasyed/telegram-bot-sdk">https://github.com/irazasyed/telegram-bot-sdk</a></p>
</li>
<li><p><strong>klev-o/telegram-bot-api</strong>. Simple and convenient object-oriented implementation Telegram Bot API with PHP version ^7.4 support.<br><a href="https://github.com/klev-o/telegram-bot-api">https://github.com/klev-o/telegram-bot-api</a></p>
<li>
<p><strong>klev-o/telegram-bot-api</strong>. Simple and convenient object-oriented implementation Telegram Bot API with PHP version ^7.4 support.
<a href="https://github.com/klev-o/telegram-bot-api">https://github.com/klev-o/telegram-bot-api</a></p>
</li>
<li><p><strong>TeleBot</strong>. Easy way to create Telegram bots in PHP. Rich Laravel support out of the box.<br><a href="https://github.com/westacks/telebot">https://github.com/westacks/telebot</a></p>
<li>
<p><strong>TeleBot</strong>. Easy way to create Telegram bots in PHP. Rich Laravel support out of the box.
<a href="https://github.com/westacks/telebot">https://github.com/westacks/telebot</a></p>
</li>
<li><p><strong>TgBotLib</strong>. Telegram Bot Library for ncc.<br><a href="https://github.com/nosial/TgBotLib">https://github.com/nosial/TgBotLib</a></p>
<li>
<p><strong>TgBotLib</strong>. Telegram Bot Library for ncc.
<a href="https://github.com/nosial/TgBotLib">https://github.com/nosial/TgBotLib</a></p>
</li>
<li><p><strong>NeleBot X Framework</strong>. Framework for Telegram Bot API.<br><a href="https://github.com/NeleB54Gold/NeleBotX">https://github.com/NeleB54Gold/NeleBotX</a></p>
<li>
<p><strong>NeleBot X Framework</strong>. Framework for Telegram Bot API.
<a href="https://github.com/NeleB54Gold/NeleBotX">https://github.com/NeleB54Gold/NeleBotX</a></p>
</li>
<li><p><strong>PHP Telegram Bot Api</strong>. Native PHP Wrapper for Telegram BOT API.<br><a href="https://github.com/TelegramBot/Api">https://github.com/TelegramBot/Api</a></p>
<li>
<p><strong>PHP Telegram Bot Api</strong>. Native PHP Wrapper for Telegram BOT API.
<a href="https://github.com/TelegramBot/Api">https://github.com/TelegramBot/Api</a></p>
</li>
<li><p><strong>NovaGram</strong>. An Object-Oriented PHP library for Telegram Bots.<br><a href="https://github.com/skrtdev/NovaGram">https://github.com/skrtdev/NovaGram</a></p>
<li>
<p><strong>NovaGram</strong>. An Object-Oriented PHP library for Telegram Bots.
<a href="https://github.com/skrtdev/NovaGram">https://github.com/skrtdev/NovaGram</a></p>
</li>
</ul>
<h4><a class="anchor" name="go" href="#go"><i class="anchor-icon"></i></a>Go</h4>
<h4><a class="anchor" href="#go" id="go" name="go"><i class="anchor-icon"></i></a>Go</h4>
<ul>
<li><p><strong>Golang Telegram Bot library</strong>. An autogenerated wrapper for the Telegram Bot API. Inspired by the python-telegram-bot library.<br><a href="https://github.com/paulsonoflars/gotgbot">https://github.com/paulsonoflars/gotgbot</a></p>
<li>
<p><strong>Golang Telegram Bot library</strong>. An autogenerated wrapper for the Telegram Bot API. Inspired by the python-telegram-bot library.
<a href="https://github.com/paulsonoflars/gotgbot">https://github.com/paulsonoflars/gotgbot</a></p>
</li>
<li><p><strong>Telego</strong>. Telegram Bot API library.<br><a href="https://github.com/mymmrac/telego">https://github.com/mymmrac/telego</a></p>
<li>
<p><strong>Telego</strong>. Telegram Bot API library.
<a href="https://github.com/mymmrac/telego">https://github.com/mymmrac/telego</a></p>
</li>
<li><p><strong>Golang Telegram Bot</strong>. Telegram Bot API Go framework.<br><a href="https://github.com/go-telegram/bot">https://github.com/go-telegram/bot</a></p>
<li>
<p><strong>Golang Telegram Bot</strong>. Telegram Bot API Go framework.
<a href="https://github.com/go-telegram/bot">https://github.com/go-telegram/bot</a></p>
</li>
<li><p><strong>go-tg</strong>. Library for accessing Telegram Bot API, with batteries for building complex bots included.<br><a href="https://github.com/mr-linch/go-tg">https://github.com/mr-linch/go-tg</a></p>
<li>
<p><strong>go-tg</strong>. Library for accessing Telegram Bot API, with batteries for building complex bots included.
<a href="https://github.com/mr-linch/go-tg">https://github.com/mr-linch/go-tg</a></p>
</li>
<li><p><strong>Telegram Bot API: Go implementation</strong>. A Telegram IM bots API implementation.<br><a href="https://github.com/temoon/telegram-bots-api">https://github.com/temoon/telegram-bots-api</a></p>
<li>
<p><strong>Telegram Bot API: Go implementation</strong>. A Telegram IM bots API implementation.
<a href="https://github.com/temoon/telegram-bots-api">https://github.com/temoon/telegram-bots-api</a></p>
</li>
<li><p><strong>echotron</strong>. An elegant and concurrent library for the Telegram Bot API.<br><a href="https://github.com/NicoNex/echotron">https://github.com/NicoNex/echotron</a></p>
<li>
<p><strong>echotron</strong>. An elegant and concurrent library for the Telegram Bot API.
<a href="https://github.com/NicoNex/echotron">https://github.com/NicoNex/echotron</a></p>
</li>
<li><p><strong>Telegram Bot API helper for Golang</strong>. A Telegram Bot API wrapper.<br><a href="https://github.com/meinside/telegram-bot-go">https://github.com/meinside/telegram-bot-go</a></p>
<li>
<p><strong>Telegram Bot API helper for Golang</strong>. A Telegram Bot API wrapper.
<a href="https://github.com/meinside/telegram-bot-go">https://github.com/meinside/telegram-bot-go</a></p>
</li>
<li><p><strong>telebot</strong>. A Telegram bot framework.<br><a href="https://github.com/tucnak/telebot">https://github.com/tucnak/telebot</a></p>
<li>
<p><strong>telebot</strong>. A Telegram bot framework.
<a href="https://github.com/tucnak/telebot">https://github.com/tucnak/telebot</a></p>
</li>
<li><p><strong>Telegrambot</strong>. Telegram Bot API in Go, but with more clean code.<br><a href="https://github.com/nickname76/telegrambot">https://github.com/nickname76/telegrambot</a></p>
<li>
<p><strong>Telegrambot</strong>. Telegram Bot API in Go, but with more clean code.
<a href="https://github.com/nickname76/telegrambot">https://github.com/nickname76/telegrambot</a></p>
</li>
</ul>
<h4><a class="anchor" name="python" href="#python"><i class="anchor-icon"></i></a>Python</h4>
<h4><a class="anchor" href="#python" id="python" name="python"><i class="anchor-icon"></i></a>Python</h4>
<ul>
<li><p><strong>AIOGram</strong>. A pretty simple and fully asynchronous library for Telegram Bot API written with asyncio and aiohttp.<br><a href="https://github.com/aiogram/aiogram">https://github.com/aiogram/aiogram</a></p>
<li>
<p><strong>AIOGram</strong>. A pretty simple and fully asynchronous library for Telegram Bot API written with asyncio and aiohttp.
<a href="https://github.com/aiogram/aiogram">https://github.com/aiogram/aiogram</a></p>
</li>
<li><p><strong>python-telegram-bot</strong>. A wrapper you can&#39;t refuse.<br><a href="https://github.com/python-telegram-bot/python-telegram-bot">https://github.com/python-telegram-bot/python-telegram-bot</a></p>
<li>
<p><strong>python-telegram-bot</strong>. A wrapper you can't refuse.
<a href="https://github.com/python-telegram-bot/python-telegram-bot">https://github.com/python-telegram-bot/python-telegram-bot</a></p>
</li>
<li><p><strong>pyTelegramBotAPI</strong>. A simple, but extensible Python implementation for the Telegram Bot API.<br><a href="https://github.com/eternnoir/pyTelegramBotAPI">https://github.com/eternnoir/pyTelegramBotAPI</a></p>
<li>
<p><strong>pyTelegramBotAPI</strong>. A simple, but extensible Python implementation for the Telegram Bot API.
<a href="https://github.com/eternnoir/pyTelegramBotAPI">https://github.com/eternnoir/pyTelegramBotAPI</a></p>
</li>
<li><p><strong>telegram-text</strong>. A Python markup module, which can be used with other frameworks.<br><a href="https://github.com/SKY-ALIN/telegram-text">https://github.com/SKY-ALIN/telegram-text</a></p>
<li>
<p><strong>telegram-text</strong>. A Python markup module, which can be used with other frameworks.
<a href="https://github.com/SKY-ALIN/telegram-text">https://github.com/SKY-ALIN/telegram-text</a></p>
</li>
<li><p><strong>TGramBot</strong>. A partially auto-generated and asynchronous Minimal Telegram Bot API framework.<br><a href="https://github.com/KeralaBots/TGramBot">https://github.com/KeralaBots/TGramBot</a></p>
<li>
<p><strong>TGramBot</strong>. A partially auto-generated and asynchronous Minimal Telegram Bot API framework.
<a href="https://github.com/KeralaBots/TGramBot">https://github.com/KeralaBots/TGramBot</a></p>
</li>
<li><p><strong>OrigamiBot</strong>. A pythonic Telegram bot API library.<br><a href="https://github.com/cmd410/OrigamiBot">https://github.com/cmd410/OrigamiBot</a></p>
<li>
<p><strong>OrigamiBot</strong>. A pythonic Telegram bot API library.
<a href="https://github.com/cmd410/OrigamiBot">https://github.com/cmd410/OrigamiBot</a></p>
</li>
</ul>
<h4><a class="anchor" name="rust" href="#rust"><i class="anchor-icon"></i></a>Rust</h4>
<h4><a class="anchor" href="#rust" id="rust" name="rust"><i class="anchor-icon"></i></a>Rust</h4>
<ul>
<li><p><strong>Frankenstein</strong>. A Telegram Bot API client.<br><a href="https://github.com/ayrat555/frankenstein">https://github.com/ayrat555/frankenstein</a></p>
<li>
<p><strong>Frankenstein</strong>. A Telegram Bot API client.
<a href="https://github.com/ayrat555/frankenstein">https://github.com/ayrat555/frankenstein</a></p>
</li>
<li><p><strong>teloxide</strong>. An elegant Telegram bots framework.<br><a href="https://github.com/teloxide/teloxide">https://github.com/teloxide/teloxide</a></p>
<li>
<p><strong>teloxide</strong>. An elegant Telegram bots framework.
<a href="https://github.com/teloxide/teloxide">https://github.com/teloxide/teloxide</a></p>
</li>
<li><p><strong>Ferrisgram</strong>. An asynchronous autogenerated wrapper for the Telegram Bot API.<br><a href="https://github.com/ferrisgram/ferrisgram">https://github.com/ferrisgram/ferrisgram</a></p>
<li>
<p><strong>Ferrisgram</strong>. An asynchronous autogenerated wrapper for the Telegram Bot API.
<a href="https://github.com/ferrisgram/ferrisgram">https://github.com/ferrisgram/ferrisgram</a></p>
</li>
<li><p><strong>tgbotapi</strong>. A library for using the Telegram Bot API.<br><a href="https://github.com/Syfaro/tgbotapi-rs">https://github.com/Syfaro/tgbotapi-rs</a></p>
<li>
<p><strong>tgbotapi</strong>. A library for using the Telegram Bot API.
<a href="https://github.com/Syfaro/tgbotapi-rs">https://github.com/Syfaro/tgbotapi-rs</a></p>
</li>
<li><p><strong>carapax</strong>. A Telegram Bot API framework.<br><a href="https://github.com/tg-rs/carapax">https://github.com/tg-rs/carapax</a></p>
<li>
<p><strong>carapax</strong>. A Telegram Bot API framework.
<a href="https://github.com/tg-rs/carapax">https://github.com/tg-rs/carapax</a></p>
</li>
<li><p><strong>MOBOT</strong>. A Telegram Bot Library in Rust.<br><a href="https://github.com/0xfe/mobot">https://github.com/0xfe/mobot</a></p>
<li>
<p><strong>MOBOT</strong>. A Telegram Bot Library in Rust.
<a href="https://github.com/0xfe/mobot">https://github.com/0xfe/mobot</a></p>
</li>
</ul>
<h4><a class="anchor" name="net" href="#net"><i class="anchor-icon"></i></a>.NET</h4>
<h4><a class="anchor" href="#net" id="net" name="net"><i class="anchor-icon"></i></a>.NET</h4>
<ul>
<li><p><strong>Telegram.bot</strong>. .NET Client for Telegram Bot API.<br><a href="https://github.com/TelegramBots/Telegram.Bot">https://github.com/TelegramBots/Telegram.Bot</a></p>
<li>
<p><strong>Telegram.bot</strong>. .NET Client for Telegram Bot API.
<a href="https://github.com/TelegramBots/Telegram.Bot">https://github.com/TelegramBots/Telegram.Bot</a></p>
</li>
<li><p><strong>Telegram.BotAPI for NET</strong>. One of the most complete libraries available to interact with the Telegram Bot API.<br><a href="https://github.com/Eptagone/Telegram.BotAPI">https://github.com/Eptagone/Telegram.BotAPI</a></p>
<li>
<p><strong>Telegram.BotAPI for NET</strong>. One of the most complete libraries available to interact with the Telegram Bot API.
<a href="https://github.com/Eptagone/Telegram.BotAPI">https://github.com/Eptagone/Telegram.BotAPI</a></p>
</li>
<li><p><strong>Telegram Bot Framework</strong>. A context based application framework for the C# TelegramBot library.<br><a href="https://github.com/MajMcCloud/TelegramBotFramework">https://github.com/MajMcCloud/TelegramBotFramework</a></p>
<li>
<p><strong>Telegram Bot Framework</strong>. A context based application framework for the C# TelegramBot library.
<a href="https://github.com/MajMcCloud/TelegramBotFramework">https://github.com/MajMcCloud/TelegramBotFramework</a></p>
</li>
<li><p><strong>RxTelegram.Bot</strong>. RxTelegram uses a reactive approach to make Updates available.<br><a href="https://github.com/RxTelegram/RxTelegram.Bot">https://github.com/RxTelegram/RxTelegram.Bot</a></p>
<li>
<p><strong>RxTelegram.Bot</strong>. RxTelegram uses a reactive approach to make Updates available.
<a href="https://github.com/RxTelegram/RxTelegram.Bot">https://github.com/RxTelegram/RxTelegram.Bot</a></p>
</li>
<li><p><strong>Telegram.Bots</strong>. A .NET 5 wrapper for the Telegram Bot API.<br><a href="https://github.com/TelegramBotsAPI/Telegram.Bots">https://github.com/TelegramBotsAPI/Telegram.Bots</a></p>
<li>
<p><strong>Telegram.Bots</strong>. A .NET 5 wrapper for the Telegram Bot API.
<a href="https://github.com/TelegramBotsAPI/Telegram.Bots">https://github.com/TelegramBotsAPI/Telegram.Bots</a></p>
</li>
</ul>
<h4><a class="anchor" name="kotlin" href="#kotlin"><i class="anchor-icon"></i></a>Kotlin</h4>
<h4><a class="anchor" href="#kotlin" id="kotlin" name="kotlin"><i class="anchor-icon"></i></a>Kotlin</h4>
<ul>
<li><p><strong>TelegramBotAPI</strong>. Type-safe library for work with Telegram Bot API.<br><a href="https://github.com/InsanusMokrassar/TelegramBotAPI">https://github.com/InsanusMokrassar/TelegramBotAPI</a></p>
<li>
<p><strong>TelegramBotAPI</strong>. Type-safe library for work with Telegram Bot API.
<a href="https://github.com/InsanusMokrassar/TelegramBotAPI">https://github.com/InsanusMokrassar/TelegramBotAPI</a></p>
</li>
<li><p><strong>Kotlin Telegram Bot</strong>. Telegram Bot API wrapper, with handy Kotlin DSL.<br><a href="https://github.com/vendelieu/telegram-bot">https://github.com/vendelieu/telegram-bot</a></p>
<li>
<p><strong>Kotlin Telegram Bot</strong>. Telegram Bot API wrapper, with handy Kotlin DSL.
<a href="https://github.com/vendelieu/telegram-bot">https://github.com/vendelieu/telegram-bot</a></p>
</li>
<li><p><strong>Kotlin Telegram Bot</strong>. A wrapper for the Telegram Bot API.<br><a href="https://github.com/kotlin-telegram-bot/kotlin-telegram-bot">https://github.com/kotlin-telegram-bot/kotlin-telegram-bot</a></p>
<li>
<p><strong>Kotlin Telegram Bot</strong>. A wrapper for the Telegram Bot API.
<a href="https://github.com/kotlin-telegram-bot/kotlin-telegram-bot">https://github.com/kotlin-telegram-bot/kotlin-telegram-bot</a></p>
</li>
<li><p><strong>kt-telegram-bot</strong>. Telegram Bot API library for Kotlin language.<br><a href="https://github.com/elbekD/kt-telegram-bot">https://github.com/elbekD/kt-telegram-bot</a></p>
<li>
<p><strong>kt-telegram-bot</strong>. Telegram Bot API library for Kotlin language.
<a href="https://github.com/elbekD/kt-telegram-bot">https://github.com/elbekD/kt-telegram-bot</a></p>
</li>
</ul>
<h4><a class="anchor" name="c" href="#c"><i class="anchor-icon"></i></a>C++</h4>
<h4><a class="anchor" href="#c" id="c" name="c"><i class="anchor-icon"></i></a>C++</h4>
<ul>
<li><p><strong>QTelegramBotAPI</strong>. Telegram Bot API on C++ and Qt.<br><a href="https://github.com/Modersi/TelegramBotAPI">https://github.com/Modersi/TelegramBotAPI</a></p>
<li>
<p><strong>QTelegramBotAPI</strong>. Telegram Bot API on C++ and Qt.
<a href="https://github.com/Modersi/TelegramBotAPI">https://github.com/Modersi/TelegramBotAPI</a></p>
</li>
<li><p><strong>tgbot</strong>. A library for Telegram Bot API with generated API types and methods.<br><a href="https://github.com/egorpugin/tgbot">https://github.com/egorpugin/tgbot</a></p>
<li>
<p><strong>tgbot</strong>. A library for Telegram Bot API with generated API types and methods.
<a href="https://github.com/egorpugin/tgbot">https://github.com/egorpugin/tgbot</a></p>
</li>
<li><p><strong>tgbot-cpp</strong>. A library for Telegram Bot API.<br><a href="https://github.com/reo7sp/tgbot-cpp">https://github.com/reo7sp/tgbot-cpp</a></p>
<li>
<p><strong>tgbot-cpp</strong>. A library for Telegram Bot API.
<a href="https://github.com/reo7sp/tgbot-cpp">https://github.com/reo7sp/tgbot-cpp</a></p>
</li>
</ul>
<h4><a class="anchor" name="ruby" href="#ruby"><i class="anchor-icon"></i></a>Ruby</h4>
<h4><a class="anchor" href="#ruby" id="ruby" name="ruby"><i class="anchor-icon"></i></a>Ruby</h4>
<ul>
<li><p><strong>telegram-bot-ruby</strong>. Ruby wrapper for Telegram&#39;s Bot API.<br><a href="https://github.com/atipugin/telegram-bot-ruby">https://github.com/atipugin/telegram-bot-ruby</a></p>
<li>
<p><strong>telegram-bot-ruby</strong>. Ruby wrapper for Telegram's Bot API.
<a href="https://github.com/atipugin/telegram-bot-ruby">https://github.com/atipugin/telegram-bot-ruby</a></p>
</li>
<li><p><strong>Telegram::Bot</strong>. Ruby gem for building Telegram Bot with optional Rails integration.<br><a href="https://github.com/telegram-bot-rb/telegram-bot">https://github.com/telegram-bot-rb/telegram-bot</a></p>
<li>
<p><strong>Telegram::Bot</strong>. Ruby gem for building Telegram Bot with optional Rails integration.
<a href="https://github.com/telegram-bot-rb/telegram-bot">https://github.com/telegram-bot-rb/telegram-bot</a></p>
</li>
<li><p><strong>TelegramWorkflow</strong>. A simple utility to help you organize the code to create Telegram bots.<br><a href="https://github.com/rsamoilov/telegram_workflow">https://github.com/rsamoilov/telegram_workflow</a></p>
<li>
<p><strong>TelegramWorkflow</strong>. A simple utility to help you organize the code to create Telegram bots.
<a href="https://github.com/rsamoilov/telegram_workflow">https://github.com/rsamoilov/telegram_workflow</a></p>
</li>
</ul>
<h4><a class="anchor" name="node-js" href="#node-js"><i class="anchor-icon"></i></a>Node.js</h4>
<h4><a class="anchor" href="#nodejs" id="nodejs" name="nodejs"><i class="anchor-icon"></i></a>Node.js</h4>
<ul>
<li><p><strong>Telegraf</strong>. Modern Telegram Bot Framework for Node.js.<br><a href="https://github.com/telegraf/telegraf">https://github.com/telegraf/telegraf</a></p>
<li>
<p><strong>Telegraf</strong>. Modern Telegram Bot Framework for Node.js.
<a href="https://github.com/telegraf/telegraf">https://github.com/telegraf/telegraf</a></p>
</li>
<li><p><strong>Telenode</strong>. Lightweight Telegram API framework for Node.js.<br><a href="https://github.com/NivEz/telenode">https://github.com/NivEz/telenode</a></p>
<li>
<p><strong>Telenode</strong>. Lightweight Telegram API framework for Node.js.
<a href="https://github.com/NivEz/telenode">https://github.com/NivEz/telenode</a></p>
</li>
<li><p><strong>Node-Telegram-bot</strong>. Node.js module to interact with the official Telegram Bot API.<br><a href="https://github.com/yagop/node-telegram-bot-api">https://github.com/yagop/node-telegram-bot-api</a></p>
<li>
<p><strong>Node-Telegram-bot</strong>. Node.js module to interact with the official Telegram Bot API.
<a href="https://github.com/yagop/node-telegram-bot-api">https://github.com/yagop/node-telegram-bot-api</a></p>
</li>
</ul>
<h4><a class="anchor" name="typescript" href="#typescript"><i class="anchor-icon"></i></a>TypeScript</h4>
<h4><a class="anchor" href="#typescript" id="typescript" name="typescript"><i class="anchor-icon"></i></a>TypeScript</h4>
<ul>
<li><p><strong>grammY</strong>. The Telegram Bot Framework.<br><a href="https://github.com/grammyjs/grammY">https://github.com/grammyjs/grammY</a></p>
<li>
<p><strong>grammY</strong>. The Telegram Bot Framework.
<a href="https://github.com/grammyjs/grammY">https://github.com/grammyjs/grammY</a></p>
</li>
<li><p><strong>puregram</strong>. Powerful and modern telegram bot api sdk for node.js and typescript.<br><a href="https://github.com/nitreojs/puregram">https://github.com/nitreojs/puregram</a></p>
<li>
<p><strong>puregram</strong>. Powerful and modern telegram bot api sdk for node.js and typescript.
<a href="https://github.com/nitreojs/puregram">https://github.com/nitreojs/puregram</a></p>
</li>
</ul>
<h4><a class="anchor" name="java" href="#java"><i class="anchor-icon"></i></a>Java</h4>
<h4><a class="anchor" href="#java" id="java" name="java"><i class="anchor-icon"></i></a>Java</h4>
<ul>
<li><p><strong>TelegramBots</strong>. A simple to use library to create Telegram Bots.<br><a href="https://github.com/rubenlagus/TelegramBots">https://github.com/rubenlagus/TelegramBots</a></p>
<li>
<p><strong>TelegramBots</strong>. A simple to use library to create Telegram Bots.
<a href="https://github.com/rubenlagus/TelegramBots">https://github.com/rubenlagus/TelegramBots</a></p>
</li>
<li><p><strong>Java API</strong>. Telegram Bot API for Java.<br><a href="https://github.com/pengrad/java-telegram-bot-api">https://github.com/pengrad/java-telegram-bot-api</a></p>
<li>
<p><strong>Java API</strong>. Telegram Bot API for Java.
<a href="https://github.com/pengrad/java-telegram-bot-api">https://github.com/pengrad/java-telegram-bot-api</a></p>
</li>
</ul>
<h4><a class="anchor" name="scala" href="#scala"><i class="anchor-icon"></i></a>Scala</h4>
<h4><a class="anchor" href="#scala" id="scala" name="scala"><i class="anchor-icon"></i></a>Scala</h4>
<ul>
<li><p><strong>bot4s.telegram</strong>. Simple, extensible, strongly-typed wrapper for the Telegram Bot API.<br><a href="https://github.com/bot4s/telegram">https://github.com/bot4s/telegram</a></p>
<li>
<p><strong>bot4s.telegram</strong>. Simple, extensible, strongly-typed wrapper for the Telegram Bot API.
<a href="https://github.com/bot4s/telegram">https://github.com/bot4s/telegram</a></p>
</li>
<li><p><strong>F[Tg] - Telegramium</strong>. Pure functional Telegram Bot API implementation.<br><a href="https://github.com/apimorphism/telegramium">https://github.com/apimorphism/telegramium</a></p>
<li>
<p><strong>F[Tg] - Telegramium</strong>. Pure functional Telegram Bot API implementation.
<a href="https://github.com/apimorphism/telegramium">https://github.com/apimorphism/telegramium</a></p>
</li>
</ul>
<h4><a class="anchor" name="lua" href="#lua"><i class="anchor-icon"></i></a>Lua</h4>
<h4><a class="anchor" href="#lua" id="lua" name="lua"><i class="anchor-icon"></i></a>Lua</h4>
<ul>
<li><p><strong>ggram</strong>. Lua library for the Telegram bot API. You can even use it in Garry&#39;s Mod.<br><a href="https://github.com/TRIGONIM/ggram">https://github.com/TRIGONIM/ggram</a></p>
<li>
<p><strong>ggram</strong>. Lua library for the Telegram bot API. You can even use it in Garry's Mod.
<a href="https://github.com/TRIGONIM/ggram">https://github.com/TRIGONIM/ggram</a></p>
</li>
<li><p><strong>telegram-bot-lua</strong>. A feature-filled Telegram Bot API library.<br><a href="https://github.com/wrxck/telegram-bot-lua">https://github.com/wrxck/telegram-bot-lua</a></p>
<li>
<p><strong>telegram-bot-lua</strong>. A feature-filled Telegram Bot API library.
<a href="https://github.com/wrxck/telegram-bot-lua">https://github.com/wrxck/telegram-bot-lua</a></p>
</li>
</ul>
<h4><a class="anchor" name="other-languages" href="#other-languages"><i class="anchor-icon"></i></a>Other Languages</h4>
<h4><a class="anchor" href="#other-languages" id="other-languages" name="other-languages"><i class="anchor-icon"></i></a>Other Languages</h4>
<ul>
<li><p>Swift. <strong>Telegram Vapor Bot</strong>. The wrapper for the Telegram Bot API written in Swift with Vapor.<br><a href="https://github.com/nerzh/telegram-vapor-bot">https://github.com/nerzh/telegram-vapor-bot</a></p>
<li>
<p>Swift. <strong>Telegram Vapor Bot</strong>. The wrapper for the Telegram Bot API written in Swift with Vapor.
<a href="https://github.com/nerzh/telegram-vapor-bot">https://github.com/nerzh/telegram-vapor-bot</a></p>
</li>
<li><p>Elixir. <strong>ExGram</strong>. Telegram Bot API low level API and framework.<br><a href="https://github.com/rockneurotiko/ex_gram">https://github.com/rockneurotiko/ex_gram</a></p>
<li>
<p>Elixir. <strong>ExGram</strong>. Telegram Bot API low level API and framework.
<a href="https://github.com/rockneurotiko/ex_gram">https://github.com/rockneurotiko/ex_gram</a></p>
</li>
<li><p>Dart. <strong>TeleDart</strong>. A library interfacing with the latest Telegram Bot API.<br><a href="https://github.com/DinoLeung/TeleDart">https://github.com/DinoLeung/TeleDart</a></p>
<li>
<p>Dart. <strong>TeleDart</strong>. A library interfacing with the latest Telegram Bot API.
<a href="https://github.com/DinoLeung/TeleDart">https://github.com/DinoLeung/TeleDart</a></p>
</li>
<li><p>Pascal. <strong>TGBotMini</strong>. Telegram Bot Mini API.<br><a href="https://github.com/HemulGM/TGBotMini">https://github.com/HemulGM/TGBotMini</a></p>
<li>
<p>Pascal. <strong>TGBotMini</strong>. Telegram Bot Mini API.
<a href="https://github.com/HemulGM/TGBotMini">https://github.com/HemulGM/TGBotMini</a></p>
</li>
<li><p>Clojure. <strong>telegrambot-lib</strong>. A library for interacting with the Telegram Bot API.<br><a href="https://github.com/wdhowe/telegrambot-lib">https://github.com/wdhowe/telegrambot-lib</a></p>
<li>
<p>Clojure. <strong>telegrambot-lib</strong>. A library for interacting with the Telegram Bot API.
<a href="https://github.com/wdhowe/telegrambot-lib">https://github.com/wdhowe/telegrambot-lib</a></p>
</li>
<li><p>OCaml. <strong>TelegraML</strong>. A library for creating bots for Telegram.<br><a href="https://github.com/nv-vn/TelegraML">https://github.com/nv-vn/TelegraML</a></p>
<li>
<p>OCaml. <strong>TelegraML</strong>. A library for creating bots for Telegram.
<a href="https://github.com/nv-vn/TelegraML">https://github.com/nv-vn/TelegraML</a></p>
</li>
<li><p>Haskell. <strong>haskell-telegram-api</strong>. High-level bindings to the Telegram Bot API based on <a href="https://haskell-servant.github.io/">servant</a> library.<br><a href="https://github.com/klappvisor/haskell-telegram-api">https://github.com/klappvisor/haskell-telegram-api</a></p>
<li>
<p>Haskell. <strong>haskell-telegram-api</strong>. High-level bindings to the Telegram Bot API based on <a href="https://haskell-servant.github.io/">servant</a> library.
<a href="https://github.com/klappvisor/haskell-telegram-api">https://github.com/klappvisor/haskell-telegram-api</a></p>
</li>
<li><p>Perl. <strong>Telegram Bot</strong>. A genuine Perl 6 client for the Telegram&#39;s Bot API.<br><a href="https://github.com/GildedHonour/TelegramBot">https://github.com/GildedHonour/TelegramBot</a></p>
<li>
<p>Perl. <strong>Telegram Bot</strong>. A genuine Perl 6 client for the Telegram's Bot API.
<a href="https://github.com/GildedHonour/TelegramBot">https://github.com/GildedHonour/TelegramBot</a></p>
</li>
</ul>
</div>
</ul></div>
</div>

View file

@ -45,33 +45,33 @@ If you have questions, try our FAQ or check out this…">
<h1 id="dev_page_title">Hellobot</h1>
<div id="dev_page_content"><blockquote>
<p>This sample PHP bot demonstrates the basics of the <a href="/bots/api">Telegram Bot API</a>.<br>If you have questions, try our <a href="/bots/faq">FAQ</a> or check out <a href="/bots/samples">this page</a> for more examples.</p>
<p>This sample PHP bot demonstrates the basics of the <a href="/bots/api">Telegram Bot API</a>.
If you have questions, try our <a href="/bots/faq">FAQ</a> or check out <a href="/bots/samples">this page</a> for more examples.</p>
</blockquote>
<div><br></div>
<pre><code>&lt;?php
define(&#39;BOT_TOKEN&#39;, &#39;12345678:replace-me-with-real-token&#39;);
define(&#39;API_URL&#39;, &#39;https://api.telegram.org/bot&#39;.BOT_TOKEN.&#39;/&#39;);
define('BOT_TOKEN', '12345678:replace-me-with-real-token');
define('API_URL', 'https://api.telegram.org/bot'.BOT_TOKEN.'/');
function apiRequestWebhook($method, $parameters) {
if (!is_string($method)) {
error_log(&quot;Method name must be a string\n&quot;);
error_log("Method name must be a string\n");
return false;
}
if (!$parameters) {
$parameters = array();
} else if (!is_array($parameters)) {
error_log(&quot;Parameters must be an array\n&quot;);
error_log("Parameters must be an array\n");
return false;
}
$parameters[&quot;method&quot;] = $method;
$parameters["method"] = $method;
$payload = json_encode($parameters);
header(&#39;Content-Type: application/json&#39;);
header(&#39;Content-Length: &#39;.strlen($payload));
header('Content-Type: application/json');
header('Content-Length: '.strlen($payload));
echo $payload;
return true;
@ -83,7 +83,7 @@ function exec_curl_request($handle) {
if ($response === false) {
$errno = curl_errno($handle);
$error = curl_error($handle);
error_log(&quot;Curl returned error $errno: $error\n&quot;);
error_log("Curl returned error $errno: $error\n");
curl_close($handle);
return false;
}
@ -97,17 +97,17 @@ function exec_curl_request($handle) {
return false;
} else if ($http_code != 200) {
$response = json_decode($response, true);
error_log(&quot;Request has failed with error {$response[&#39;error_code&#39;]}: {$response[&#39;description&#39;]}\n&quot;);
error_log("Request has failed with error {$response['error_code']}: {$response['description']}\n");
if ($http_code == 401) {
throw new Exception(&#39;Invalid access token provided&#39;);
throw new Exception('Invalid access token provided');
}
return false;
} else {
$response = json_decode($response, true);
if (isset($response[&#39;description&#39;])) {
error_log(&quot;Request was successful: {$response[&#39;description&#39;]}\n&quot;);
if (isset($response['description'])) {
error_log("Request was successful: {$response['description']}\n");
}
$response = $response[&#39;result&#39;];
$response = $response['result'];
}
return $response;
@ -115,14 +115,14 @@ function exec_curl_request($handle) {
function apiRequest($method, $parameters) {
if (!is_string($method)) {
error_log(&quot;Method name must be a string\n&quot;);
error_log("Method name must be a string\n");
return false;
}
if (!$parameters) {
$parameters = array();
} else if (!is_array($parameters)) {
error_log(&quot;Parameters must be an array\n&quot;);
error_log("Parameters must be an array\n");
return false;
}
@ -132,7 +132,7 @@ function apiRequest($method, $parameters) {
$val = json_encode($val);
}
}
$url = API_URL.$method.&#39;?&#39;.http_build_query($parameters);
$url = API_URL.$method.'?'.http_build_query($parameters);
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
@ -144,18 +144,18 @@ function apiRequest($method, $parameters) {
function apiRequestJson($method, $parameters) {
if (!is_string($method)) {
error_log(&quot;Method name must be a string\n&quot;);
error_log("Method name must be a string\n");
return false;
}
if (!$parameters) {
$parameters = array();
} else if (!is_array($parameters)) {
error_log(&quot;Parameters must be an array\n&quot;);
error_log("Parameters must be an array\n");
return false;
}
$parameters[&quot;method&quot;] = $method;
$parameters["method"] = $method;
$handle = curl_init(API_URL);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
@ -163,47 +163,47 @@ function apiRequestJson($method, $parameters) {
curl_setopt($handle, CURLOPT_TIMEOUT, 60);
curl_setopt($handle, CURLOPT_POST, true);
curl_setopt($handle, CURLOPT_POSTFIELDS, json_encode($parameters));
curl_setopt($handle, CURLOPT_HTTPHEADER, array(&quot;Content-Type: application/json&quot;));
curl_setopt($handle, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
return exec_curl_request($handle);
}
function processMessage($message) {
// process incoming message
$message_id = $message[&#39;message_id&#39;];
$chat_id = $message[&#39;chat&#39;][&#39;id&#39;];
if (isset($message[&#39;text&#39;])) {
$message_id = $message['message_id'];
$chat_id = $message['chat']['id'];
if (isset($message['text'])) {
// incoming text message
$text = $message[&#39;text&#39;];
$text = $message['text'];
if (strpos($text, &quot;/start&quot;) === 0) {
apiRequestJson(&quot;sendMessage&quot;, array(&#39;chat_id&#39; =&gt; $chat_id, &quot;text&quot; =&gt; &#39;Hello&#39;, &#39;reply_markup&#39; =&gt; array(
&#39;keyboard&#39; =&gt; array(array(&#39;Hello&#39;, &#39;Hi&#39;)),
&#39;one_time_keyboard&#39; =&gt; true,
&#39;resize_keyboard&#39; =&gt; true)));
} else if ($text === &quot;Hello&quot; || $text === &quot;Hi&quot;) {
apiRequest(&quot;sendMessage&quot;, array(&#39;chat_id&#39; =&gt; $chat_id, &quot;text&quot; =&gt; &#39;Nice to meet you&#39;));
} else if (strpos($text, &quot;/stop&quot;) === 0) {
if (strpos($text, "/start") === 0) {
apiRequestJson("sendMessage", array('chat_id' =&gt; $chat_id, "text" =&gt; 'Hello', 'reply_markup' =&gt; array(
'keyboard' =&gt; array(array('Hello', 'Hi')),
'one_time_keyboard' =&gt; true,
'resize_keyboard' =&gt; true)));
} else if ($text === "Hello" || $text === "Hi") {
apiRequest("sendMessage", array('chat_id' =&gt; $chat_id, "text" =&gt; 'Nice to meet you'));
} else if (strpos($text, "/stop") === 0) {
// stop now
} else {
apiRequestWebhook(&quot;sendMessage&quot;, array(&#39;chat_id&#39; =&gt; $chat_id, &quot;reply_to_message_id&quot; =&gt; $message_id, &quot;text&quot; =&gt; &#39;Cool&#39;));
apiRequestWebhook("sendMessage", array('chat_id' =&gt; $chat_id, "reply_to_message_id" =&gt; $message_id, "text" =&gt; 'Cool'));
}
} else {
apiRequest(&quot;sendMessage&quot;, array(&#39;chat_id&#39; =&gt; $chat_id, &quot;text&quot; =&gt; &#39;I understand only text messages&#39;));
apiRequest("sendMessage", array('chat_id' =&gt; $chat_id, "text" =&gt; 'I understand only text messages'));
}
}
define(&#39;WEBHOOK_URL&#39;, &#39;https://my-site.example.com/secret-path-for-webhooks/&#39;);
define('WEBHOOK_URL', 'https://my-site.example.com/secret-path-for-webhooks/');
if (php_sapi_name() == &#39;cli&#39;) {
if (php_sapi_name() == 'cli') {
// if run from console, set or delete webhook
apiRequest(&#39;setWebhook&#39;, array(&#39;url&#39; =&gt; isset($argv[1]) &amp;&amp; $argv[1] == &#39;delete&#39; ? &#39;&#39; : WEBHOOK_URL));
apiRequest('setWebhook', array('url' =&gt; isset($argv[1]) &amp;&amp; $argv[1] == 'delete' ? '' : WEBHOOK_URL));
exit;
}
$content = file_get_contents(&quot;php://input&quot;);
$content = file_get_contents("php://input");
$update = json_decode($content, true);
if (!$update) {
@ -211,10 +211,9 @@ if (!$update) {
exit;
}
if (isset($update[&quot;message&quot;])) {
processMessage($update[&quot;message&quot;]);
}</code></pre>
</div>
if (isset($update["message"])) {
processMessage($update["message"]);
}</code></pre></div>
</div>

View file

@ -44,21 +44,19 @@
<div id="dev_page_content"><!-- scroll_nav -->
<p>This guide will walk you through everything you need to know to build your first <strong>Telegram Bot</strong>.<br>If you already know your way around some of the basic steps, you can jump directly to the part you&#39;re missing. Equivalent examples are available in <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.cs">C#</a>, <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.py">Python</a>, <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.go">Go</a> and <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/tree/main/Nodejs">TypeScript</a> .</p>
<p>This guide will walk you through everything you need to know to build your first <strong>Telegram Bot</strong>.
If you already know your way around some of the basic steps, you can jump directly to the part you're missing. Equivalent examples are available in <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.cs">C#</a>, <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.py">Python</a>, <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.go">Go</a> and <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/tree/main/Nodejs">TypeScript</a> .</p>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#getting-ready"><strong>Basic Tutorial</strong></a></li>
</ul>
<div id="dev_page_content">
<ul style="padding-left: 30px;">
<li style="margin-top: -5px"><a href="#getting-ready">Environment</a></li>
<li><a href="#first-run">First Run</a></li>
<li><a href="#echo-bot">Echo Bot</a></li>
</ul>
</div>
<ul>
<li><a href="#executing-commands"><strong>Advanced Tutorial</strong></a></li>
</ul>
@ -68,50 +66,51 @@
<li><a href="#navigation">Navigation</a></li>
<li><a href="#database">Database</a></li>
<li><a href="#hosting">Hosting</a></li>
</ul>
</div>
<ul>
<li><a href="#further-reading">Further Reading</a></li>
</ul>
<hr>
<h3><a class="anchor" name="introduction" href="#introduction"><i class="anchor-icon"></i></a>Introduction</h3>
<h3><a class="anchor" href="#introduction" id="introduction" name="introduction"><i class="anchor-icon"></i></a>Introduction</h3>
<p>At its core, you can think of the Telegram <a href="api">Bot API</a> as software that provides <a href="https://en.wikipedia.org/wiki/JSON">JSON-encoded</a> responses to your queries.</p>
<p>A bot, on the other hand, is essentially a routine, software or script that queries the API by means of an <a href="https://core.telegram.org/bots/api#making-requests">HTTPS request</a> and waits for a response. There are several types of <a href="api#available-methods">requests</a> you can make, as well as many different <a href="api#available-types">objects</a> that you can use and receive as responses.</p>
<p>Since <strong>your browser</strong> is capable of sending HTTPS requests, you can use it to quickly try out the API. After <a href="#obtain-your-bot-token">obtaining your token</a>, try pasting this string into your browser:</p>
<pre><code>https://api.telegram.org/bot&lt;YOUR_BOT_TOKEN&gt;/getMe</code></pre>
<p>In theory, you could interact with the API with <strong>basic requests</strong> like this, either via your browser or other tailor-made tools like <a href="https://curl.se/">cURL</a>. While this can work for simple requests like the example above, it&#39;s not practical for larger applications and doesn&#39;t scale well.<br>For that reason, this guide will show you how to use <a href="samples">libraries and frameworks</a>, along with some <strong>basic programming skills</strong>, to build a more robust and scalable project.</p>
<p>If you know how to code, you&#39;ll fly right through each step in no time and if you&#39;re just starting out, this guide will show you everything you need to learn.</p>
<p>In theory, you could interact with the API with <strong>basic requests</strong> like this, either via your browser or other tailor-made tools like <a href="https://curl.se/">cURL</a>. While this can work for simple requests like the example above, it's not practical for larger applications and doesn't scale well.
For that reason, this guide will show you how to use <a href="samples">libraries and frameworks</a>, along with some <strong>basic programming skills</strong>, to build a more robust and scalable project.</p>
<p>If you know how to code, you'll fly right through each step in no time and if you're just starting out, this guide will show you everything you need to learn.</p>
<blockquote>
<p>We will use <a href="https://en.wikipedia.org/wiki/Java_%28programming_language%29">Java</a> throughout this guide as it&#39;s one of the most popular programming languages, however, you can follow along with any language as all the steps are fundamentally the same.<br>Since Java is fully cross-platform, each code example will work with any operating system.<br>If you pick another language, equivalent examples are available in <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.cs">C#</a>, <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.py">Python</a>, <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.go">Go</a> and <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/tree/main/Nodejs">TypeScript</a> .</p>
<p>We will use <a href="https://en.wikipedia.org/wiki/Java_%28programming_language%29">Java</a> throughout this guide as it's one of the most popular programming languages, however, you can follow along with any language as all the steps are fundamentally the same.
Since Java is fully cross-platform, each code example will work with any operating system.
If you pick another language, equivalent examples are available in <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.cs">C#</a>, <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.py">Python</a>, <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.go">Go</a> and <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/tree/main/Nodejs">TypeScript</a> .</p>
</blockquote>
<h3><a class="anchor" name="getting-ready" href="#getting-ready"><i class="anchor-icon"></i></a>Getting Ready</h3>
<h3><a class="anchor" href="#getting-ready" id="getting-ready" name="getting-ready"><i class="anchor-icon"></i></a>Getting Ready</h3>
<p>First, we will briefly cover how to <strong>create your first project</strong>, obtain your <strong>API token</strong> and download all necessary <strong>dependencies and libraries</strong>.</p>
<p>For the purposes of this guide, a copy of the bot you will be creating is also live at <a href="https://t.me/tutorialbot">@TutorialBot</a> feel free to check it out along the way to see how your own implementation should look after each step.</p>
<h4><a class="anchor" name="obtain-your-bot-token" href="#obtain-your-bot-token"><i class="anchor-icon"></i></a>Obtain Your Bot Token</h4>
<h4><a class="anchor" href="#obtain-your-bot-token" id="obtain-your-bot-token" name="obtain-your-bot-token"><i class="anchor-icon"></i></a>Obtain Your Bot Token</h4>
<p>In this context, a <strong>token</strong> is a string that authenticates your bot (not your account) on the bot API. Each bot has a unique token which can also be revoked at any time via <a href="https://t.me/botfather">@BotFather</a>.</p>
<p>Obtaining a token is as simple as contacting <a href="https://t.me/botfather">@BotFather</a>, issuing the <code>/newbot</code> command and following the steps until you&#39;re given a new token. You can find a step-by-step guide <a href="features#creating-a-new-bot">here</a>.</p>
<p>Obtaining a token is as simple as contacting <a href="https://t.me/botfather">@BotFather</a>, issuing the <code>/newbot</code> command and following the steps until you're given a new token. You can find a step-by-step guide <a href="features#creating-a-new-bot">here</a>.</p>
<p>Your token will look something like this:</p>
<pre><code>4839574812:AAFD39kkdpWt3ywyRZergyOLMaJhac60qc</code></pre>
<blockquote>
<p>Make sure to save your token in a secure place, treat it like a password and <strong>don&#39;t share it with anyone</strong>.</p>
<p>Make sure to save your token in a secure place, treat it like a password and <strong>don't share it with anyone</strong>.</p>
</blockquote>
<h4><a class="anchor" name="download-an-ide" href="#download-an-ide"><i class="anchor-icon"></i></a>Download an IDE</h4>
<p>To program in Java you&#39;ll need an <a href="https://en.wikipedia.org/wiki/Integrated_development_environment">IDE</a> a special text editor that will let you write, compile and run your code.<br>In this tutorial, we&#39;ll use IntelliJ there are several free, open source alternatives like <a href="https://www.eclipse.org/ide/">Eclipse</a> or <a href="https://netbeans.apache.org/download/index.html">NetBeans</a> which work in the exact same way.</p>
<p>You will also need a <a href="https://en.wikipedia.org/wiki/Java_Development_Kit">JDK</a>, a software kit that allows your Java code to run.<br>Most IDEs don&#39;t include a JDK, so you should download a version compatible with your operating system separately. You can find a free, open source version <a href="https://adoptium.net/temurin/releases/">here</a>.</p>
<h4><a class="anchor" href="#download-an-ide" id="download-an-ide" name="download-an-ide"><i class="anchor-icon"></i></a>Download an IDE</h4>
<p>To program in Java you'll need an <a href="https://en.wikipedia.org/wiki/Integrated_development_environment">IDE</a> a special text editor that will let you write, compile and run your code.
In this tutorial, we'll use IntelliJ there are several free, open source alternatives like <a href="https://www.eclipse.org/ide/">Eclipse</a> or <a href="https://netbeans.apache.org/download/index.html">NetBeans</a> which work in the exact same way.</p>
<p>You will also need a <a href="https://en.wikipedia.org/wiki/Java_Development_Kit">JDK</a>, a software kit that allows your Java code to run.
Most IDEs don't include a JDK, so you should download a version compatible with your operating system separately. You can find a free, open source version <a href="https://adoptium.net/temurin/releases/">here</a>.</p>
<blockquote>
<p>If you use another language, the steps are identical. You will just have to download a different IDE and software development kit.</p>
</blockquote>
<h4><a class="anchor" name="pick-a-framework-or-library" href="#pick-a-framework-or-library"><i class="anchor-icon"></i></a>Pick a Framework or Library</h4>
<h4><a class="anchor" href="#pick-a-framework-or-library" id="pick-a-framework-or-library" name="pick-a-framework-or-library"><i class="anchor-icon"></i></a>Pick a Framework or Library</h4>
<p>You can think of a framework as software that handles all the low-level logic for you, including the API calls, and lets you focus on your bot-specific logic.</p>
<p>In this tutorial, we&#39;ll use <a href="https://github.com/rubenlagus/TelegramBots">TelegramBots</a>, but you can follow along with any equivalent implementation, since all the underlying methods are either similar or exactly the same.</p>
<p>In this tutorial, we'll use <a href="https://github.com/rubenlagus/TelegramBots">TelegramBots</a>, but you can follow along with any equivalent implementation, since all the underlying methods are either similar or exactly the same.</p>
<blockquote>
<p>You can find many frameworks, along with code examples, in <a href="samples">our dedicated list</a>.</p>
</blockquote>
<h4><a class="anchor" name="create-your-project" href="#create-your-project"><i class="anchor-icon"></i></a>Create Your Project</h4>
<h4><a class="anchor" href="#create-your-project" id="create-your-project" name="create-your-project"><i class="anchor-icon"></i></a>Create Your Project</h4>
<p>In IntelliJ, go to <code>File &gt; New &gt; Project</code>.</p>
<p>Fill in the fields accordingly:</p>
<ul>
@ -119,7 +118,7 @@
<li><strong>Location</strong> - Where to store your project. You can use the default value.</li>
<li><strong>Language</strong> - Java</li>
<li><strong>Build System</strong> - The framework that will handle your dependencies. Pick <em>Maven</em>.</li>
<li><strong>JDK</strong> - Pick whichever version you downloaded. We&#39;ll be using version <em>17</em>.</li>
<li><strong>JDK</strong> - Pick whichever version you downloaded. We'll be using version <em>17</em>.</li>
<li><strong>Add Sample Code</strong> - Leave this <strong>selected</strong>, it will generate some needed files for you.</li>
<li><strong>Advanced Settings &gt; GroupId</strong> - We suggest <em>tutorial</em>.</li>
<li><strong>Advanced Settings &gt; ArtifactId</strong> - You can use the default value.</li>
@ -134,12 +133,16 @@
│ └─ Main
└─ pom.xml</code></pre>
<blockquote>
<p>Other IDEs will follow a similar pattern. Your dependency management system will have a different name (or no name at all if it&#39;s built-in) depending on the language you chose.</p>
<p>Other IDEs will follow a similar pattern. Your dependency management system will have a different name (or no name at all if it's built-in) depending on the language you chose.</p>
</blockquote>
<p>If this looks scary, don&#39;t worry. We will only be using the <code>Main</code> file and the <code>pom.xml</code> file.<br>In fact, to check that everything is working so far, double click on <em>Main</em> and click on the small green arrow on the left of <em>public class Main</em>, then select the first option.<br>If you followed the steps correctly, <em>Hello world!</em> should appear in the console below.</p>
<h4><a class="anchor" name="add-framework-dependency" href="#add-framework-dependency"><i class="anchor-icon"></i></a>Add Framework Dependency</h4>
<p>We will now instruct the IDE to download and configure everything needed to work with the API.<br>This is very easy and happens automatically behind the scenes.</p>
<p>First, locate your <code>pom.xml</code> file on the left side of the screen.<br>Open it by double-clicking and simply add:</p>
<p>If this looks scary, don't worry. We will only be using the <code>Main</code> file and the <code>pom.xml</code> file.
In fact, to check that everything is working so far, double click on <em>Main</em> and click on the small green arrow on the left of <em>public class Main</em>, then select the first option.
If you followed the steps correctly, <em>Hello world!</em> should appear in the console below.</p>
<h4><a class="anchor" href="#add-framework-dependency" id="add-framework-dependency" name="add-framework-dependency"><i class="anchor-icon"></i></a>Add Framework Dependency</h4>
<p>We will now instruct the IDE to download and configure everything needed to work with the API.
This is very easy and happens automatically behind the scenes.</p>
<p>First, locate your <code>pom.xml</code> file on the left side of the screen.
Open it by double-clicking and simply add:</p>
<pre><code>&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.telegram&lt;/groupId&gt;
@ -148,14 +151,17 @@
&lt;/dependency&gt;
&lt;/dependencies&gt;</code></pre>
<p>right after the <code>&lt;/properties&gt;</code> tag.</p>
<p>When you&#39;re done, your <code>pom.xml</code> should look something like <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/pom.xml">this</a>.</p>
<h3><a class="anchor" name="start-coding" href="#start-coding"><i class="anchor-icon"></i></a>Start Coding</h3>
<p>We are ready to start coding. If you&#39;re a beginner, consider that being familiar with your language of choice will greatly help. With this tutorial, you&#39;ll be able to teach your bot basic behaviors, though more advanced features will require some coding experience.</p>
<h4><a class="anchor" name="creating-a-bot-class" href="#creating-a-bot-class"><i class="anchor-icon"></i></a>Creating a Bot Class</h4>
<p>If you&#39;re familiar with <a href="https://en.wikipedia.org/wiki/Object-oriented_programming">object-oriented programming</a>, you&#39;ll know what a class is.<br>If you&#39;ve never heard of it before, consider a class as a file where you write some logic.</p>
<p>When you're done, your <code>pom.xml</code> should look something like <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/pom.xml">this</a>.</p>
<h3><a class="anchor" href="#start-coding" id="start-coding" name="start-coding"><i class="anchor-icon"></i></a>Start Coding</h3>
<p>We are ready to start coding. If you're a beginner, consider that being familiar with your language of choice will greatly help. With this tutorial, you'll be able to teach your bot basic behaviors, though more advanced features will require some coding experience.</p>
<h4><a class="anchor" href="#creating-a-bot-class" id="creating-a-bot-class" name="creating-a-bot-class"><i class="anchor-icon"></i></a>Creating a Bot Class</h4>
<p>If you're familiar with <a href="https://en.wikipedia.org/wiki/Object-oriented_programming">object-oriented programming</a>, you'll know what a class is.
If you've never heard of it before, consider a class as a file where you write some logic.</p>
<p>To <strong>create the class</strong> that will contain the bot logic, right click on <em>tutorial</em> from the project tree on the left and select <em>New &gt; Java Class</em>. Name it <em>Bot</em> and hit enter.</p>
<p>Now we have to connect this class to the bot framework. In other words, we must make sure it extends <code>TelegramLongPollingBot</code>. To do that, just add <em>extends TelegramLongPollingBot</em> right after <em>Bot</em>.<br>A red line will appear it simply means we&#39;re missing some important methods.</p>
<p>To fix this, hover over the red line, click on <em>implement methods</em>, then hit OK.<br>Depending on the IDE, this option may be called <em>implement missing methods</em> or something similar.</p>
<p>Now we have to connect this class to the bot framework. In other words, we must make sure it extends <code>TelegramLongPollingBot</code>. To do that, just add <em>extends TelegramLongPollingBot</em> right after <em>Bot</em>.
A red line will appear it simply means we're missing some important methods.</p>
<p>To fix this, hover over the red line, click on <em>implement methods</em>, then hit OK.
Depending on the IDE, this option may be called <em>implement missing methods</em> or something similar.</p>
<p>You should end up with this if something went wrong, feel free to copy it from here and paste it in your class:</p>
<pre><code>package tutorial;
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
@ -178,53 +184,55 @@ public class Bot extends TelegramLongPollingBot {
}</code></pre>
<blockquote>
<p>If you get a red line under TelegramLongPollingBot, it means you didn&#39;t set up your pom.xml correctly. If this is the case, restart from <a href="#add-framework-dependency">here</a>.</p>
<p>If you get a red line under TelegramLongPollingBot, it means you didn't set up your pom.xml correctly. If this is the case, restart from <a href="#add-framework-dependency">here</a>.</p>
</blockquote>
<h4><a class="anchor" name="available-methods" href="#available-methods"><i class="anchor-icon"></i></a>Available Methods</h4>
<p>Let&#39;s look into these 3 methods one by one.</p>
<h4><a class="anchor" href="#available-methods" id="available-methods" name="available-methods"><i class="anchor-icon"></i></a>Available Methods</h4>
<p>Let's look into these 3 methods one by one.</p>
<ul>
<li><strong>getBotUsername</strong> - This method must be edited to always return your bot&#39;s username. You should replace the <em>null</em> return value with it.</li>
<li><strong>getBotUsername</strong> - This method must be edited to always return your bot's username. You should replace the <em>null</em> return value with it.</li>
<li><strong>getBotToken</strong> - This method will be used by the framework to retrieve your bot token. You should replace the <em>null</em> return value with the token.</li>
<li><strong>onUpdateReceived</strong> - This is the most important method. It will be called automatically whenever a new Update is available. Let&#39;s add a <code>System.out.println(update);</code> call in there to quickly show what we are getting.</li>
<li><strong>onUpdateReceived</strong> - This is the most important method. It will be called automatically whenever a new Update is available. Let's add a <code>System.out.println(update);</code> call in there to quickly show what we are getting.</li>
</ul>
<p>After you&#39;ve replaced all the strings, you should end up with this:</p>
<p>After you've replaced all the strings, you should end up with this:</p>
<pre><code>@Override
public String getBotUsername() {
return &quot;TutorialBot&quot;;
return "TutorialBot";
}
@Override
public String getBotToken() {
return &quot;4839574812:AAFD39kkdpWt3ywyRZergyOLMaJhac60qc&quot;;
return "4839574812:AAFD39kkdpWt3ywyRZergyOLMaJhac60qc";
}
@Override
public void onUpdateReceived(Update update) {
System.out.println(update);
}</code></pre>
<p>At this point, the bot is configured and ready to go time to register it on the API and start processing updates.</p>
<p>At this point, the bot is configured and ready to go  time to register it on the API and start processing updates.</p>
<blockquote>
<p>In the future, you should consider storing your token in a dedicated settings file or in <a href="https://en.wikipedia.org/wiki/Environment_variable">environment variables</a>. Keeping it in the code is fine for the scope of this tutorial, however, it&#39;s not very versatile and is generally considered bad practice. </p>
<p>In the future, you should consider storing your token in a dedicated settings file or in <a href="https://en.wikipedia.org/wiki/Environment_variable">environment variables</a>. Keeping it in the code is fine for the scope of this tutorial, however, it's not very versatile and is generally considered bad practice. </p>
</blockquote>
<h4><a class="anchor" name="registering-the-bot" href="#registering-the-bot"><i class="anchor-icon"></i></a>Registering the Bot</h4>
<h4><a class="anchor" href="#registering-the-bot" id="registering-the-bot" name="registering-the-bot"><i class="anchor-icon"></i></a>Registering the Bot</h4>
<p>To <strong>register the bot</strong> on the API, simply add a couple of lines <strong>in the main method</strong> that will launch the application. If you named your class <code>Bot</code>, this is what your main method should look like:</p>
<pre><code>public static void main(String[] args) throws TelegramApiException {
TelegramBotsApi botsApi = new TelegramBotsApi(DefaultBotSession.class);
botsApi.registerBot(new Bot());
}</code></pre>
<blockquote>
<p>You can place this method in any class. Since we have an auto-generated <code>main</code> method in the Main class, we&#39;ll be using that one for this tutorial.</p>
<p>You can place this method in any class. Since we have an auto-generated <code>main</code> method in the Main class, we'll be using that one for this tutorial.</p>
</blockquote>
<h3><a class="anchor" name="first-run" href="#first-run"><i class="anchor-icon"></i></a>First Run</h3>
<p>It&#39;s time to <strong>run your bot</strong> for the first time.<br>Hit the green arrow to the left of <code>public static void main</code> and select the first option.</p>
<p><em>And then there was nothing</em>. Yes, a bit anticlimactic.<br>This is because your bot <strong>has nothing to print</strong> there are <strong>no new updates</strong> because nobody messaged it yet.</p>
<p>If you try messaging the bot on Telegram, you&#39;ll then see <strong>new updates</strong> pop up in the console. At this point, you have your very own Telegram Bot quite the achievement. Now, on to making it a bit more intelligent.</p>
<h3><a class="anchor" href="#first-run" id="first-run" name="first-run"><i class="anchor-icon"></i></a>First Run</h3>
<p>It's time to <strong>run your bot</strong> for the first time.
Hit the green arrow to the left of <code>public static void main</code> and select the first option.</p>
<p><em>And then there was nothing</em>. Yes, a bit anticlimactic.
This is because your bot <strong>has nothing to print</strong> there are <strong>no new updates</strong> because nobody messaged it yet.</p>
<p>If you try messaging the bot on Telegram, you'll then see <strong>new updates</strong> pop up in the console. At this point, you have your very own Telegram Bot quite the achievement. Now, on to making it a bit more intelligent.</p>
<blockquote>
<p>If nothing pops up, make sure you messaged the right bot and that the token you pasted in the code is correct.</p>
</blockquote>
<h3><a class="anchor" name="receiving-messages" href="#receiving-messages"><i class="anchor-icon"></i></a>Receiving Messages</h3>
<p>Every time someone sends a <strong>private message</strong> to your bot, your <code>onUpdateReceived</code> method will be called automatically and you&#39;ll be able to handle the <code>update</code> parameter, which contains the <strong>message</strong>, along with a great deal of other info which you can see detailed <a href="api#update">here</a>.</p>
<p>Let&#39;s focus on two values for now:</p>
<h3><a class="anchor" href="#receiving-messages" id="receiving-messages" name="receiving-messages"><i class="anchor-icon"></i></a>Receiving Messages</h3>
<p>Every time someone sends a <strong>private message</strong> to your bot, your <code>onUpdateReceived</code> method will be called automatically and you'll be able to handle the <code>update</code> parameter, which contains the <strong>message</strong>, along with a great deal of other info which you can see detailed <a href="api#update">here</a>.</p>
<p>Let's focus on two values for now:</p>
<ul>
<li><strong>The user</strong> - Who sent the message. Access it via <code>update.getMessage().getFrom()</code>.</li>
<li><strong>The message</strong> - What was sent. Access it via <code>update.getMessage()</code>.</li>
@ -235,21 +243,21 @@ public void onUpdateReceived(Update update) {
var msg = update.getMessage();
var user = msg.getFrom();
System.out.println(user.getFirstName() + &quot; wrote &quot; + msg.getText());
System.out.println(user.getFirstName() + " wrote " + msg.getText());
}</code></pre>
<p>This is just a basic example you can now play around with all the methods to see everything you can pull out of these objects. You can try <code>getUsername</code>, <code>getLanguageCode</code>, and dozens more.</p>
<p>Knowing how to receive, process and print <strong>incoming messages</strong>, now it&#39;s time to learn how to <strong>answer them</strong>.</p>
<p>Knowing how to receive, process and print <strong>incoming messages</strong>, now it's time to learn how to <strong>answer them</strong>.</p>
<blockquote>
<p>Remember to stop and re-launch your bot after each change to the code.</p>
</blockquote>
<h3><a class="anchor" name="sending-messages" href="#sending-messages"><i class="anchor-icon"></i></a>Sending Messages</h3>
<h3><a class="anchor" href="#sending-messages" id="sending-messages" name="sending-messages"><i class="anchor-icon"></i></a>Sending Messages</h3>
<p>To send a private text message, you generally need <strong>three things</strong>:</p>
<ul>
<li>The user <strong>must</strong> have contacted your bot first. (Unless the user sent a join request to a group where your bot is an admin, but that&#39;s a more advanced scenario).</li>
<li>The user <strong>must</strong> have contacted your bot first. (Unless the user sent a join request to a group where your bot is an admin, but that's a more advanced scenario).</li>
<li>You <strong>must</strong> have previously saved the <strong>User ID</strong> (<code>user.getId()</code>)</li>
<li>A <code>String</code> object containing the message text, 1-4096 characters.</li>
</ul>
<p>With that out of the way, let&#39;s create a <strong>new method</strong> to send the first message:</p>
<p>With that out of the way, let's create a <strong>new method</strong> to send the first message:</p>
<pre><code>public void sendText(Long who, String what){
SendMessage sm = SendMessage.builder()
.chatId(who.toString()) //Who are we sending a message to
@ -260,20 +268,23 @@ public void onUpdateReceived(Update update) {
throw new RuntimeException(e); //Any error will be printed here
}
}</code></pre>
<p>And proceed to run this in the <code>main</code> method, right after registering the bot.<br>For this example, we&#39;ll assume your User ID is <code>1234</code>.</p>
<p>And proceed to run this in the <code>main</code> method, right after registering the bot.
For this example, we'll assume your User ID is <code>1234</code>.</p>
<pre><code>public static void main(String[] args) throws TelegramApiException {
TelegramBotsApi botsApi = new TelegramBotsApi(DefaultBotSession.class);
Bot bot = new Bot(); //We moved this line out of the register method, to access it later
botsApi.registerBot(bot);
bot.sendText(1234L, &quot;Hello World!&quot;); //The L just turns the Integer into a Long
bot.sendText(1234L, "Hello World!"); //The L just turns the Integer into a Long
}</code></pre>
<p>If you did everything correctly, your bot should text you <em>Hello World!</em> every time you launch your code. Sending messages to groups or channels assuming you have the relevant permissions is as simple as replacing <code>1234</code> with the ID of the respective chat.</p>
<blockquote>
<p>Try experimenting with other types of messages, like SendPhoto, SendSticker, SendDice…<br>A full list is available starting <a href="https://core.telegram.org/bots/api#sendmessage">here</a>.</p>
<p>Try experimenting with other types of messages, like SendPhoto, SendSticker, SendDice...
A full list is available starting <a href="https://core.telegram.org/bots/api#sendmessage">here</a>.</p>
</blockquote>
<h3><a class="anchor" name="echo-bot" href="#echo-bot"><i class="anchor-icon"></i></a>Echo Bot</h3>
<p>Let&#39;s practice everything we tried so far by coding an <strong>Echo Bot</strong>.<br>Its functionality will be rather simple: every text message it receives will be sent right back to the user.</p>
<h4><a class="anchor" name="copying-text" href="#copying-text"><i class="anchor-icon"></i></a>Copying Text</h4>
<h3><a class="anchor" href="#echo-bot" id="echo-bot" name="echo-bot"><i class="anchor-icon"></i></a>Echo Bot</h3>
<p>Let's practice everything we tried so far by coding an <strong>Echo Bot</strong>.
Its functionality will be rather simple: every text message it receives will be sent right back to the user.</p>
<h4><a class="anchor" href="#copying-text" id="copying-text" name="copying-text"><i class="anchor-icon"></i></a>Copying Text</h4>
<p>The most intuitive way of coding this is saving the User ID and calling <code>sendText</code> right after each update.</p>
<p>In other words:</p>
<pre><code>@Override
@ -285,11 +296,12 @@ public void onUpdateReceived(Update update) {
sendText(id, msg.getText());
}</code></pre>
<p>This works for text but can be extended to stickers, media and files.</p>
<h4><a class="anchor" name="copying-everything" href="#copying-everything"><i class="anchor-icon"></i></a>Copying Everything</h4>
<p>There are more specific functions that can be used to copy messages and send them back.<br>Let&#39;s build a method to do just that:</p>
<h4><a class="anchor" href="#copying-everything" id="copying-everything" name="copying-everything"><i class="anchor-icon"></i></a>Copying Everything</h4>
<p>There are more specific functions that can be used to copy messages and send them back.
Let's build a method to do just that:</p>
<pre><code>public void copyMessage(Long who, Integer msgId){
CopyMessage cm = CopyMessage.builder()
.fromChatId(who.toString()) //We copy from the user
.fromChatId(who.toString()) //We copy from the user
.chatId(who.toString()) //And send it back to him
.messageId(msgId) //Specifying what message
.build();
@ -303,25 +315,28 @@ public void onUpdateReceived(Update update) {
<blockquote>
<p>This tutorial assumes that updates always contain messages for the sake of simplicity. This may not always be true be sure to implement all the proper checks in your code to handle every type of update with the appropriate methods.</p>
</blockquote>
<h3><a class="anchor" name="executing-commands" href="#executing-commands"><i class="anchor-icon"></i></a>Executing Commands</h3>
<p>To learn what a command is and how it works, we recommend reading this <a href="features#commands">dedicated summary</a>.<br>In this guide, we&#39;ll focus on the technical side of things.</p>
<h4><a class="anchor" name="creating-your-command" href="#creating-your-command"><i class="anchor-icon"></i></a>Creating Your Command</h4>
<p>Begin by opening <a href="https://t.me/botfather">@BotFather</a>.<br>Type <code>/mybots</code> &gt; <em>Your_Bot_Name</em> &gt; Edit Bot &gt; Edit Commands.</p>
<p>Now send a new command, followed by a brief description.<br>For the purpose of this tutorial, we&#39;ll implement two simple commands:</p>
<pre><code>scream - Speak, I&#39;ll scream right back
<h3><a class="anchor" href="#executing-commands" id="executing-commands" name="executing-commands"><i class="anchor-icon"></i></a>Executing Commands</h3>
<p>To learn what a command is and how it works, we recommend reading this <a href="features#commands">dedicated summary</a>.
In this guide, we'll focus on the technical side of things.</p>
<h4><a class="anchor" href="#creating-your-command" id="creating-your-command" name="creating-your-command"><i class="anchor-icon"></i></a>Creating Your Command</h4>
<p>Begin by opening <a href="https://t.me/botfather">@BotFather</a>.
Type <code>/mybots</code> &gt; <em>Your_Bot_Name</em> &gt; Edit Bot &gt; Edit Commands.</p>
<p>Now send a new command, followed by a brief description.
For the purpose of this tutorial, we'll implement two simple commands:</p>
<pre><code>scream - Speak, I'll scream right back
whisper - Shhhhhhh</code></pre>
<h4><a class="anchor" name="command-logic" href="#command-logic"><i class="anchor-icon"></i></a>Command Logic</h4>
<p>We want the <strong>Echo Bot</strong> to reply in uppercase when it&#39;s in <strong>scream mode</strong> and normally otherwise.</p>
<p>First, let&#39;s <strong>create a variable</strong> to store the current mode.</p>
<h4><a class="anchor" href="#command-logic" id="command-logic" name="command-logic"><i class="anchor-icon"></i></a>Command Logic</h4>
<p>We want the <strong>Echo Bot</strong> to reply in uppercase when it's in <strong>scream mode</strong> and normally otherwise.</p>
<p>First, let's <strong>create a variable</strong> to store the current mode.</p>
<pre><code>public class Bot extends TelegramLongPollingBot {
private boolean screaming = false;
[...]
}</code></pre>
<p>Then, let&#39;s change some logic to <strong>account for this mode</strong>.</p>
<p>Then, let's change some logic to <strong>account for this mode</strong>.</p>
<pre><code>public void onUpdateReceived(Update update) {
[...] //Same variables as the previous versions
[...] //Same variables as the previous versions
if(screaming) //If we are screaming
scream(id, update.getMessage()); //Call a custom method
else
@ -332,26 +347,28 @@ private void scream(Long id, Message msg) {
if(msg.hasText())
sendText(id, msg.getText().toUpperCase());
else
copyMessage(id, msg.getMessageId()); //We can&#39;t really scream a sticker
copyMessage(id, msg.getMessageId()); //We can't really scream a sticker
}</code></pre>
<p>Finally, let&#39;s add a couple more lines to the <code>onUpdateReceived</code> method to process each command before replying.</p>
<p>Finally, let's add a couple more lines to the <code>onUpdateReceived</code> method to process each command before replying.</p>
<pre><code>if(msg.isCommand()){
if(msg.getText().equals(&quot;/scream&quot;)) //If the command was /scream, we switch gears
if(msg.getText().equals("/scream")) //If the command was /scream, we switch gears
screaming = true;
else if (msg.getText().equals(&quot;/whisper&quot;)) //Otherwise, we return to normal
else if (msg.getText().equals("/whisper")) //Otherwise, we return to normal
screaming = false;
return; //We don&#39;t want to echo commands, so we exit
return; //We don't want to echo commands, so we exit
}</code></pre>
<p>As you can see, it checks if the message <strong>is a command</strong>. If it is, the bot enters <strong>scream mode</strong>.<br>In the update method, we check <strong>which mode we are in</strong> and either copy the message or convert it to upper case before <strong>sending it back</strong>.</p>
<p>And that&#39;s it. Now the bot can <strong>execute commands</strong> and change its behavior accordingly.</p>
<p>Naturally, this simplified logic will change the bot&#39;s behavior for <strong>everyone</strong> not just the person who sent the command. This can be fun for this tutorial but <strong>won&#39;t work in a production environment</strong> consider using a Map, dictionary or equivalent data structure to assign settings for individual users.</p>
<p>As you can see, it checks if the message <strong>is a command</strong>. If it is, the bot enters <strong>scream mode</strong>.
In the update method, we check <strong>which mode we are in</strong> and either copy the message or convert it to upper case before <strong>sending it back</strong>.</p>
<p>And that's it. Now the bot can <strong>execute commands</strong> and change its behavior accordingly.</p>
<p>Naturally, this simplified logic will change the bot's behavior for <strong>everyone</strong> not just the person who sent the command. This can be fun for this tutorial but <strong>won't work in a production environment</strong> consider using a Map, dictionary or equivalent data structure to assign settings for individual users.</p>
<blockquote>
<p>Remember to always implement a few basic <a href="features#global-commands">global commands</a>.<br>You can practice by implementing a simple feedback to the <code>/start</code> command, which we intentionally left out.</p>
<p>Remember to always implement a few basic <a href="features#global-commands">global commands</a>.
You can practice by implementing a simple feedback to the <code>/start</code> command, which we intentionally left out.</p>
</blockquote>
<h3><a class="anchor" name="buttons-and-keyboards" href="#buttons-and-keyboards"><i class="anchor-icon"></i></a>Buttons and Keyboards</h3>
<h3><a class="anchor" href="#buttons-and-keyboards" id="buttons-and-keyboards" name="buttons-and-keyboards"><i class="anchor-icon"></i></a>Buttons and Keyboards</h3>
<p>To streamline and simplify user interaction with your bot, you can replace many text-based exchanges with handy buttons. These buttons can perform a wide variety of actions and can be customized for each user.</p>
<h4><a class="anchor" name="button-types" href="#button-types"><i class="anchor-icon"></i></a>Button Types</h4>
<h4><a class="anchor" href="#button-types" id="button-types" name="button-types"><i class="anchor-icon"></i></a>Button Types</h4>
<p>There are two main types of buttons:</p>
<ul>
<li><strong>Reply Buttons</strong> - used to provide a list of predefined text <a href="features#keyboards">reply options</a>.</li>
@ -359,27 +376,27 @@ private void scream(Long id, Message msg) {
</ul>
<p>Using these buttons is as easy as attaching a <code>ReplyKeyboardMarkup</code> or an <code>InlineKeyboardMarkup</code> to your <code>SendMessage</code> object.</p>
<p>This guide will focus on <strong>inline buttons</strong> since they only require a few extra lines of code.</p>
<h4><a class="anchor" name="creating-buttons" href="#creating-buttons"><i class="anchor-icon"></i></a>Creating Buttons</h4>
<p>First of all, let&#39;s create some buttons.</p>
<h4><a class="anchor" href="#creating-buttons" id="creating-buttons" name="creating-buttons"><i class="anchor-icon"></i></a>Creating Buttons</h4>
<p>First of all, let's create some buttons.</p>
<pre><code> var next = InlineKeyboardButton.builder()
.text(&quot;Next&quot;).callbackData(&quot;next&quot;)
.text("Next").callbackData("next")
.build();
var back = InlineKeyboardButton.builder()
.text(&quot;Back&quot;).callbackData(&quot;back&quot;)
.text("Back").callbackData("back")
.build();
var url = InlineKeyboardButton.builder()
.text(&quot;Tutorial&quot;)
.url(&quot;https://core.telegram.org/bots/api&quot;)
.text("Tutorial")
.url("https://core.telegram.org/bots/api")
.build();</code></pre>
<p>Let&#39;s go back through the fields we specified:</p>
<p>Let's go back through the fields we specified:</p>
<ul>
<li><strong>Text</strong> - This is what the user will see, the text that appears on the button</li>
<li><strong>Callback Data</strong> - This will be sent back to the code instance as part of a new <code>Update</code>, so we can quickly identify what button was clicked.</li>
<li><strong>Url</strong> - A button that specifies a URL doesn&#39;t specify callbackdata since its behavior is predefined it will open the given link when tapped.</li>
<li><strong>Url</strong> - A button that specifies a URL doesn't specify callbackdata since its behavior is predefined it will open the given link when tapped.</li>
</ul>
<h4><a class="anchor" name="creating-keyboards" href="#creating-keyboards"><i class="anchor-icon"></i></a>Creating Keyboards</h4>
<h4><a class="anchor" href="#creating-keyboards" id="creating-keyboards" name="creating-keyboards"><i class="anchor-icon"></i></a>Creating Keyboards</h4>
<p>The <strong>buttons</strong> we created can be assembled into two <strong>keyboards</strong>, which will then be used to navigate back and forth between two <strong>sample menus</strong>.</p>
<p>First, <strong>add two fields</strong> to store the necessary keyboards.</p>
<pre><code>private boolean screaming = false;
@ -396,13 +413,13 @@ keyboardM2 = InlineKeyboardMarkup.builder()
.keyboardRow(List.of(url))
.build();</code></pre>
<blockquote>
<p>You can place this code wherever you prefer, the important thing is making sure that keyboard variables are accessible from the method call that will send the new menu. If you&#39;re confused by this concept and don&#39;t know where to put them, just paste them above the command processing flow.</p>
<p>You can place this code wherever you prefer, the important thing is making sure that keyboard variables are accessible from the method call that will send the new menu. If you're confused by this concept and don't know where to put them, just paste them above the command processing flow.</p>
</blockquote>
<h4><a class="anchor" name="sending-keyboards" href="#sending-keyboards"><i class="anchor-icon"></i></a>Sending Keyboards</h4>
<h4><a class="anchor" href="#sending-keyboards" id="sending-keyboards" name="sending-keyboards"><i class="anchor-icon"></i></a>Sending Keyboards</h4>
<p>Sending a keyboard only requires specifying a reply markup for the message.</p>
<pre><code>public void sendMenu(Long who, String txt, InlineKeyboardMarkup kb){
SendMessage sm = SendMessage.builder().chatId(who.toString())
.parseMode(&quot;HTML&quot;).text(txt)
.parseMode("HTML").text(txt)
.replyMarkup(kb).build();
try {
@ -412,30 +429,33 @@ keyboardM2 = InlineKeyboardMarkup.builder()
}
}</code></pre>
<blockquote>
<p>You may have noticed that we also added a new parameter, <code>HTML</code>.<br>This is called a <a href="api#formatting-options">formatting option</a> and will allow us to use HTML tags and add formatting to the text later on.</p>
<p>You may have noticed that we also added a new parameter, <code>HTML</code>.
This is called a <a href="api#formatting-options">formatting option</a> and will allow us to use HTML tags and add formatting to the text later on.</p>
</blockquote>
<h4><a class="anchor" name="menu-trigger" href="#menu-trigger"><i class="anchor-icon"></i></a>Menu Trigger</h4>
<p>We could send a new menu for each new user, but for simplicity let&#39;s add a new command that will spawn a menu. We can achieve this by adding a new <strong>else clause</strong> to the previous command flow.</p>
<h4><a class="anchor" href="#menu-trigger" id="menu-trigger" name="menu-trigger"><i class="anchor-icon"></i></a>Menu Trigger</h4>
<p>We could send a new menu for each new user, but for simplicity let's add a new command that will spawn a menu. We can achieve this by adding a new <strong>else clause</strong> to the previous command flow.</p>
<pre><code> var txt = msg.getText();
if(msg.isCommand()) {
if (txt.equals(&quot;/scream&quot;))
if (txt.equals("/scream"))
screaming = true;
else if (txt.equals(&quot;/whisper&quot;))
else if (txt.equals("/whisper"))
screaming = false;
else if (txt.equals(&quot;/menu&quot;))
sendMenu(id, &quot;&lt;b&gt;Menu 1&lt;/b&gt;&quot;, keyboardM1);
else if (txt.equals("/menu"))
sendMenu(id, "&lt;b&gt;Menu 1&lt;/b&gt;", keyboardM1);
return;
}</code></pre>
<p>Try sending <code>/menu</code> to your bot now. If you did everything correctly, you should see a brand new menu pop up.</p>
<blockquote>
<p>In a production environment, commands should be handled with an appropriate design pattern that isolates them into different executor classes modular and separated from the main logic.</p>
</blockquote>
<h3><a class="anchor" name="navigation" href="#navigation"><i class="anchor-icon"></i></a>Navigation</h3>
<h3><a class="anchor" href="#navigation" id="navigation" name="navigation"><i class="anchor-icon"></i></a>Navigation</h3>
<p>When building complex bots, navigation is essential. Your users must be able to move seamlessly from one menu to the next. </p>
<p>In this example, we want the <code>Next</code> button to lead the user to the second menu.<br>The <code>Back</code> button will send us back.<br>To do that, we will start processing incoming <code>CallbackQueries</code>, which are the results we get after the user taps on a button.</p>
<p>In this example, we want the <code>Next</code> button to lead the user to the second menu.
The <code>Back</code> button will send us back.
To do that, we will start processing incoming <code>CallbackQueries</code>, which are the results we get after the user taps on a button.</p>
<p>A <code>CallbackQuery</code> is essentially composed of three main parameters:</p>
<ul>
<li><strong>queryId</strong> - Needed to close the query. You <strong>must always</strong> close new queries after processing them if you don&#39;t, a loading symbol will keep showing on the user&#39;s side on top of each button.</li>
<li><strong>queryId</strong> - Needed to close the query. You <strong>must always</strong> close new queries after processing them if you don't, a loading symbol will keep showing on the user's side on top of each button.</li>
<li><strong>data</strong> - This identifies which button was pressed.</li>
<li><strong>from</strong> - The user who pressed the button.</li>
</ul>
@ -445,16 +465,16 @@ keyboardM2 = InlineKeyboardMarkup.builder()
EditMessageText newTxt = EditMessageText.builder()
.chatId(id.toString())
.messageId(msgId).text(&quot;&quot;).build();
.messageId(msgId).text("").build();
EditMessageReplyMarkup newKb = EditMessageReplyMarkup.builder()
.chatId(id.toString()).messageId(msgId).build();
if(data.equals(&quot;next&quot;)) {
newTxt.setText(&quot;MENU 2&quot;);
if(data.equals("next")) {
newTxt.setText("MENU 2");
newKb.setReplyMarkup(keyboardM2);
} else if(data.equals(&quot;back&quot;)) {
newTxt.setText(&quot;MENU 1&quot;);
} else if(data.equals("back")) {
newTxt.setText("MENU 1");
newKb.setReplyMarkup(keyboardM1);
}
@ -465,21 +485,29 @@ keyboardM2 = InlineKeyboardMarkup.builder()
execute(newTxt);
execute(newKb);
}</code></pre>
<p>With this handler, whenever a button is tapped, your bot will automatically navigate between inline menus.<br>Expanding on this concept allows for endless combinations of navigable submenus, settings and dynamic pages.</p>
<h3><a class="anchor" name="database" href="#database"><i class="anchor-icon"></i></a>Database</h3>
<p>With this handler, whenever a button is tapped, your bot will automatically navigate between inline menus.
Expanding on this concept allows for endless combinations of navigable submenus, settings and dynamic pages.</p>
<h3><a class="anchor" href="#database" id="database" name="database"><i class="anchor-icon"></i></a>Database</h3>
<p>Telegram <strong>does not</strong> host an update database for you once you process and consume an update, it will no longer be available. This means that features like user lists, message lists, current user inline menu, settings, etc. <strong>have to be implemented and maintained</strong> by bot developers.</p>
<p>If your bot needs one of these features and you want to get started on <strong>data persistence</strong>, we recommend that you look into <a href="https://en.wikipedia.org/wiki/Serialization">serialization</a> practices and libraries for your language of choice, as well as available databases.</p>
<p>Implementing a database is out of scope for this guide, however, several guides are available online for simple embedded <strong>open source</strong> software solutions like <a href="https://www.sqlite.org/index.html">SQLite</a>, <a href="https://hsqldb.org/">HyperSQL</a>, <a href="https://db.apache.org/derby/">Derby</a> and many more.</p>
<blockquote>
<p>Your language of choice will also influence which databases are available and supported the list above assumes you followed this Java tutorial.</p>
</blockquote>
<h3><a class="anchor" name="hosting" href="#hosting"><i class="anchor-icon"></i></a>Hosting</h3>
<p>So far, your bot has been running on your <strong>local machine</strong> your PC. While this may be good for <strong>developing</strong>, <strong>testing</strong> and <strong>debugging</strong>, it is not ideal for a production environment.<br>You&#39;ll want your bot to be available and responsive at all times, but your computer might not always be online.</p>
<h3><a class="anchor" href="#hosting" id="hosting" name="hosting"><i class="anchor-icon"></i></a>Hosting</h3>
<p>So far, your bot has been running on your <strong>local machine</strong> your PC. While this may be good for <strong>developing</strong>, <strong>testing</strong> and <strong>debugging</strong>, it is not ideal for a production environment.
You'll want your bot to be available and responsive at all times, but your computer might not always be online.</p>
<p>This can be done in four steps:</p>
<ul>
<li><p><strong>Package your code</strong><br>Making your bot <strong>easy to move</strong> and <strong>runnable</strong> outside of an IDE is essential to <strong>host it elsewhere</strong>.<br>If you followed this tutorial, this <a href="https://www.jetbrains.com/help/idea/compiling-applications.html#run_packaged_jar">standard guide</a> will work for you. If you didn&#39;t, look into <strong>export or packaging guides</strong> for your IDE and language of choice procedures may vary but the end result is the same.</p>
<li>
<p><strong>Package your code</strong>
Making your bot <strong>easy to move</strong> and <strong>runnable</strong> outside of an IDE is essential to <strong>host it elsewhere</strong>.
If you followed this tutorial, this <a href="https://www.jetbrains.com/help/idea/compiling-applications.html#run_packaged_jar">standard guide</a> will work for you. If you didn't, look into <strong>export or packaging guides</strong> for your IDE and language of choice procedures may vary but the end result is the same.</p>
</li>
<li><p><strong>Purchase a VPS or equivalent service</strong><br>A server is essentially a machine that is always online and running, without you having to worry about anything. To host your bot, you can opt for a <a href="https://en.wikipedia.org/wiki/Virtual_private_server">VPS</a> which serves this purpose and can be rented from several different providers.<br>Another option would be to purchase a network-capable <a href="https://en.wikipedia.org/wiki/Microcontroller">microcontroller</a>, which come in all different specs and sizes depending on your needs.</p>
<li>
<p><strong>Purchase a VPS or equivalent service</strong>
A server is essentially a machine that is always online and running, without you having to worry about anything. To host your bot, you can opt for a <a href="https://en.wikipedia.org/wiki/Virtual_private_server">VPS</a> which serves this purpose and can be rented from several different providers.
Another option would be to purchase a network-capable <a href="https://en.wikipedia.org/wiki/Microcontroller">microcontroller</a>, which come in all different specs and sizes depending on your needs.</p>
</li>
</ul>
<blockquote>
@ -488,7 +516,8 @@ keyboardM2 = InlineKeyboardMarkup.builder()
<ul>
<li><strong>Upload your executable/package</strong></li>
</ul>
<p>Once you have a working <a href="https://en.wikipedia.org/wiki/Secure_Shell">ssh</a> connection between your machine and your new server, you should upload your executable and all associated files.<br>We will assume the runnable jar <code>TutorialBot.jar</code> and its database <code>dbase.db</code> are currently in the <code>/TBot</code> folder.</p>
<p>Once you have a working <a href="https://en.wikipedia.org/wiki/Secure_Shell">ssh</a> connection between your machine and your new server, you should upload your executable and all associated files.
We will assume the runnable jar <code>TutorialBot.jar</code> and its database <code>dbase.db</code> are currently in the <code>/TBot</code> folder.</p>
<pre><code>$ scp -r /TBot/ username@server_ip:/bots/TBotRemote/</code></pre>
<ul>
<li><strong>Run your application</strong></li>
@ -496,23 +525,23 @@ keyboardM2 = InlineKeyboardMarkup.builder()
<p>Depending on which language you chose, you might have to configure your server environment differently. If you chose Java, you just need to install a compatible JDK.</p>
<pre><code>$ apt install openjdk-17-jre
$ java -version</code></pre>
<p>If you did everything correctly, you should see a Java version as the output, along with a few other values. This means you&#39;re ready to run your application.</p>
<p>If you did everything correctly, you should see a Java version as the output, along with a few other values. This means you're ready to run your application.</p>
<p>Now, to run the executable:</p>
<pre><code>$ cd /bots/TBotRemote/
$ java -jar TutorialBot.jar</code></pre>
<p>Your bot is now online and users can interact with it at any time.</p>
<blockquote>
<p>To streamline and modularize this process, you could employ a specialized <a href="https://www.docker.com/resources/what-container/">docker container</a> or equivalent service.<br>If you followed along in one of the equivalent examples (<a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.cs">C#</a>, <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.py">Python</a>, <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.go">Go</a> and <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/tree/main/Nodejs">TypeScript</a>) you can find a detailed set of instructions to export and run your code <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/tree/main/">here</a>.</p>
<p>To streamline and modularize this process, you could employ a specialized <a href="https://www.docker.com/resources/what-container/">docker container</a> or equivalent service.
If you followed along in one of the equivalent examples (<a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.cs">C#</a>, <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.py">Python</a>, <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/blob/main/TutorialBot.go">Go</a> and <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/tree/main/Nodejs">TypeScript</a>) you can find a detailed set of instructions to export and run your code <a href="https://gitlab.com/Athamaxy/telegram-bot-tutorial/-/tree/main/">here</a>.</p>
</blockquote>
<h3><a class="anchor" name="further-reading" href="#further-reading"><i class="anchor-icon"></i></a>Further Reading</h3>
<h3><a class="anchor" href="#further-reading" id="further-reading" name="further-reading"><i class="anchor-icon"></i></a>Further Reading</h3>
<p>If you got this far, you might be interested in these additional guides and docs:</p>
<ul>
<li><a href="/bots">General Bot Platform Overview</a></li>
<li><a href="/bots/features">Detailed List of Bot Features</a></li>
<li><a href="/bots/api">Full API Reference</a></li>
</ul>
<p>If you encounter any issues while following this guide, you can contact us on Telegram at <a href="https://t.me/botsupport">@BotSupport</a>.</p>
</div>
<p>If you encounter any issues while following this guide, you can contact us on Telegram at <a href="https://t.me/botsupport">@BotSupport</a>.</p></div>
</div>

File diff suppressed because it is too large Load diff

View file

@ -77,6 +77,11 @@
<td>Flags, see <a href="/mtproto/TL-combinators#conditional-fields">TL conditional fields</a></td>
</tr>
<tr>
<td><strong>broadcasts_only</strong></td>
<td style="text-align: center;"><a href="/mtproto/TL-combinators#conditional-fields">flags</a>.1?<a href="/constructor/true">true</a></td>
<td> </td>
</tr>
<tr>
<td><strong>folder_id</strong></td>
<td style="text-align: center;"><a href="/mtproto/TL-combinators#conditional-fields">flags</a>.0?<a href="/type/int">int</a></td>
<td><a href="/api/folders#peer-folders">Peer folder ID, for more info click here</a></td>

View file

@ -53,9 +53,9 @@
<h5><a class="anchor" href="#1-client-sends-query-to-server" id="1-client-sends-query-to-server" name="1-client-sends-query-to-server"><i class="anchor-icon"></i></a>1) Client sends query to server</h5>
<!-- start req_pq_multi -->
<p>Sent payload (excluding transport headers/trailers):</p>
<pre><code>0000 | 00 00 00 00 00 00 00 00 18 1D 06 00 89 0C EB 65
0010 | 14 00 00 00 F1 8E 7E BE 6C 5D 01 83 C0 9B 3D 4C
0020 | 65 0C 7A 02 E4 D8 BD F8</code></pre>
<pre><code>0000 | 00 00 00 00 00 00 00 00 98 A9 0D 00 DC 75 64 66
0010 | 14 00 00 00 F1 8E 7E BE 0B FE 9D 6B 3D 0A 6B E1
0020 | 37 49 41 41 F3 9D 2D 23</code></pre>
<p>Payload (de)serialization:</p>
<pre><code>req_pq_multi#be7e8ef1 nonce:int128 = ResPQ;</code></pre>
<table class="table">
@ -77,7 +77,7 @@
<tr>
<td>message_id</td>
<td>8, 8</td>
<td><code>181D0600890CEB65</code></td>
<td><code>98A90D00DC756466</code></td>
<td>Message ID generated as specified <a href="/mtproto/description#message-identifier-msg-id">here »</a> (unixtime() &lt;&lt; 32) + (N*4)</td>
</tr>
<tr>
@ -95,7 +95,7 @@
<tr>
<td>nonce</td>
<td>24, 16</td>
<td><code>6C5D0183C09B3D4C650C7A02E4D8BDF8</code></td>
<td><code>0BFE9D6B3D0A6BE137494141F39D2D23</code></td>
<td>Random number</td>
</tr>
</tbody>
@ -104,11 +104,11 @@
<h5><a class="anchor" href="#2-server-sends-response-of-the-form" id="2-server-sends-response-of-the-form" name="2-server-sends-response-of-the-form"><i class="anchor-icon"></i></a>2) Server sends response of the form</h5>
<!-- start resPQ -->
<p>Received payload (excluding transport headers/trailers):</p>
<pre><code>0000 | 00 00 00 00 00 00 00 00 01 B4 BF 94 89 0C EB 65
0010 | B0 00 00 00 63 24 16 05 6C 5D 01 83 C0 9B 3D 4C
0020 | 65 0C 7A 02 E4 D8 BD F8 F3 9F 03 F1 56 5D 6D 00
0030 | 28 51 C6 FC AC 8A CD 0D 08 22 0D C2 2C A4 0D 5C
0040 | A7 00 00 00 15 C4 B5 1C 03 00 00 00 A5 B7 F7 09
<pre><code>0000 | 00 00 00 00 00 00 00 00 01 B8 84 BC DC 75 64 66
0010 | C4 00 00 00 63 24 16 05 0B FE 9D 6B 3D 0A 6B E1
0020 | 37 49 41 41 F3 9D 2D 23 87 BB 22 11 92 61 99 C9
0030 | 9D 85 2A 84 B6 1A 13 B5 08 18 23 ED E7 98 25 4E
0040 | 0F 00 00 00 15 C4 B5 1C 03 00 00 00 A5 B7 F7 09
0050 | 35 5F C3 0B 21 6B E8 6C 02 2B B4 C3 85 FD 64 DE
0060 | 85 1D 9D D0</code></pre>
<p>Payload (de)serialization:</p>
@ -132,13 +132,13 @@
<tr>
<td>message_id</td>
<td>8, 8</td>
<td><code>01B4BF94890CEB65</code></td>
<td><code>01B884BCDC756466</code></td>
<td>Message ID generated as specified <a href="/mtproto/description#message-identifier-msg-id">here »</a> (unixtime() &lt;&lt; 32) + (N*4)</td>
</tr>
<tr>
<td>message_length</td>
<td>16, 4</td>
<td><code>B0000000</code> (176 in decimal)</td>
<td><code>C4000000</code> (196 in decimal)</td>
<td>Message body length</td>
</tr>
<tr>
@ -150,19 +150,19 @@
<tr>
<td>nonce</td>
<td>24, 16</td>
<td><code>6C5D0183C09B3D4C650C7A02E4D8BDF8</code></td>
<td><code>0BFE9D6B3D0A6BE137494141F39D2D23</code></td>
<td>Value generated by client in Step 1</td>
</tr>
<tr>
<td>server_nonce</td>
<td>40, 16</td>
<td><code>F39F03F1565D6D002851C6FCAC8ACD0D</code></td>
<td><code>87BB2211926199C99D852A84B61A13B5</code></td>
<td>Server-generated random number</td>
</tr>
<tr>
<td>pq</td>
<td>56, 12</td>
<td><code>08220DC22CA40D5CA7000000</code><br>TL byte deserialization <br>=&gt; bigendian conversion to decimal<br>=&gt; 2453830868973477031</td>
<td><code>081823EDE798254E0F000000</code><br>TL byte deserialization <br>=&gt; bigendian conversion to decimal<br>=&gt; 1739495460040953359</td>
<td>Single-byte prefix denoting length, an 8-byte string, and three bytes of padding</td>
</tr>
<tr>
@ -208,22 +208,22 @@
<h4><a class="anchor" href="#proof-of-work" id="proof-of-work" name="proof-of-work"><i class="anchor-icon"></i></a>Proof of work</h4>
<h5><a class="anchor" href="#3-client-decomposes-pq-into-prime-factors-such-that-p-lt-q" id="3-client-decomposes-pq-into-prime-factors-such-that-p-lt-q" name="3-client-decomposes-pq-into-prime-factors-such-that-p-lt-q"><i class="anchor-icon"></i></a>3) Client decomposes pq into prime factors such that p &lt; q.</h5>
<!-- start pq -->
<pre><code>pq = 2453830868973477031</code></pre>
<p>Decompose into 2 prime cofactors <code>p &lt; q</code>: <code>2453830868973477031 = 1343866633 * 1825948207</code></p>
<pre><code>p = 1343866633
q = 1825948207</code></pre>
<pre><code>pq = 1739495460040953359</code></pre>
<p>Decompose into 2 prime cofactors <code>p &lt; q</code>: <code>1739495460040953359 = 1111714897 * 1564695647</code></p>
<pre><code>p = 1111714897
q = 1564695647</code></pre>
<!-- end pq -->
<h4><a class="anchor" href="#presenting-proof-of-work-server-authentication" id="presenting-proof-of-work-server-authentication" name="presenting-proof-of-work-server-authentication"><i class="anchor-icon"></i></a>Presenting proof of work; Server authentication</h4>
<h5><a class="anchor" href="#4-encrypted-data-payload-generation" id="4-encrypted-data-payload-generation" name="4-encrypted-data-payload-generation"><i class="anchor-icon"></i></a>4) <code>encrypted_data</code> payload generation</h5>
<p>First of all, generate an <code>encrypted_data</code> payload as follows:</p>
<!-- start p_q_inner_data_dc -->
<p>Generated payload (excluding transport headers/trailers):</p>
<pre><code>0000 | 95 5F F5 A9 08 22 0D C2 2C A4 0D 5C A7 00 00 00
0010 | 04 50 19 C7 09 00 00 00 04 6C D5 C2 2F 00 00 00
0020 | 6C 5D 01 83 C0 9B 3D 4C 65 0C 7A 02 E4 D8 BD F8
0030 | F3 9F 03 F1 56 5D 6D 00 28 51 C6 FC AC 8A CD 0D
0040 | 2D 1F 97 69 1A D9 39 B4 94 C3 01 53 E1 9A A2 61
0050 | FB 11 10 FF 51 D2 5D 56 06 34 70 CA D9 8B 7D 1D
<pre><code>0000 | 95 5F F5 A9 08 18 23 ED E7 98 25 4E 0F 00 00 00
0010 | 04 42 43 6C 51 00 00 00 04 5D 43 5C 5F 00 00 00
0020 | 0B FE 9D 6B 3D 0A 6B E1 37 49 41 41 F3 9D 2D 23
0030 | 87 BB 22 11 92 61 99 C9 9D 85 2A 84 B6 1A 13 B5
0040 | 1C FE F7 D6 C8 51 80 C8 C3 DE D0 6B 26 7A 3A 0F
0050 | A9 B9 CF DC D5 BE 69 A6 A4 5E 37 D7 8B B8 41 56
0060 | 02 00 00 00</code></pre>
<p>Payload (de)serialization:</p>
<pre><code>p_q_inner_data_dc#a9f55f95 pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 dc:int = P_Q_inner_data;</code></pre>
@ -246,37 +246,37 @@ q = 1825948207</code></pre>
<tr>
<td>pq</td>
<td>4, 12</td>
<td><code>08220DC22CA40D5CA7000000</code><br>TL byte deserialization <br>=&gt; bigendian conversion to decimal<br>=&gt; 2453830868973477031</td>
<td><code>081823EDE798254E0F000000</code><br>TL byte deserialization <br>=&gt; bigendian conversion to decimal<br>=&gt; 1739495460040953359</td>
<td>Single-byte prefix denoting length, 8-byte string, and three bytes of padding</td>
</tr>
<tr>
<td>p</td>
<td>16, 8</td>
<td><code>045019C709000000</code><br>TL byte deserialization <br>=&gt; bigendian conversion to decimal<br>=&gt; 1343866633</td>
<td><code>0442436C51000000</code><br>TL byte deserialization <br>=&gt; bigendian conversion to decimal<br>=&gt; 1111714897</td>
<td>First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding</td>
</tr>
<tr>
<td>q</td>
<td>24, 8</td>
<td><code>046CD5C22F000000</code><br>TL byte deserialization <br>=&gt; bigendian conversion to decimal<br>=&gt; 1825948207</td>
<td><code>045D435C5F000000</code><br>TL byte deserialization <br>=&gt; bigendian conversion to decimal<br>=&gt; 1564695647</td>
<td>Second prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding</td>
</tr>
<tr>
<td>nonce</td>
<td>32, 16</td>
<td><code>6C5D0183C09B3D4C650C7A02E4D8BDF8</code></td>
<td><code>0BFE9D6B3D0A6BE137494141F39D2D23</code></td>
<td>Value generated by client in Step 1</td>
</tr>
<tr>
<td>server_nonce</td>
<td>48, 16</td>
<td><code>F39F03F1565D6D002851C6FCAC8ACD0D</code></td>
<td><code>87BB2211926199C99D852A84B61A13B5</code></td>
<td>Value received from server in Step 2</td>
</tr>
<tr>
<td>new_nonce</td>
<td>64, 32</td>
<td><code>2D1F97691AD939B494C30153E19AA261</code> <code>FB1110FF51D25D56063470CAD98B7D1D</code></td>
<td><code>1CFEF7D6C85180C8C3DED06B267A3A0F</code> <code>A9B9CFDCD5BE69A6A45E37D78BB84156</code></td>
<td>Client-generated random number</td>
</tr>
<tr>
@ -291,39 +291,39 @@ q = 1825948207</code></pre>
<p>The serialization of <em>P_Q_inner_data</em> produces <strong>data</strong>, which is used to generate <strong>encrypted_data</strong> as specified in <a href="/mtproto/auth_key">step 4.1</a>.<br>
These are the inputs to the algorithm specified in <a href="/mtproto/auth_key">step 4.1</a>:</p>
<!-- start p_q_inner_data_input -->
<pre><code>data = 955FF5A908220DC22CA40D5CA7000000045019C709000000046CD5C22F0000006C5D0183C09B3D4C650C7A02E4D8BDF8F39F03F1565D6D002851C6FCAC8ACD0D2D1F97691AD939B494C30153E19AA261FB1110FF51D25D56063470CAD98B7D1D02000000
random_padding_bytes = 4347A0F58FFA3C09FD35129D919DE5F28204BB1881B4DFD74F34E8D37F1B2B174B8080BDD94DB34876588957B1A27EB6A4772FF102569EF27B2E578F3EF0B687B25025A6F22D214797C028053702E7E327622A09BBFCE461F08E17AB</code></pre>
<pre><code>data = 955FF5A9081823EDE798254E0F0000000442436C51000000045D435C5F0000000BFE9D6B3D0A6BE137494141F39D2D2387BB2211926199C99D852A84B61A13B51CFEF7D6C85180C8C3DED06B267A3A0FA9B9CFDCD5BE69A6A45E37D78BB8415602000000
random_padding_bytes = CB46E2B5099183E41329B59FA3AC47F5232A17ADF9468856A4D7E9E3EEBA86653C7C1718EEC42649F117A83BBDF08F86E5311C29BC6283DD959E811E8E12751D6555C6927909900A7EC5C76F6707B63328D7D7ABAF72D856552B2E5C</code></pre>
<!-- end p_q_inner_data_input -->
<p>And this is the output:</p>
<!-- start p_q_inner_data_output -->
<pre><code>encrypted_data = E29CDFF0C375F9AA616187FCD985672C5DC7854BEAF2DCF07B1BDF7E51DA27CB15CD1F5A8DA506C6C877334ED1A148B09D5322FA4F066B502996B4D483D56A2DA40F253CC65F3EE4B0D3D778CB716DA0E710D57EB9FF959A4D3D6A557329CC0E01F74127B7F6B99DAC0E63E44538CF6F3B7FD8B076DC13DDECF55CE62B33F7928B3301870860690F1E15541BBE3CE1F2995D91C6CA352BAB250D06B6FA0F2A095B07009379108B37FFF3BBF01E119449BADDADF175411DA2E5E33C849BE410DCAEF6CE325A33B9F602E064EE47EDDD1C083E17CF8E0465EA838C98535CFC5043C754BF3B1954DED2140FB28FA523C54727F1DEE9544673EB1B82ABB53F567A60</code></pre>
<pre><code>encrypted_data = BBCA9A81C65B7E667BE2BF1E08E2E309917FFBDD1CE12E5CE53E8EFC0CA2B8BC2873483BD582E4C5A47A7C722D05F8205A8870D77124F6599A16395E6BF90F247CC589895D3A9410F69C0948EA60F1EF0556ADD2E04F7A111DE288EBD830041EC796545D6BD71A8281BD62A897AAAC7E07C20B2724A6436ECA74EF06160C0D125314AA592135AFFB8096B70B3D1F2E51CA57760E6A99CFFD7E12ACEFFE7C128534555A324968616C86BF944B3D69891A042C8F16D955A82F9B5CFBBFEBD5F8AF02BFA9B3D14ACDBE69B0177F82FB60DFE13DD22BC3CA0BB586046D2E64261981219542B05C97F67E37B23D5D9BDDEE35AAB3C6209C2720249AAD5B101891C9F0</code></pre>
<!-- end p_q_inner_data_output -->
<p>The length of the final string is 256 bytes.</p>
<h5><a class="anchor" href="#5-send-req-dh-params-query-with-generated-encrypted-data" id="5-send-req-dh-params-query-with-generated-encrypted-data" name="5-send-req-dh-params-query-with-generated-encrypted-data"><i class="anchor-icon"></i></a>5) Send req_DH_params query with generated <code>encrypted_data</code></h5>
<!-- start req_DH_params -->
<p>Sent payload (excluding transport headers/trailers):</p>
<pre><code>0000 | 00 00 00 00 00 00 00 00 F4 F2 09 00 89 0C EB 65
0010 | 40 01 00 00 BE E4 12 D7 6C 5D 01 83 C0 9B 3D 4C
0020 | 65 0C 7A 02 E4 D8 BD F8 F3 9F 03 F1 56 5D 6D 00
0030 | 28 51 C6 FC AC 8A CD 0D 04 50 19 C7 09 00 00 00
0040 | 04 6C D5 C2 2F 00 00 00 85 FD 64 DE 85 1D 9D D0
0050 | FE 00 01 00 E2 9C DF F0 C3 75 F9 AA 61 61 87 FC
0060 | D9 85 67 2C 5D C7 85 4B EA F2 DC F0 7B 1B DF 7E
0070 | 51 DA 27 CB 15 CD 1F 5A 8D A5 06 C6 C8 77 33 4E
0080 | D1 A1 48 B0 9D 53 22 FA 4F 06 6B 50 29 96 B4 D4
0090 | 83 D5 6A 2D A4 0F 25 3C C6 5F 3E E4 B0 D3 D7 78
00A0 | CB 71 6D A0 E7 10 D5 7E B9 FF 95 9A 4D 3D 6A 55
00B0 | 73 29 CC 0E 01 F7 41 27 B7 F6 B9 9D AC 0E 63 E4
00C0 | 45 38 CF 6F 3B 7F D8 B0 76 DC 13 DD EC F5 5C E6
00D0 | 2B 33 F7 92 8B 33 01 87 08 60 69 0F 1E 15 54 1B
00E0 | BE 3C E1 F2 99 5D 91 C6 CA 35 2B AB 25 0D 06 B6
00F0 | FA 0F 2A 09 5B 07 00 93 79 10 8B 37 FF F3 BB F0
0100 | 1E 11 94 49 BA DD AD F1 75 41 1D A2 E5 E3 3C 84
0110 | 9B E4 10 DC AE F6 CE 32 5A 33 B9 F6 02 E0 64 EE
0120 | 47 ED DD 1C 08 3E 17 CF 8E 04 65 EA 83 8C 98 53
0130 | 5C FC 50 43 C7 54 BF 3B 19 54 DE D2 14 0F B2 8F
0140 | A5 23 C5 47 27 F1 DE E9 54 46 73 EB 1B 82 AB B5
0150 | 3F 56 7A 60</code></pre>
<pre><code>0000 | 00 00 00 00 00 00 00 00 9C A9 0D 00 DC 75 64 66
0010 | 40 01 00 00 BE E4 12 D7 0B FE 9D 6B 3D 0A 6B E1
0020 | 37 49 41 41 F3 9D 2D 23 87 BB 22 11 92 61 99 C9
0030 | 9D 85 2A 84 B6 1A 13 B5 04 42 43 6C 51 00 00 00
0040 | 04 5D 43 5C 5F 00 00 00 85 FD 64 DE 85 1D 9D D0
0050 | FE 00 01 00 BB CA 9A 81 C6 5B 7E 66 7B E2 BF 1E
0060 | 08 E2 E3 09 91 7F FB DD 1C E1 2E 5C E5 3E 8E FC
0070 | 0C A2 B8 BC 28 73 48 3B D5 82 E4 C5 A4 7A 7C 72
0080 | 2D 05 F8 20 5A 88 70 D7 71 24 F6 59 9A 16 39 5E
0090 | 6B F9 0F 24 7C C5 89 89 5D 3A 94 10 F6 9C 09 48
00A0 | EA 60 F1 EF 05 56 AD D2 E0 4F 7A 11 1D E2 88 EB
00B0 | D8 30 04 1E C7 96 54 5D 6B D7 1A 82 81 BD 62 A8
00C0 | 97 AA AC 7E 07 C2 0B 27 24 A6 43 6E CA 74 EF 06
00D0 | 16 0C 0D 12 53 14 AA 59 21 35 AF FB 80 96 B7 0B
00E0 | 3D 1F 2E 51 CA 57 76 0E 6A 99 CF FD 7E 12 AC EF
00F0 | FE 7C 12 85 34 55 5A 32 49 68 61 6C 86 BF 94 4B
0100 | 3D 69 89 1A 04 2C 8F 16 D9 55 A8 2F 9B 5C FB BF
0110 | EB D5 F8 AF 02 BF A9 B3 D1 4A CD BE 69 B0 17 7F
0120 | 82 FB 60 DF E1 3D D2 2B C3 CA 0B B5 86 04 6D 2E
0130 | 64 26 19 81 21 95 42 B0 5C 97 F6 7E 37 B2 3D 5D
0140 | 9B DD EE 35 AA B3 C6 20 9C 27 20 24 9A AD 5B 10
0150 | 18 91 C9 F0</code></pre>
<p>Payload (de)serialization:</p>
<pre><code>req_DH_params#d712e4be nonce:int128 server_nonce:int128 p:string q:string public_key_fingerprint:long encrypted_data:string = Server_DH_Params;</code></pre>
<table class="table">
@ -345,7 +345,7 @@ random_padding_bytes = 4347A0F58FFA3C09FD35129D919DE5F28204BB1881B4DFD74F34E8D37
<tr>
<td>message_id</td>
<td>8, 8</td>
<td><code>F4F20900890CEB65</code></td>
<td><code>9CA90D00DC756466</code></td>
<td>Message ID generated as specified <a href="/mtproto/description#message-identifier-msg-id">here »</a> (unixtime() &lt;&lt; 32) + (N*4)</td>
</tr>
<tr>
@ -363,25 +363,25 @@ random_padding_bytes = 4347A0F58FFA3C09FD35129D919DE5F28204BB1881B4DFD74F34E8D37
<tr>
<td>nonce</td>
<td>24, 16</td>
<td><code>6C5D0183C09B3D4C650C7A02E4D8BDF8</code></td>
<td><code>0BFE9D6B3D0A6BE137494141F39D2D23</code></td>
<td>Value generated by client in Step 1</td>
</tr>
<tr>
<td>server_nonce</td>
<td>40, 16</td>
<td><code>F39F03F1565D6D002851C6FCAC8ACD0D</code></td>
<td><code>87BB2211926199C99D852A84B61A13B5</code></td>
<td>Value received from server in Step 2</td>
</tr>
<tr>
<td>p</td>
<td>56, 8</td>
<td><code>045019C709000000</code><br>TL byte deserialization <br>=&gt; bigendian conversion to decimal<br>=&gt; 1343866633</td>
<td><code>0442436C51000000</code><br>TL byte deserialization <br>=&gt; bigendian conversion to decimal<br>=&gt; 1111714897</td>
<td>First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding</td>
</tr>
<tr>
<td>q</td>
<td>64, 8</td>
<td><code>046CD5C22F000000</code><br>TL byte deserialization <br>=&gt; bigendian conversion to decimal<br>=&gt; 1825948207</td>
<td><code>045D435C5F000000</code><br>TL byte deserialization <br>=&gt; bigendian conversion to decimal<br>=&gt; 1564695647</td>
<td>Second prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding</td>
</tr>
<tr>
@ -393,7 +393,7 @@ random_padding_bytes = 4347A0F58FFA3C09FD35129D919DE5F28204BB1881B4DFD74F34E8D37
<tr>
<td>encrypted_data</td>
<td>80, 260</td>
<td><code>FE000100E29CDFF0C375F9AA616187FC</code> <code>D985672C5DC7854BEAF2DCF07B1BDF7E</code> <code>51DA27CB15CD1F5A8DA506C6C877334E</code> <code>D1A148B09D5322FA4F066B502996B4D4</code> <code>83D56A2DA40F253CC65F3EE4B0D3D778</code> <code>CB716DA0E710D57EB9FF959A4D3D6A55</code> <code>7329CC0E01F74127B7F6B99DAC0E63E4</code> <code>4538CF6F3B7FD8B076DC13DDECF55CE6</code> <code>2B33F7928B3301870860690F1E15541B</code> <code>BE3CE1F2995D91C6CA352BAB250D06B6</code> <code>FA0F2A095B07009379108B37FFF3BBF0</code> <code>1E119449BADDADF175411DA2E5E33C84</code> <code>9BE410DCAEF6CE325A33B9F602E064EE</code> <code>47EDDD1C083E17CF8E0465EA838C9853</code> <code>5CFC5043C754BF3B1954DED2140FB28F</code> <code>A523C54727F1DEE9544673EB1B82ABB5</code><br> <code>3F567A60</code></td>
<td><code>FE000100BBCA9A81C65B7E667BE2BF1E</code> <code>08E2E309917FFBDD1CE12E5CE53E8EFC</code> <code>0CA2B8BC2873483BD582E4C5A47A7C72</code> <code>2D05F8205A8870D77124F6599A16395E</code> <code>6BF90F247CC589895D3A9410F69C0948</code> <code>EA60F1EF0556ADD2E04F7A111DE288EB</code> <code>D830041EC796545D6BD71A8281BD62A8</code> <code>97AAAC7E07C20B2724A6436ECA74EF06</code> <code>160C0D125314AA592135AFFB8096B70B</code> <code>3D1F2E51CA57760E6A99CFFD7E12ACEF</code> <code>FE7C128534555A324968616C86BF944B</code> <code>3D69891A042C8F16D955A82F9B5CFBBF</code> <code>EBD5F8AF02BFA9B3D14ACDBE69B0177F</code> <code>82FB60DFE13DD22BC3CA0BB586046D2E</code> <code>64261981219542B05C97F67E37B23D5D</code> <code>9BDDEE35AAB3C6209C2720249AAD5B10</code><br> <code>1891C9F0</code></td>
<td>Value generated above</td>
</tr>
</tbody>
@ -402,47 +402,47 @@ random_padding_bytes = 4347A0F58FFA3C09FD35129D919DE5F28204BB1881B4DFD74F34E8D37
<h5><a class="anchor" href="#6-server-responds-with" id="6-server-responds-with" name="6-server-responds-with"><i class="anchor-icon"></i></a>6) Server responds with:</h5>
<!-- start server_DH_params_ok -->
<p>Received payload (excluding transport headers/trailers):</p>
<pre><code>0000 | 00 00 00 00 00 00 00 00 01 64 78 42 8A 0C EB 65
0010 | DC 02 00 00 5C 07 E8 D0 6C 5D 01 83 C0 9B 3D 4C
0020 | 65 0C 7A 02 E4 D8 BD F8 F3 9F 03 F1 56 5D 6D 00
0030 | 28 51 C6 FC AC 8A CD 0D FE 50 02 00 FC 5B 35 4A
0040 | 74 FF 07 4F 47 36 CD 0C 00 15 17 6F 2F 85 8D 3A
0050 | 2D FC 31 74 2A 4B DC 67 CD 55 FF 1E 0B 1C E7 5D
0060 | 39 2A F5 7B D8 C4 A0 B9 00 8C 9B 8D C2 20 B8 67
0070 | 53 0C CB C2 BB 5F 74 91 09 3C 3B CD 51 F2 7E 71
0080 | AD E0 10 ED 22 A4 F6 16 71 D3 5E AB 57 61 8C 0C
0090 | 1A 35 99 8F C1 4A 91 7C CD 6C 63 C8 3E A3 36 EA
00A0 | 9C 40 16 48 7D 9A 18 DB 4F DC 65 0C A8 DF F7 F3
00B0 | FC 8B 78 D5 0E DA FE 30 F2 01 52 AA 2F EB 0C 14
00C0 | C1 20 38 8E 0B 28 EC 8E 3D 4B 49 05 A7 96 64 FE
00D0 | 99 7C 8E 4A 43 52 32 9A E0 0B 62 84 F7 38 2C DA
00E0 | 1B 19 E5 36 EE 68 6E 90 3D 82 13 B5 D4 CD 8E 2B
00F0 | E0 2B 3E 98 83 92 A7 3B 7B F8 FB 7B 02 82 EA 85
0100 | 3F 5C EF 28 2C 8F 1B DB 7D 46 4C DC 09 54 63 B7
0110 | A7 E9 87 87 94 26 B3 E6 6E 8A 39 EE 8A 0A D5 94
0120 | AC 87 AD 5E 4A 38 E4 07 FE D3 E7 0E B5 30 0A AE
0130 | 05 87 4E 0E 81 F2 24 E2 F5 7C 37 0F 48 48 78 90
0140 | 5F 7A 04 35 EC 4F F0 6E 47 72 23 16 3D AA E0 7F
0150 | AE C5 FB 3B 64 48 AD 9C 38 90 FB E0 1A 95 7F 8C
0160 | DD 37 83 CD AF 78 AC 60 68 4E F4 C9 A0 7D E2 21
0170 | 1F F9 C1 86 5F 74 5E 4A 4A 2C 56 74 7E 49 63 47
0180 | 35 64 A1 98 40 C1 82 66 9C FE 84 63 A0 37 6E 3F
0190 | B5 FB B0 47 DA 0B 87 C1 88 A5 B3 26 33 CF 55 EE
01A0 | 1B D9 35 B5 6B F8 0E 44 77 B1 84 6A 9C B2 79 50
01B0 | 3E 6C 44 EB 00 91 B0 EC A1 08 0E ED 47 44 CF 55
01C0 | 89 B8 92 6C 5C 8B 6E 78 B2 14 B7 46 83 4E B0 7C
01D0 | DB 37 B3 F3 C3 7D E7 BD F7 28 65 5B 4C 6D 32 E7
01E0 | D9 F8 A2 84 05 62 29 9D 10 32 2C 29 D8 03 13 EA
01F0 | 17 A2 8B 0C 86 85 A4 26 F7 0E FE BA 8D 57 EE D1
0200 | B7 E6 0D 11 17 BF A3 F9 49 B1 10 CB E2 08 54 C2
0210 | F1 AB 4C 37 A0 91 60 08 AB 20 63 B6 75 E2 32 97
0220 | 9B D9 94 83 69 57 A1 86 1B CD 63 CE 8A C2 D1 EE
0230 | 99 97 DC 48 F5 4F 68 F4 C1 83 85 D4 47 A9 42 83
0240 | 91 A2 C7 77 13 FE 4C C7 5B 92 1C 7C 2E BA A2 80
0250 | 16 C5 40 12 8B 17 9B F5 63 27 90 27 3E F1 64 7F
0260 | AA 5B 98 27 DD 89 C2 9D 61 ED DD A7 68 E8 AF C4
0270 | F0 4F BA 8B 02 5E F4 B4 45 1C 71 DB 63 26 52 92
0280 | 84 27 BE 66 B6 F1 FE 0A 88 94 3B 2F</code></pre>
<pre><code>0000 | 00 00 00 00 00 00 00 00 01 94 2B 8B DD 75 64 66
0010 | F0 02 00 00 5C 07 E8 D0 0B FE 9D 6B 3D 0A 6B E1
0020 | 37 49 41 41 F3 9D 2D 23 87 BB 22 11 92 61 99 C9
0030 | 9D 85 2A 84 B6 1A 13 B5 FE 50 02 00 75 88 A5 C1
0040 | F6 9A 41 C8 E5 C2 75 90 DA C1 77 4F 99 B8 6F C6
0050 | 98 2C E5 6C 37 D3 23 C2 42 C6 18 93 83 B4 E4 C0
0060 | 64 89 DA AE 50 5B 82 F0 ED 29 26 3C 66 1F 68 41
0070 | 7A A9 9D 74 FB E5 E7 35 58 86 4D D1 BB A8 D3 33
0080 | 52 1D 1B 94 97 23 4D 28 2A 99 18 83 79 7A 6C BC
0090 | DB 1A E8 3B 95 DA 4B 8F 3D 26 61 25 36 C6 EE EA
00A0 | 8A 51 E5 28 83 33 01 2F 66 96 DE 39 98 28 24 3B
00B0 | 5E D3 BA C4 B7 54 73 A4 62 94 8D F1 26 7D 72 8A
00C0 | 96 05 83 F3 EA 51 79 3F 3B 0F BE 96 CC 14 46 8D
00D0 | 4A 55 7A 65 56 51 6B C2 E8 6A CC 40 AF F7 64 FE
00E0 | 6F 6C 0D 0C 97 82 D2 8C 5B 60 27 53 0E 9F 74 11
00F0 | E5 C4 32 91 D4 07 6D 9F 90 33 3E 75 3C F8 2E 18
0100 | 70 76 7A 50 16 CA 5C D3 4E F2 36 82 06 DE DB D1
0110 | 17 94 05 A7 AC BF 1C 7C 33 9A 02 5E E6 06 17 07
0120 | 0E F9 4E B1 EF 06 3F 9F 95 85 7E 78 14 75 C9 00
0130 | 56 A5 ED 9B 57 C1 C0 50 0E 3C C7 69 A5 BA 16 B0
0140 | 1E 57 72 49 48 EF 8E 65 66 0A EC 47 95 3E 2C 2D
0150 | DA 7C 5B DF 0B 23 05 00 3B 43 4B 0B 7A 77 69 62
0160 | 99 33 02 57 42 66 60 A4 58 3E BF C4 B1 A2 B6 43
0170 | F9 48 2F DF F3 51 A0 2A E8 F6 70 20 E5 3B FC 78
0180 | 44 F1 D9 D0 C8 C3 E3 3D E4 B0 E4 65 C5 DE C8 EA
0190 | C9 CD 6F C3 92 41 E4 AC 9E 0D B0 98 AB 40 FE E3
01A0 | AB 38 C9 E1 B0 D3 4F 88 2A 78 AF C8 CF 0B BB 9B
01B0 | 95 A5 64 5F 86 84 42 BD C5 FD 30 4E 15 23 7E 19
01C0 | B6 B1 9C 18 E1 90 2D 77 FF 63 60 E5 F3 4E EF AE
01D0 | 1C 98 74 C6 01 59 FA 5C B2 4D 6F 30 FF 41 1F 5B
01E0 | 0E 57 6C 02 37 2A E7 78 6D 31 AC 76 AD 6A 24 97
01F0 | 45 7A 20 77 AE 7C B0 4B 4E 22 C9 1B 89 FF 72 80
0200 | A8 96 EC 6F 28 33 57 70 19 7C 99 2F BF 00 AD 4B
0210 | CB 68 E3 5B 55 E4 57 FE FF BF D3 B8 EF BB 64 61
0220 | 73 62 BD D7 35 4C 25 B0 2D E0 E4 E6 F6 5A FF 4B
0230 | E3 9A A3 88 BB 55 0E 29 6E 45 A8 91 EA 8C D1 ED
0240 | 1A D8 3E 64 3D 24 2B BB 59 26 EA DD 5C 8C 18 AD
0250 | 4B 8B CB 8E 14 49 2F 47 76 FF 34 76 16 F1 26 8E
0260 | 27 F8 F6 AF B0 ED EF 5D D7 95 EC 6B 70 FB FE 78
0270 | 64 7B E3 16 FE 2D B3 43 6F 5B 5E B9 66 16 69 A4
0280 | E4 92 A3 6A 43 0E ED 24 A5 52 5B 09</code></pre>
<p>Payload (de)serialization:</p>
<pre><code>server_DH_params_ok#d0e8075c nonce:int128 server_nonce:int128 encrypted_answer:string = Server_DH_Params;</code></pre>
<table class="table">
@ -464,13 +464,13 @@ random_padding_bytes = 4347A0F58FFA3C09FD35129D919DE5F28204BB1881B4DFD74F34E8D37
<tr>
<td>message_id</td>
<td>8, 8</td>
<td><code>016478428A0CEB65</code></td>
<td><code>01942B8BDD756466</code></td>
<td>Message ID generated as specified <a href="/mtproto/description#message-identifier-msg-id">here »</a> (unixtime() &lt;&lt; 32) + (N*4)</td>
</tr>
<tr>
<td>message_length</td>
<td>16, 4</td>
<td><code>DC020000</code> (732 in decimal)</td>
<td><code>F0020000</code> (752 in decimal)</td>
<td>Message body length</td>
</tr>
<tr>
@ -482,19 +482,19 @@ random_padding_bytes = 4347A0F58FFA3C09FD35129D919DE5F28204BB1881B4DFD74F34E8D37
<tr>
<td>nonce</td>
<td>24, 16</td>
<td><code>6C5D0183C09B3D4C650C7A02E4D8BDF8</code></td>
<td><code>0BFE9D6B3D0A6BE137494141F39D2D23</code></td>
<td>Value generated by client in Step 1</td>
</tr>
<tr>
<td>server_nonce</td>
<td>40, 16</td>
<td><code>F39F03F1565D6D002851C6FCAC8ACD0D</code></td>
<td><code>87BB2211926199C99D852A84B61A13B5</code></td>
<td>Value received from server in Step 2</td>
</tr>
<tr>
<td>encrypted_answer</td>
<td>56, 596</td>
<td><code>FE500200FC5B354A74FF074F4736CD0C</code> <code>0015176F2F858D3A2DFC31742A4BDC67</code> <code>CD55FF1E0B1CE75D392AF57BD8C4A0B9</code> <code>008C9B8DC220B867530CCBC2BB5F7491</code> <code>093C3BCD51F27E71ADE010ED22A4F616</code> <code>71D35EAB57618C0C1A35998FC14A917C</code> <code>CD6C63C83EA336EA9C4016487D9A18DB</code> <code>4FDC650CA8DFF7F3FC8B78D50EDAFE30</code> <code>F20152AA2FEB0C14C120388E0B28EC8E</code> <code>3D4B4905A79664FE997C8E4A4352329A</code> <code>E00B6284F7382CDA1B19E536EE686E90</code> <code>3D8213B5D4CD8E2BE02B3E988392A73B</code> <code>7BF8FB7B0282EA853F5CEF282C8F1BDB</code> <code>7D464CDC095463B7A7E987879426B3E6</code> <code>6E8A39EE8A0AD594AC87AD5E4A38E407</code> <code>FED3E70EB5300AAE05874E0E81F224E2</code> <code>F57C370F484878905F7A0435EC4FF06E</code> <code>477223163DAAE07FAEC5FB3B6448AD9C</code> <code>3890FBE01A957F8CDD3783CDAF78AC60</code> <code>684EF4C9A07DE2211FF9C1865F745E4A</code> <code>4A2C56747E4963473564A19840C18266</code> <code>9CFE8463A0376E3FB5FBB047DA0B87C1</code> <code>88A5B32633CF55EE1BD935B56BF80E44</code> <code>77B1846A9CB279503E6C44EB0091B0EC</code> <code>A1080EED4744CF5589B8926C5C8B6E78</code> <code>B214B746834EB07CDB37B3F3C37DE7BD</code> <code>F728655B4C6D32E7D9F8A2840562299D</code> <code>10322C29D80313EA17A28B0C8685A426</code> <code>F70EFEBA8D57EED1B7E60D1117BFA3F9</code> <code>49B110CBE20854C2F1AB4C37A0916008</code> <code>AB2063B675E232979BD994836957A186</code> <code>1BCD63CE8AC2D1EE9997DC48F54F68F4</code> <code>C18385D447A9428391A2C77713FE4CC7</code> <code>5B921C7C2EBAA28016C540128B179BF5</code> <code>632790273EF1647FAA5B9827DD89C29D</code> <code>61EDDDA768E8AFC4F04FBA8B025EF4B4</code> <code>451C71DB632652928427BE66B6F1FE0A</code><br> <code>88943B2F</code></td>
<td><code>FE5002007588A5C1F69A41C8E5C27590</code> <code>DAC1774F99B86FC6982CE56C37D323C2</code> <code>42C6189383B4E4C06489DAAE505B82F0</code> <code>ED29263C661F68417AA99D74FBE5E735</code> <code>58864DD1BBA8D333521D1B9497234D28</code> <code>2A991883797A6CBCDB1AE83B95DA4B8F</code> <code>3D26612536C6EEEA8A51E5288333012F</code> <code>6696DE399828243B5ED3BAC4B75473A4</code> <code>62948DF1267D728A960583F3EA51793F</code> <code>3B0FBE96CC14468D4A557A6556516BC2</code> <code>E86ACC40AFF764FE6F6C0D0C9782D28C</code> <code>5B6027530E9F7411E5C43291D4076D9F</code> <code>90333E753CF82E1870767A5016CA5CD3</code> <code>4EF2368206DEDBD1179405A7ACBF1C7C</code> <code>339A025EE60617070EF94EB1EF063F9F</code> <code>95857E781475C90056A5ED9B57C1C050</code> <code>0E3CC769A5BA16B01E57724948EF8E65</code> <code>660AEC47953E2C2DDA7C5BDF0B230500</code> <code>3B434B0B7A77696299330257426660A4</code> <code>583EBFC4B1A2B643F9482FDFF351A02A</code> <code>E8F67020E53BFC7844F1D9D0C8C3E33D</code> <code>E4B0E465C5DEC8EAC9CD6FC39241E4AC</code> <code>9E0DB098AB40FEE3AB38C9E1B0D34F88</code> <code>2A78AFC8CF0BBB9B95A5645F868442BD</code> <code>C5FD304E15237E19B6B19C18E1902D77</code> <code>FF6360E5F34EEFAE1C9874C60159FA5C</code> <code>B24D6F30FF411F5B0E576C02372AE778</code> <code>6D31AC76AD6A2497457A2077AE7CB04B</code> <code>4E22C91B89FF7280A896EC6F28335770</code> <code>197C992FBF00AD4BCB68E35B55E457FE</code> <code>FFBFD3B8EFBB64617362BDD7354C25B0</code> <code>2DE0E4E6F65AFF4BE39AA388BB550E29</code> <code>6E45A891EA8CD1ED1AD83E643D242BBB</code> <code>5926EADD5C8C18AD4B8BCB8E14492F47</code> <code>76FF347616F1268E27F8F6AFB0EDEF5D</code> <code>D795EC6B70FBFE78647BE316FE2DB343</code> <code>6F5B5EB9661669A4E492A36A430EED24</code><br> <code>A5525B09</code></td>
<td>See below</td>
</tr>
</tbody>
@ -502,20 +502,20 @@ random_padding_bytes = 4347A0F58FFA3C09FD35129D919DE5F28204BB1881B4DFD74F34E8D37
<!-- end server_DH_params_ok -->
<p>Decrypt <code>encrypted_answer</code> using the reverse of the process specified in <a href="/mtproto/auth_key#6-server-responds-with">step 6</a>:</p>
<!-- start server_DH_inner_data_input -->
<pre><code>encrypted_answer = FC5B354A74FF074F4736CD0C0015176F2F858D3A2DFC31742A4BDC67CD55FF1E0B1CE75D392AF57BD8C4A0B9008C9B8DC220B867530CCBC2BB5F7491093C3BCD51F27E71ADE010ED22A4F61671D35EAB57618C0C1A35998FC14A917CCD6C63C83EA336EA9C4016487D9A18DB4FDC650CA8DFF7F3FC8B78D50EDAFE30F20152AA2FEB0C14C120388E0B28EC8E3D4B4905A79664FE997C8E4A4352329AE00B6284F7382CDA1B19E536EE686E903D8213B5D4CD8E2BE02B3E988392A73B7BF8FB7B0282EA853F5CEF282C8F1BDB7D464CDC095463B7A7E987879426B3E66E8A39EE8A0AD594AC87AD5E4A38E407FED3E70EB5300AAE05874E0E81F224E2F57C370F484878905F7A0435EC4FF06E477223163DAAE07FAEC5FB3B6448AD9C3890FBE01A957F8CDD3783CDAF78AC60684EF4C9A07DE2211FF9C1865F745E4A4A2C56747E4963473564A19840C182669CFE8463A0376E3FB5FBB047DA0B87C188A5B32633CF55EE1BD935B56BF80E4477B1846A9CB279503E6C44EB0091B0ECA1080EED4744CF5589B8926C5C8B6E78B214B746834EB07CDB37B3F3C37DE7BDF728655B4C6D32E7D9F8A2840562299D10322C29D80313EA17A28B0C8685A426F70EFEBA8D57EED1B7E60D1117BFA3F949B110CBE20854C2F1AB4C37A0916008AB2063B675E232979BD994836957A1861BCD63CE8AC2D1EE9997DC48F54F68F4C18385D447A9428391A2C77713FE4CC75B921C7C2EBAA28016C540128B179BF5632790273EF1647FAA5B9827DD89C29D61EDDDA768E8AFC4F04FBA8B025EF4B4451C71DB632652928427BE66B6F1FE0A88943B2F
tmp_aes_key = D67A9AF27A626BEB5A05876F54041BEB5B740B5AD508AFF47098B475BFF245C9
tmp_aes_iv = 633E1706BCD8F7B53618C96E9156EA9D01C547EE97A967AFC46D7AF92D1F9769</code></pre>
<pre><code>encrypted_answer = 7588A5C1F69A41C8E5C27590DAC1774F99B86FC6982CE56C37D323C242C6189383B4E4C06489DAAE505B82F0ED29263C661F68417AA99D74FBE5E73558864DD1BBA8D333521D1B9497234D282A991883797A6CBCDB1AE83B95DA4B8F3D26612536C6EEEA8A51E5288333012F6696DE399828243B5ED3BAC4B75473A462948DF1267D728A960583F3EA51793F3B0FBE96CC14468D4A557A6556516BC2E86ACC40AFF764FE6F6C0D0C9782D28C5B6027530E9F7411E5C43291D4076D9F90333E753CF82E1870767A5016CA5CD34EF2368206DEDBD1179405A7ACBF1C7C339A025EE60617070EF94EB1EF063F9F95857E781475C90056A5ED9B57C1C0500E3CC769A5BA16B01E57724948EF8E65660AEC47953E2C2DDA7C5BDF0B2305003B434B0B7A77696299330257426660A4583EBFC4B1A2B643F9482FDFF351A02AE8F67020E53BFC7844F1D9D0C8C3E33DE4B0E465C5DEC8EAC9CD6FC39241E4AC9E0DB098AB40FEE3AB38C9E1B0D34F882A78AFC8CF0BBB9B95A5645F868442BDC5FD304E15237E19B6B19C18E1902D77FF6360E5F34EEFAE1C9874C60159FA5CB24D6F30FF411F5B0E576C02372AE7786D31AC76AD6A2497457A2077AE7CB04B4E22C91B89FF7280A896EC6F28335770197C992FBF00AD4BCB68E35B55E457FEFFBFD3B8EFBB64617362BDD7354C25B02DE0E4E6F65AFF4BE39AA388BB550E296E45A891EA8CD1ED1AD83E643D242BBB5926EADD5C8C18AD4B8BCB8E14492F4776FF347616F1268E27F8F6AFB0EDEF5DD795EC6B70FBFE78647BE316FE2DB3436F5B5EB9661669A4E492A36A430EED24A5525B09
tmp_aes_key = C7777CE359E2207BAAAEFF1726DC69D536B9562F8AC0AEA52E411C05D372B6A6
tmp_aes_iv = BD3674185FDEB79A8470EF790D462B59B4D1BC47C27DBEA935135D561CFEF7D6</code></pre>
<!-- end server_DH_inner_data_input -->
<p>Yielding:</p>
<!-- start server_DH_inner_data_output -->
<pre><code>answer_with_hash = 3CEEF63E6429077AC0AF699997900135D70CBADEBA0D89B56C5D0183C09B3D4C650C7A02E4D8BDF8F39F03F1565D6D002851C6FCAC8ACD0D03000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE0001006039629EBA52516DC5B01C7C7F28BE83F751F923A88085CC05C25F388E6031FFBDC0821E95B2E859E0E1FB132F6CC448DF87D23823055E13B4F8A9F1656B71424521EE9C0B806CF8FEB8A3331BA08694FD538A92A50F6A15382ED36D15EB3DB939232FC8965BA089AC4A6E03F5187E5BB1E2E80B559B944B613A588A61F984C177D453EFA668B93F97AB8819018D937C9BFAFF671C115D710EC9784B2DD1F52628466E5B070E30A43CFF773713383359D49C41330AFC2A6EAB26393E72E102A5CDF6C7E26648D9902B75B39CD4CC4D2F6E2E9B38B54FFF23292894B6BD403EFE742A88EAF2742DD50234A8D2BE05E7D506174EB47E11EEA074A0FC226D4D9D358A0CEB6527AF3FBAABC99484
answer = BA0D89B56C5D0183C09B3D4C650C7A02E4D8BDF8F39F03F1565D6D002851C6FCAC8ACD0D03000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE0001006039629EBA52516DC5B01C7C7F28BE83F751F923A88085CC05C25F388E6031FFBDC0821E95B2E859E0E1FB132F6CC448DF87D23823055E13B4F8A9F1656B71424521EE9C0B806CF8FEB8A3331BA08694FD538A92A50F6A15382ED36D15EB3DB939232FC8965BA089AC4A6E03F5187E5BB1E2E80B559B944B613A588A61F984C177D453EFA668B93F97AB8819018D937C9BFAFF671C115D710EC9784B2DD1F52628466E5B070E30A43CFF773713383359D49C41330AFC2A6EAB26393E72E102A5CDF6C7E26648D9902B75B39CD4CC4D2F6E2E9B38B54FFF23292894B6BD403EFE742A88EAF2742DD50234A8D2BE05E7D506174EB47E11EEA074A0FC226D4D9D358A0CEB6527AF3FBAABC99484</code></pre>
<pre><code>answer_with_hash = 73AB84BACF18E14FFE355CBF2C96CD522FA3D9DBBA0D89B50BFE9D6B3D0A6BE137494141F39D2D2387BB2211926199C99D852A84B61A13B503000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE000100A974C49F454931C0E6F8CD2F53B624B637F14333003C9C54674DAF636E8F860858E7BBC40954218E3BECD260E271BC622C76D7AE63C13BBF81EB06BF054F27A17F108D42CB6C914D81720B81CFE6C926F546586A54A9C4A74B123A123E9E9A5371511369B52C1149D8579BE52D1FE84E4E4DCA16B7460E29F36CF4E8DAA48579C6E7D6B819D3DC576E0C54ACBB75DF5FD9E28E5B2B3DC742C9055887A6190CE42F52DEA151723E1C1F02023A433A1FE4DCE3842CD37A5C12BE19BC9A4CB1C5E3AF895444EBB883D56FECC61CAD1980117D2F492C815DFE65F4A12C5CECF2B06DB9BD3BBF9BB14B475A7D29693CE4FB172FF6678B81C7FD5CF7DB4EC639011557DD75646666FD6A06BD2D1F26
answer = BA0D89B50BFE9D6B3D0A6BE137494141F39D2D2387BB2211926199C99D852A84B61A13B503000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE000100A974C49F454931C0E6F8CD2F53B624B637F14333003C9C54674DAF636E8F860858E7BBC40954218E3BECD260E271BC622C76D7AE63C13BBF81EB06BF054F27A17F108D42CB6C914D81720B81CFE6C926F546586A54A9C4A74B123A123E9E9A5371511369B52C1149D8579BE52D1FE84E4E4DCA16B7460E29F36CF4E8DAA48579C6E7D6B819D3DC576E0C54ACBB75DF5FD9E28E5B2B3DC742C9055887A6190CE42F52DEA151723E1C1F02023A433A1FE4DCE3842CD37A5C12BE19BC9A4CB1C5E3AF895444EBB883D56FECC61CAD1980117D2F492C815DFE65F4A12C5CECF2B06DB9BD3BBF9BB14B475A7D29693CE4FB172FF6678B81C7FD5CF7DB4EC639011557DD75646666FD6A06BD2D1F26</code></pre>
<!-- end server_DH_inner_data_output -->
<!-- start server_DH_inner_data -->
<p>Generated payload (excluding transport headers/trailers):</p>
<pre><code>0000 | BA 0D 89 B5 6C 5D 01 83 C0 9B 3D 4C 65 0C 7A 02
0010 | E4 D8 BD F8 F3 9F 03 F1 56 5D 6D 00 28 51 C6 FC
0020 | AC 8A CD 0D 03 00 00 00 FE 00 01 00 C7 1C AE B9
<pre><code>0000 | BA 0D 89 B5 0B FE 9D 6B 3D 0A 6B E1 37 49 41 41
0010 | F3 9D 2D 23 87 BB 22 11 92 61 99 C9 9D 85 2A 84
0020 | B6 1A 13 B5 03 00 00 00 FE 00 01 00 C7 1C AE B9
0030 | C6 B1 C9 04 8E 6C 52 2F 70 F1 3F 73 98 0D 40 23
0040 | 8E 3E 21 C1 49 34 D0 37 56 3D 93 0F 48 19 8A 0A
0050 | A7 C1 40 58 22 94 93 D2 25 30 F4 DB FA 33 6F 6E
@ -532,23 +532,23 @@ answer = BA0D89B56C5D0183C09B3D4C650C7A02E4D8BDF8F39F03F1565D6D002851C6FCAC8ACD0
0100 | F4 7B F9 59 D9 56 85 0C E9 29 85 1F 0D 81 15 F6
0110 | 35 B1 05 EE 2E 4E 15 D0 4B 24 54 BF 6F 4F AD F0
0120 | 34 B1 04 03 11 9C D8 E3 B9 2F CC 5B FE 00 01 00
0130 | 60 39 62 9E BA 52 51 6D C5 B0 1C 7C 7F 28 BE 83
0140 | F7 51 F9 23 A8 80 85 CC 05 C2 5F 38 8E 60 31 FF
0150 | BD C0 82 1E 95 B2 E8 59 E0 E1 FB 13 2F 6C C4 48
0160 | DF 87 D2 38 23 05 5E 13 B4 F8 A9 F1 65 6B 71 42
0170 | 45 21 EE 9C 0B 80 6C F8 FE B8 A3 33 1B A0 86 94
0180 | FD 53 8A 92 A5 0F 6A 15 38 2E D3 6D 15 EB 3D B9
0190 | 39 23 2F C8 96 5B A0 89 AC 4A 6E 03 F5 18 7E 5B
01A0 | B1 E2 E8 0B 55 9B 94 4B 61 3A 58 8A 61 F9 84 C1
01B0 | 77 D4 53 EF A6 68 B9 3F 97 AB 88 19 01 8D 93 7C
01C0 | 9B FA FF 67 1C 11 5D 71 0E C9 78 4B 2D D1 F5 26
01D0 | 28 46 6E 5B 07 0E 30 A4 3C FF 77 37 13 38 33 59
01E0 | D4 9C 41 33 0A FC 2A 6E AB 26 39 3E 72 E1 02 A5
01F0 | CD F6 C7 E2 66 48 D9 90 2B 75 B3 9C D4 CC 4D 2F
0200 | 6E 2E 9B 38 B5 4F FF 23 29 28 94 B6 BD 40 3E FE
0210 | 74 2A 88 EA F2 74 2D D5 02 34 A8 D2 BE 05 E7 D5
0220 | 06 17 4E B4 7E 11 EE A0 74 A0 FC 22 6D 4D 9D 35
0230 | 8A 0C EB 65</code></pre>
0130 | A9 74 C4 9F 45 49 31 C0 E6 F8 CD 2F 53 B6 24 B6
0140 | 37 F1 43 33 00 3C 9C 54 67 4D AF 63 6E 8F 86 08
0150 | 58 E7 BB C4 09 54 21 8E 3B EC D2 60 E2 71 BC 62
0160 | 2C 76 D7 AE 63 C1 3B BF 81 EB 06 BF 05 4F 27 A1
0170 | 7F 10 8D 42 CB 6C 91 4D 81 72 0B 81 CF E6 C9 26
0180 | F5 46 58 6A 54 A9 C4 A7 4B 12 3A 12 3E 9E 9A 53
0190 | 71 51 13 69 B5 2C 11 49 D8 57 9B E5 2D 1F E8 4E
01A0 | 4E 4D CA 16 B7 46 0E 29 F3 6C F4 E8 DA A4 85 79
01B0 | C6 E7 D6 B8 19 D3 DC 57 6E 0C 54 AC BB 75 DF 5F
01C0 | D9 E2 8E 5B 2B 3D C7 42 C9 05 58 87 A6 19 0C E4
01D0 | 2F 52 DE A1 51 72 3E 1C 1F 02 02 3A 43 3A 1F E4
01E0 | DC E3 84 2C D3 7A 5C 12 BE 19 BC 9A 4C B1 C5 E3
01F0 | AF 89 54 44 EB B8 83 D5 6F EC C6 1C AD 19 80 11
0200 | 7D 2F 49 2C 81 5D FE 65 F4 A1 2C 5C EC F2 B0 6D
0210 | B9 BD 3B BF 9B B1 4B 47 5A 7D 29 69 3C E4 FB 17
0220 | 2F F6 67 8B 81 C7 FD 5C F7 DB 4E C6 39 01 15 57
0230 | DD 75 64 66</code></pre>
<p>Payload (de)serialization:</p>
<pre><code>server_DH_inner_data#b5890dba nonce:int128 server_nonce:int128 g:int dh_prime:string g_a:string server_time:int = Server_DH_inner_data;</code></pre>
<table class="table">
@ -570,13 +570,13 @@ answer = BA0D89B56C5D0183C09B3D4C650C7A02E4D8BDF8F39F03F1565D6D002851C6FCAC8ACD0
<tr>
<td>nonce</td>
<td>4, 16</td>
<td><code>6C5D0183C09B3D4C650C7A02E4D8BDF8</code></td>
<td><code>0BFE9D6B3D0A6BE137494141F39D2D23</code></td>
<td>Value generated by client in Step 1</td>
</tr>
<tr>
<td>server_nonce</td>
<td>20, 16</td>
<td><code>F39F03F1565D6D002851C6FCAC8ACD0D</code></td>
<td><code>87BB2211926199C99D852A84B61A13B5</code></td>
<td>Value received from server in Step 2</td>
</tr>
<tr>
@ -594,13 +594,13 @@ answer = BA0D89B56C5D0183C09B3D4C650C7A02E4D8BDF8F39F03F1565D6D002851C6FCAC8ACD0
<tr>
<td>g_a</td>
<td>300, 260</td>
<td><code>FE0001006039629EBA52516DC5B01C7C</code> <code>7F28BE83F751F923A88085CC05C25F38</code> <code>8E6031FFBDC0821E95B2E859E0E1FB13</code> <code>2F6CC448DF87D23823055E13B4F8A9F1</code> <code>656B71424521EE9C0B806CF8FEB8A333</code> <code>1BA08694FD538A92A50F6A15382ED36D</code> <code>15EB3DB939232FC8965BA089AC4A6E03</code> <code>F5187E5BB1E2E80B559B944B613A588A</code> <code>61F984C177D453EFA668B93F97AB8819</code> <code>018D937C9BFAFF671C115D710EC9784B</code> <code>2DD1F52628466E5B070E30A43CFF7737</code> <code>13383359D49C41330AFC2A6EAB26393E</code> <code>72E102A5CDF6C7E26648D9902B75B39C</code> <code>D4CC4D2F6E2E9B38B54FFF23292894B6</code> <code>BD403EFE742A88EAF2742DD50234A8D2</code> <code>BE05E7D506174EB47E11EEA074A0FC22</code><br> <code>6D4D9D35</code></td>
<td><code>FE000100A974C49F454931C0E6F8CD2F</code> <code>53B624B637F14333003C9C54674DAF63</code> <code>6E8F860858E7BBC40954218E3BECD260</code> <code>E271BC622C76D7AE63C13BBF81EB06BF</code> <code>054F27A17F108D42CB6C914D81720B81</code> <code>CFE6C926F546586A54A9C4A74B123A12</code> <code>3E9E9A5371511369B52C1149D8579BE5</code> <code>2D1FE84E4E4DCA16B7460E29F36CF4E8</code> <code>DAA48579C6E7D6B819D3DC576E0C54AC</code> <code>BB75DF5FD9E28E5B2B3DC742C9055887</code> <code>A6190CE42F52DEA151723E1C1F02023A</code> <code>433A1FE4DCE3842CD37A5C12BE19BC9A</code> <code>4CB1C5E3AF895444EBB883D56FECC61C</code> <code>AD1980117D2F492C815DFE65F4A12C5C</code> <code>ECF2B06DB9BD3BBF9BB14B475A7D2969</code> <code>3CE4FB172FF6678B81C7FD5CF7DB4EC6</code><br> <code>39011557</code></td>
<td><code>g_a</code> diffie-hellman parameter</td>
</tr>
<tr>
<td>server_time</td>
<td>560, 4</td>
<td><code>8A0CEB65</code> (1709902986 in decimal)</td>
<td><code>DD756466</code> (1717859805 in decimal)</td>
<td>Server time</td>
</tr>
</tbody>
@ -609,34 +609,34 @@ answer = BA0D89B56C5D0183C09B3D4C650C7A02E4D8BDF8F39F03F1565D6D002851C6FCAC8ACD0
<h5><a class="anchor" href="#7-client-computes-random-2048-bit-number-b-using-a-sufficient-amount-of-entropy-and-sends-the-server-a-message" id="7-client-computes-random-2048-bit-number-b-using-a-sufficient-amount-of-entropy-and-sends-the-server-a-message" name="7-client-computes-random-2048-bit-number-b-using-a-sufficient-amount-of-entropy-and-sends-the-server-a-message"><i class="anchor-icon"></i></a>7) Client computes random 2048-bit number <em>b</em> (using a sufficient amount of entropy) and sends the server a message</h5>
<p>First, generate a secure random 2048-bit number b:</p>
<!-- start b -->
<pre><code>b = 3926B53315738C46D2E423FFB79850E2E379B64D1C5B3C83CDA52239918B87012F35E0AAA6C2F8D49E400DCC9791422AF46EDE0981A4DD725D31D9EAB91C6339BFBCF932A05074ACE182A78F385A72BCD28FF6F83D6BC67CC578F20BDACC27F213D7002B8505D41F538D97DEF151582FEFD432499059672725C202781982214D50E85D6BC462B27991DD3F644BF615805B96AED7FC8E08AB2F64D6F72BCB237C7E615521AC6C6729557E295E40FEA37A20357FF8EAB9CB6E67878D25ABCE71461855F44C14F01142B7965507053E6CDC9AA9DF1523733D53999C6B0AB865D90E7629F26766B5BFFAC67560D5046B67A9A9200D137D9ECE173D6CEC464307FB3D</code></pre>
<pre><code>b = 1FA80FEAEC1184E73B63B5352D37A37024B7B498B809DF38D2F60FD4D8539605CDCEA2A073DD125099D62A191137925E1D8C41E56FA5BA084C7B3467BA63697C3D57274B763D43055BD079099A7EEC4F5B9AC6A60BAC82A9D8A434C99D62C70C9DD4E56A4951F7080D78DD84C6F890681AC2BFBBCC6868B33B75EE91F8C390139AE4D38B146C1286080E89C74749364F074A37AC0A230923EC92B146D3BFD15841059E9BB24C3AC50FC7BCD1933F3E7AEBCF5EAF49E1BBD01FD4D248DED6DC1B1069DAD8E671AA3D734BBE44C7AAAC95772C02625234960D9DB7F6967F387F3566F20A546498FFC6418256CCFB89D325F9C1934B772892BE68F58E1460CF8849</code></pre>
<!-- end b -->
<p>Then compute <code>g_b = pow(g, b) mod dh_prime</code></p>
<!-- start g_b -->
<pre><code>g_b = 1DDC05FBEF7A9710530DAFAA636EA23AC840EF6E4568F46808A5C9C066BE1167EE71D5991672D79B803D6BE374076C3583B55143641F0347E0AD51DEA2C33C787915879FF333ED3BA33A2B58DF37E435910A5462C47F0CFAC658ABFA6020E36188719355D6D5477C93A69F9795EBEF0C43744E5E267579439E0ABC8D15365DE72709B19ECB516D148BB07836AA3BB3B05B4E0A226FC9DCDBE56CAF573D831D4384ECECB7529009E06996DE5F71A3CD1E2614467187C4569098571D90F5B6BD6A59214AD6F073E35A5D2436117F087FA67FC8BE53C1788338342990DE6AE9C08522CA490795B9D4E9E177D228BCDCDA2ABF27904917C2E22C36CD7746FA1F2C53</code></pre>
<pre><code>g_b = 6A4277562D3206742DABBB6D4411B896367514D8D4531D1292430EBFA418BB74C63CBD880BEFAF0ECC03FC9C62E8C10C51E32BDB923B0D5A335A22C8AE6E5E11AC2CF0D1D69A3E51AFB54865A6098969750CCF03AA5E48EC455506BAB99524D779854ECDA622DA661F055FBC3FC6B67B82B5BB172FEF7FB3577ACDA3E0FDA6CEE6E29BAA43FA6B27A76C9F5ECB29DE2E485B67BC1A65F1A72FB1A7D632B02584A0218C09A8D5F90880848DAAF3987F46E34F7F554040563503B8C45213ADDFCE8A74964F49C407ED5FCB95034E58B57DCC3C4C354657D8B0165501332314D26899F9F667E4809D41F59BEB5E0A94B9FE97653607DDB83403F6B87DE6147401D1</code></pre>
<!-- end g_b -->
<h6>7.1) generation of encrypted_data</h6>
<!-- start client_DH_inner_data -->
<p>Generated payload (excluding transport headers/trailers):</p>
<pre><code>0000 | 54 B6 43 66 6C 5D 01 83 C0 9B 3D 4C 65 0C 7A 02
0010 | E4 D8 BD F8 F3 9F 03 F1 56 5D 6D 00 28 51 C6 FC
0020 | AC 8A CD 0D 00 00 00 00 00 00 00 00 FE 00 01 00
0030 | 1D DC 05 FB EF 7A 97 10 53 0D AF AA 63 6E A2 3A
0040 | C8 40 EF 6E 45 68 F4 68 08 A5 C9 C0 66 BE 11 67
0050 | EE 71 D5 99 16 72 D7 9B 80 3D 6B E3 74 07 6C 35
0060 | 83 B5 51 43 64 1F 03 47 E0 AD 51 DE A2 C3 3C 78
0070 | 79 15 87 9F F3 33 ED 3B A3 3A 2B 58 DF 37 E4 35
0080 | 91 0A 54 62 C4 7F 0C FA C6 58 AB FA 60 20 E3 61
0090 | 88 71 93 55 D6 D5 47 7C 93 A6 9F 97 95 EB EF 0C
00A0 | 43 74 4E 5E 26 75 79 43 9E 0A BC 8D 15 36 5D E7
00B0 | 27 09 B1 9E CB 51 6D 14 8B B0 78 36 AA 3B B3 B0
00C0 | 5B 4E 0A 22 6F C9 DC DB E5 6C AF 57 3D 83 1D 43
00D0 | 84 EC EC B7 52 90 09 E0 69 96 DE 5F 71 A3 CD 1E
00E0 | 26 14 46 71 87 C4 56 90 98 57 1D 90 F5 B6 BD 6A
00F0 | 59 21 4A D6 F0 73 E3 5A 5D 24 36 11 7F 08 7F A6
0100 | 7F C8 BE 53 C1 78 83 38 34 29 90 DE 6A E9 C0 85
0110 | 22 CA 49 07 95 B9 D4 E9 E1 77 D2 28 BC DC DA 2A
0120 | BF 27 90 49 17 C2 E2 2C 36 CD 77 46 FA 1F 2C 53</code></pre>
<pre><code>0000 | 54 B6 43 66 0B FE 9D 6B 3D 0A 6B E1 37 49 41 41
0010 | F3 9D 2D 23 87 BB 22 11 92 61 99 C9 9D 85 2A 84
0020 | B6 1A 13 B5 00 00 00 00 00 00 00 00 FE 00 01 00
0030 | 6A 42 77 56 2D 32 06 74 2D AB BB 6D 44 11 B8 96
0040 | 36 75 14 D8 D4 53 1D 12 92 43 0E BF A4 18 BB 74
0050 | C6 3C BD 88 0B EF AF 0E CC 03 FC 9C 62 E8 C1 0C
0060 | 51 E3 2B DB 92 3B 0D 5A 33 5A 22 C8 AE 6E 5E 11
0070 | AC 2C F0 D1 D6 9A 3E 51 AF B5 48 65 A6 09 89 69
0080 | 75 0C CF 03 AA 5E 48 EC 45 55 06 BA B9 95 24 D7
0090 | 79 85 4E CD A6 22 DA 66 1F 05 5F BC 3F C6 B6 7B
00A0 | 82 B5 BB 17 2F EF 7F B3 57 7A CD A3 E0 FD A6 CE
00B0 | E6 E2 9B AA 43 FA 6B 27 A7 6C 9F 5E CB 29 DE 2E
00C0 | 48 5B 67 BC 1A 65 F1 A7 2F B1 A7 D6 32 B0 25 84
00D0 | A0 21 8C 09 A8 D5 F9 08 80 84 8D AA F3 98 7F 46
00E0 | E3 4F 7F 55 40 40 56 35 03 B8 C4 52 13 AD DF CE
00F0 | 8A 74 96 4F 49 C4 07 ED 5F CB 95 03 4E 58 B5 7D
0100 | CC 3C 4C 35 46 57 D8 B0 16 55 01 33 23 14 D2 68
0110 | 99 F9 F6 67 E4 80 9D 41 F5 9B EB 5E 0A 94 B9 FE
0120 | 97 65 36 07 DD B8 34 03 F6 B8 7D E6 14 74 01 D1</code></pre>
<p>Payload (de)serialization:</p>
<pre><code>client_DH_inner_data#6643b654 nonce:int128 server_nonce:int128 retry_id:long g_b:string = Client_DH_Inner_Data;</code></pre>
<table class="table">
@ -658,19 +658,19 @@ answer = BA0D89B56C5D0183C09B3D4C650C7A02E4D8BDF8F39F03F1565D6D002851C6FCAC8ACD0
<tr>
<td>nonce</td>
<td>4, 16</td>
<td><code>6C5D0183C09B3D4C650C7A02E4D8BDF8</code></td>
<td><code>0BFE9D6B3D0A6BE137494141F39D2D23</code></td>
<td>Value generated by client in Step 1</td>
</tr>
<tr>
<td>server_nonce</td>
<td>20, 16</td>
<td><code>F39F03F1565D6D002851C6FCAC8ACD0D</code></td>
<td><code>87BB2211926199C99D852A84B61A13B5</code></td>
<td>Value received from server in Step 2</td>
</tr>
<tr>
<td>g_b</td>
<td>36, 260</td>
<td><code>FE0001001DDC05FBEF7A9710530DAFAA</code> <code>636EA23AC840EF6E4568F46808A5C9C0</code> <code>66BE1167EE71D5991672D79B803D6BE3</code> <code>74076C3583B55143641F0347E0AD51DE</code> <code>A2C33C787915879FF333ED3BA33A2B58</code> <code>DF37E435910A5462C47F0CFAC658ABFA</code> <code>6020E36188719355D6D5477C93A69F97</code> <code>95EBEF0C43744E5E267579439E0ABC8D</code> <code>15365DE72709B19ECB516D148BB07836</code> <code>AA3BB3B05B4E0A226FC9DCDBE56CAF57</code> <code>3D831D4384ECECB7529009E06996DE5F</code> <code>71A3CD1E2614467187C4569098571D90</code> <code>F5B6BD6A59214AD6F073E35A5D243611</code> <code>7F087FA67FC8BE53C1788338342990DE</code> <code>6AE9C08522CA490795B9D4E9E177D228</code> <code>BCDCDA2ABF27904917C2E22C36CD7746</code><br> <code>FA1F2C53</code></td>
<td><code>FE0001006A4277562D3206742DABBB6D</code> <code>4411B896367514D8D4531D1292430EBF</code> <code>A418BB74C63CBD880BEFAF0ECC03FC9C</code> <code>62E8C10C51E32BDB923B0D5A335A22C8</code> <code>AE6E5E11AC2CF0D1D69A3E51AFB54865</code> <code>A6098969750CCF03AA5E48EC455506BA</code> <code>B99524D779854ECDA622DA661F055FBC</code> <code>3FC6B67B82B5BB172FEF7FB3577ACDA3</code> <code>E0FDA6CEE6E29BAA43FA6B27A76C9F5E</code> <code>CB29DE2E485B67BC1A65F1A72FB1A7D6</code> <code>32B02584A0218C09A8D5F90880848DAA</code> <code>F3987F46E34F7F554040563503B8C452</code> <code>13ADDFCE8A74964F49C407ED5FCB9503</code> <code>4E58B57DCC3C4C354657D8B016550133</code> <code>2314D26899F9F667E4809D41F59BEB5E</code> <code>0A94B9FE97653607DDB83403F6B87DE6</code><br> <code>147401D1</code></td>
<td>Single-byte prefix denoting length, a 256-byte (2048-bit) string, and zero bytes of padding</td>
</tr>
<tr>
@ -684,47 +684,47 @@ answer = BA0D89B56C5D0183C09B3D4C650C7A02E4D8BDF8F39F03F1565D6D002851C6FCAC8ACD0
<!-- end client_DH_inner_data -->
<p>The serialization of <em>Client_DH_Inner_Data</em> produces a string <strong>data</strong>. This is used to generate <strong>encrypted_data</strong> as specified in <a href="#7-client-computes-random-2048-bit-number-b-using-a-sufficient-amount-of-entropy-and-sends-the-server-a-message">step 6</a>, using the following inputs:</p>
<!-- start client_DH_inner_data_input -->
<pre><code>data = 54B643666C5D0183C09B3D4C650C7A02E4D8BDF8F39F03F1565D6D002851C6FCAC8ACD0D0000000000000000FE0001001DDC05FBEF7A9710530DAFAA636EA23AC840EF6E4568F46808A5C9C066BE1167EE71D5991672D79B803D6BE374076C3583B55143641F0347E0AD51DEA2C33C787915879FF333ED3BA33A2B58DF37E435910A5462C47F0CFAC658ABFA6020E36188719355D6D5477C93A69F9795EBEF0C43744E5E267579439E0ABC8D15365DE72709B19ECB516D148BB07836AA3BB3B05B4E0A226FC9DCDBE56CAF573D831D4384ECECB7529009E06996DE5F71A3CD1E2614467187C4569098571D90F5B6BD6A59214AD6F073E35A5D2436117F087FA67FC8BE53C1788338342990DE6AE9C08522CA490795B9D4E9E177D228BCDCDA2ABF27904917C2E22C36CD7746FA1F2C53
padding = D1AB41649AEDE24CDBCA70A7
tmp_aes_key = D67A9AF27A626BEB5A05876F54041BEB5B740B5AD508AFF47098B475BFF245C9
tmp_aes_iv = 633E1706BCD8F7B53618C96E9156EA9D01C547EE97A967AFC46D7AF92D1F9769</code></pre>
<pre><code>data = 54B643660BFE9D6B3D0A6BE137494141F39D2D2387BB2211926199C99D852A84B61A13B50000000000000000FE0001006A4277562D3206742DABBB6D4411B896367514D8D4531D1292430EBFA418BB74C63CBD880BEFAF0ECC03FC9C62E8C10C51E32BDB923B0D5A335A22C8AE6E5E11AC2CF0D1D69A3E51AFB54865A6098969750CCF03AA5E48EC455506BAB99524D779854ECDA622DA661F055FBC3FC6B67B82B5BB172FEF7FB3577ACDA3E0FDA6CEE6E29BAA43FA6B27A76C9F5ECB29DE2E485B67BC1A65F1A72FB1A7D632B02584A0218C09A8D5F90880848DAAF3987F46E34F7F554040563503B8C45213ADDFCE8A74964F49C407ED5FCB95034E58B57DCC3C4C354657D8B0165501332314D26899F9F667E4809D41F59BEB5E0A94B9FE97653607DDB83403F6B87DE6147401D1
padding = 573EC483F7801A59B475C54F
tmp_aes_key = C7777CE359E2207BAAAEFF1726DC69D536B9562F8AC0AEA52E411C05D372B6A6
tmp_aes_iv = BD3674185FDEB79A8470EF790D462B59B4D1BC47C27DBEA935135D561CFEF7D6</code></pre>
<!-- end client_DH_inner_data_input -->
<p>Process:</p>
<pre><code>data_with_hash := SHA1(data) + data + padding (0-15 random bytes such that total length is divisible by 16)
encrypted_data := AES256_ige_encrypt (data_with_hash, tmp_aes_key, tmp_aes_iv);</code></pre>
<p>Output:</p>
<!-- start client_DH_inner_data_output -->
<pre><code>encrypted_data = C0C869F3A61EDF52A8B225272E29F60F285210BBF02753CEA722A48CF940F4E7E4060252F991B8EBC7F9F0BCDE9F061AD4CA836C2B72814BE43B740F4BAA645137DB09776DA20D31C22F50A00CE3F2258F59BACBA2EFFB8D42BEAE51CFD796261DE24CE486471FE7B8CE22E2EA3474019C973AFB610730F903B0A23F50DB7880A0C290F6F55FE00E34A406161150151B1967EBD4896933BD40BA93636F5C9AC89E98CE8B948812B6BBABAF5ABAF3E2C1C67D22DE739F852D578A98A0E23F6362EAC4709764E6F4C7EEFAA0FE3580F5D609E06CDC23B011BEF6D496374EB37BA44B4BDAAED57A25CDD48B59B19CDFA328660D58186DC45C3450DA3FD7DFAE686CDA17744DA85A885C03D084F607520B9A6E50B97F658DE0AA1CA39291B66D3600D880036D6BD09830F05768BB0923FCCA119128B88C1A4481451337915FFAF4905978E04CC7EE7B4C7F7A48BD61B04E44</code></pre>
<pre><code>encrypted_data = B160815FF0457D0DBE5DE90D3575167CE1E4EDA690D0FD89C06FCF562B563D04D919EBAF11A8FEDA02C5A4B9D745F14285AA770C7DE5E6FAC936CA996DC7EE537BB8994CB39700A41F30CAF16EC4CD5BD62F00AB3D25254241F84FEF1E341F4F758A348AE7A73EA6BA32132C6463BB3FC3D9808D5EF4E69B2476EA127A0EF0D001B9D29672FF9FB82F0EDDCBFAB52DC3424AB7CD62D0894DA435A87A4FD5F913698E0A7EF8E5A9D0DD45B2D03D9B571B7DFACDF699AA4F1237BB268F7F45403A2F6679B97C2AC91A1A57E51EC59ADAF9E99D4FB6C6406C7DE9E825BA61EEC8CD7AC294C01FC2191518CEF8CDD9F882DF350375045AB6B50774CC42210E73128FDE86F73BB47D19B59B27C16397EC02A173869238711DAE83ECE806DF55521DBCF7A21E63240D732C46A604F9D4305DE25934A87B356681E3ACA961C3FDB86A1DF7F57428BC2420400679676AF5F78D5B</code></pre>
<!-- end client_DH_inner_data_output -->
<p>The length of the final string is 336 bytes.</p>
<h6>7.2) set_client_DH_params query</h6>
<!-- start set_client_DH_params -->
<p>Sent payload (excluding transport headers/trailers):</p>
<pre><code>0000 | 00 00 00 00 00 00 00 00 A0 58 07 00 8A 0C EB 65
0010 | 78 01 00 00 1F 5F 04 F5 6C 5D 01 83 C0 9B 3D 4C
0020 | 65 0C 7A 02 E4 D8 BD F8 F3 9F 03 F1 56 5D 6D 00
0030 | 28 51 C6 FC AC 8A CD 0D FE 50 01 00 C0 C8 69 F3
0040 | A6 1E DF 52 A8 B2 25 27 2E 29 F6 0F 28 52 10 BB
0050 | F0 27 53 CE A7 22 A4 8C F9 40 F4 E7 E4 06 02 52
0060 | F9 91 B8 EB C7 F9 F0 BC DE 9F 06 1A D4 CA 83 6C
0070 | 2B 72 81 4B E4 3B 74 0F 4B AA 64 51 37 DB 09 77
0080 | 6D A2 0D 31 C2 2F 50 A0 0C E3 F2 25 8F 59 BA CB
0090 | A2 EF FB 8D 42 BE AE 51 CF D7 96 26 1D E2 4C E4
00A0 | 86 47 1F E7 B8 CE 22 E2 EA 34 74 01 9C 97 3A FB
00B0 | 61 07 30 F9 03 B0 A2 3F 50 DB 78 80 A0 C2 90 F6
00C0 | F5 5F E0 0E 34 A4 06 16 11 50 15 1B 19 67 EB D4
00D0 | 89 69 33 BD 40 BA 93 63 6F 5C 9A C8 9E 98 CE 8B
00E0 | 94 88 12 B6 BB AB AF 5A BA F3 E2 C1 C6 7D 22 DE
00F0 | 73 9F 85 2D 57 8A 98 A0 E2 3F 63 62 EA C4 70 97
0100 | 64 E6 F4 C7 EE FA A0 FE 35 80 F5 D6 09 E0 6C DC
0110 | 23 B0 11 BE F6 D4 96 37 4E B3 7B A4 4B 4B DA AE
0120 | D5 7A 25 CD D4 8B 59 B1 9C DF A3 28 66 0D 58 18
0130 | 6D C4 5C 34 50 DA 3F D7 DF AE 68 6C DA 17 74 4D
0140 | A8 5A 88 5C 03 D0 84 F6 07 52 0B 9A 6E 50 B9 7F
0150 | 65 8D E0 AA 1C A3 92 91 B6 6D 36 00 D8 80 03 6D
0160 | 6B D0 98 30 F0 57 68 BB 09 23 FC CA 11 91 28 B8
0170 | 8C 1A 44 81 45 13 37 91 5F FA F4 90 59 78 E0 4C
0180 | C7 EE 7B 4C 7F 7A 48 BD 61 B0 4E 44</code></pre>
<pre><code>0000 | 00 00 00 00 00 00 00 00 68 B1 05 00 DD 75 64 66
0010 | 78 01 00 00 1F 5F 04 F5 0B FE 9D 6B 3D 0A 6B E1
0020 | 37 49 41 41 F3 9D 2D 23 87 BB 22 11 92 61 99 C9
0030 | 9D 85 2A 84 B6 1A 13 B5 FE 50 01 00 B1 60 81 5F
0040 | F0 45 7D 0D BE 5D E9 0D 35 75 16 7C E1 E4 ED A6
0050 | 90 D0 FD 89 C0 6F CF 56 2B 56 3D 04 D9 19 EB AF
0060 | 11 A8 FE DA 02 C5 A4 B9 D7 45 F1 42 85 AA 77 0C
0070 | 7D E5 E6 FA C9 36 CA 99 6D C7 EE 53 7B B8 99 4C
0080 | B3 97 00 A4 1F 30 CA F1 6E C4 CD 5B D6 2F 00 AB
0090 | 3D 25 25 42 41 F8 4F EF 1E 34 1F 4F 75 8A 34 8A
00A0 | E7 A7 3E A6 BA 32 13 2C 64 63 BB 3F C3 D9 80 8D
00B0 | 5E F4 E6 9B 24 76 EA 12 7A 0E F0 D0 01 B9 D2 96
00C0 | 72 FF 9F B8 2F 0E DD CB FA B5 2D C3 42 4A B7 CD
00D0 | 62 D0 89 4D A4 35 A8 7A 4F D5 F9 13 69 8E 0A 7E
00E0 | F8 E5 A9 D0 DD 45 B2 D0 3D 9B 57 1B 7D FA CD F6
00F0 | 99 AA 4F 12 37 BB 26 8F 7F 45 40 3A 2F 66 79 B9
0100 | 7C 2A C9 1A 1A 57 E5 1E C5 9A DA F9 E9 9D 4F B6
0110 | C6 40 6C 7D E9 E8 25 BA 61 EE C8 CD 7A C2 94 C0
0120 | 1F C2 19 15 18 CE F8 CD D9 F8 82 DF 35 03 75 04
0130 | 5A B6 B5 07 74 CC 42 21 0E 73 12 8F DE 86 F7 3B
0140 | B4 7D 19 B5 9B 27 C1 63 97 EC 02 A1 73 86 92 38
0150 | 71 1D AE 83 EC E8 06 DF 55 52 1D BC F7 A2 1E 63
0160 | 24 0D 73 2C 46 A6 04 F9 D4 30 5D E2 59 34 A8 7B
0170 | 35 66 81 E3 AC A9 61 C3 FD B8 6A 1D F7 F5 74 28
0180 | BC 24 20 40 06 79 67 6A F5 F7 8D 5B</code></pre>
<p>Payload (de)serialization:</p>
<pre><code>set_client_DH_params#f5045f1f nonce:int128 server_nonce:int128 encrypted_data:string = Set_client_DH_params_answer;</code></pre>
<table class="table">
@ -746,7 +746,7 @@ encrypted_data := AES256_ige_encrypt (data_with_hash, tmp_aes_key, tmp_aes_iv);<
<tr>
<td>message_id</td>
<td>8, 8</td>
<td><code>A05807008A0CEB65</code></td>
<td><code>68B10500DD756466</code></td>
<td>Message ID generated as specified <a href="/mtproto/description#message-identifier-msg-id">here »</a> (unixtime() &lt;&lt; 32) + (N*4)</td>
</tr>
<tr>
@ -764,19 +764,19 @@ encrypted_data := AES256_ige_encrypt (data_with_hash, tmp_aes_key, tmp_aes_iv);<
<tr>
<td>nonce</td>
<td>24, 16</td>
<td><code>6C5D0183C09B3D4C650C7A02E4D8BDF8</code></td>
<td><code>0BFE9D6B3D0A6BE137494141F39D2D23</code></td>
<td>Value generated by client in Step 1</td>
</tr>
<tr>
<td>server_nonce</td>
<td>40, 16</td>
<td><code>F39F03F1565D6D002851C6FCAC8ACD0D</code></td>
<td><code>87BB2211926199C99D852A84B61A13B5</code></td>
<td>Value received from server in Step 2</td>
</tr>
<tr>
<td>encrypted_data</td>
<td>56, 340</td>
<td><code>FE500100C0C869F3A61EDF52A8B22527</code> <code>2E29F60F285210BBF02753CEA722A48C</code> <code>F940F4E7E4060252F991B8EBC7F9F0BC</code> <code>DE9F061AD4CA836C2B72814BE43B740F</code> <code>4BAA645137DB09776DA20D31C22F50A0</code> <code>0CE3F2258F59BACBA2EFFB8D42BEAE51</code> <code>CFD796261DE24CE486471FE7B8CE22E2</code> <code>EA3474019C973AFB610730F903B0A23F</code> <code>50DB7880A0C290F6F55FE00E34A40616</code> <code>1150151B1967EBD4896933BD40BA9363</code> <code>6F5C9AC89E98CE8B948812B6BBABAF5A</code> <code>BAF3E2C1C67D22DE739F852D578A98A0</code> <code>E23F6362EAC4709764E6F4C7EEFAA0FE</code> <code>3580F5D609E06CDC23B011BEF6D49637</code> <code>4EB37BA44B4BDAAED57A25CDD48B59B1</code> <code>9CDFA328660D58186DC45C3450DA3FD7</code> <code>DFAE686CDA17744DA85A885C03D084F6</code> <code>07520B9A6E50B97F658DE0AA1CA39291</code> <code>B66D3600D880036D6BD09830F05768BB</code> <code>0923FCCA119128B88C1A448145133791</code> <code>5FFAF4905978E04CC7EE7B4C7F7A48BD</code><br> <code>61B04E44</code></td>
<td><code>FE500100B160815FF0457D0DBE5DE90D</code> <code>3575167CE1E4EDA690D0FD89C06FCF56</code> <code>2B563D04D919EBAF11A8FEDA02C5A4B9</code> <code>D745F14285AA770C7DE5E6FAC936CA99</code> <code>6DC7EE537BB8994CB39700A41F30CAF1</code> <code>6EC4CD5BD62F00AB3D25254241F84FEF</code> <code>1E341F4F758A348AE7A73EA6BA32132C</code> <code>6463BB3FC3D9808D5EF4E69B2476EA12</code> <code>7A0EF0D001B9D29672FF9FB82F0EDDCB</code> <code>FAB52DC3424AB7CD62D0894DA435A87A</code> <code>4FD5F913698E0A7EF8E5A9D0DD45B2D0</code> <code>3D9B571B7DFACDF699AA4F1237BB268F</code> <code>7F45403A2F6679B97C2AC91A1A57E51E</code> <code>C59ADAF9E99D4FB6C6406C7DE9E825BA</code> <code>61EEC8CD7AC294C01FC2191518CEF8CD</code> <code>D9F882DF350375045AB6B50774CC4221</code> <code>0E73128FDE86F73BB47D19B59B27C163</code> <code>97EC02A173869238711DAE83ECE806DF</code> <code>55521DBCF7A21E63240D732C46A604F9</code> <code>D4305DE25934A87B356681E3ACA961C3</code> <code>FDB86A1DF7F57428BC2420400679676A</code><br> <code>F5F78D5B</code></td>
<td>Encrypted client_DH_inner_data generated previously, serialized as a TL byte string</td>
</tr>
</tbody>
@ -785,17 +785,17 @@ encrypted_data := AES256_ige_encrypt (data_with_hash, tmp_aes_key, tmp_aes_iv);<
<h5><a class="anchor" href="#8-auth-key-generation" id="8-auth-key-generation" name="8-auth-key-generation"><i class="anchor-icon"></i></a>8) Auth key generation</h5>
<p>The client computes the auth_key using formula <code>g_a^b mod dh_prime</code>:</p>
<!-- start auth_key -->
<pre><code>auth_key = 74C1BCCC199791B64A8A55CA88337D2072B99630263D6D8B84CD192860D90F764C4FC4782DA33326611B7606EB60A82552AEED09FBDA4EAF44FA57D36B22C1085110BCAB8FB0C6582E883E90A60F0CE02B4F249BC76CEBA166BA109AC35CC8317702460F4C64AEA5555963D660FBDEFACF415F08064D149DA32E0406CAC149B1D4B02F544966552D2BD5DAC78B946DEABBA890363350868AA4AF8EE572A8430616B5B977B9E5E79C1139EE0C3902D6533C5446853AA14DCB85C2FBD7BAA5FCD9FD2ED7F203935426BF6831B06C950B404016C430904F18D74A56E8CF3AA8C86E5A69E5429BB314F7A12C485D643A03F48759E4DEC722C1C6EFD698710E6B8003</code></pre>
<pre><code>auth_key = 280720C2FC3DC490C5B479DE91A990CC98C1C8A464C1E9BDF86066EA86A3874FED3F4D7595AB4C8BC1DBC7D51A4B8EA706218862C1EADE6E91A6FA4328B3B2C60915A695951BA1FE2858EDD9D504182D530262E1C0150BDA84529912CAD1A4C59CFA5D92B87C965C6FD15B04588DBB16AE509AFAF51ED2CE0FFED59011B84F42C568A4AF9C051F14ED4A758ECF79878135EFCF1BC9BC28CCBC354F07FA57FEE55E924C49FF2EF6BB3A639C2019CBB5F11EA056048623A5C50E866DFCF5C89A1863CC49E8F4E331FE60AA4B4775B2468EF497D0A26B20E765DD6B8B7C7FCA1422A5EE1A057D6340E117C64C1BC66F22ADBBCF58EF482C3BAF5503F4A5A1B3586C</code></pre>
<!-- end auth_key -->
<h5><a class="anchor" href="#9-final-server-reply" id="9-final-server-reply" name="9-final-server-reply"><i class="anchor-icon"></i></a>9) Final server reply</h5>
<p>The server verifies and confirms that auth_key_hash is unique: since it's unique, it replies with the following:</p>
<!-- start dh_gen_ok -->
<p>Received payload (excluding transport headers/trailers):</p>
<pre><code>0000 | 00 00 00 00 00 00 00 00 01 08 02 06 8B 0C EB 65
0010 | A4 00 00 00 34 F7 CB 3B 6C 5D 01 83 C0 9B 3D 4C
0020 | 65 0C 7A 02 E4 D8 BD F8 F3 9F 03 F1 56 5D 6D 00
0030 | 28 51 C6 FC AC 8A CD 0D A0 0A 66 F3 13 69 78 A2
0040 | 68 1E ED 6D E8 21 EF 13</code></pre>
<pre><code>0000 | 00 00 00 00 00 00 00 00 01 30 1B 64 DE 75 64 66
0010 | 68 00 00 00 34 F7 CB 3B 0B FE 9D 6B 3D 0A 6B E1
0020 | 37 49 41 41 F3 9D 2D 23 87 BB 22 11 92 61 99 C9
0030 | 9D 85 2A 84 B6 1A 13 B5 BC 53 F0 C6 09 54 4B D6
0040 | 67 66 8A D6 A4 0B 76 E9</code></pre>
<p>Payload (de)serialization:</p>
<pre><code>dh_gen_ok#3bcbf734 nonce:int128 server_nonce:int128 new_nonce_hash1:int128 = Set_client_DH_params_answer;</code></pre>
<table class="table">
@ -817,13 +817,13 @@ encrypted_data := AES256_ige_encrypt (data_with_hash, tmp_aes_key, tmp_aes_iv);<
<tr>
<td>message_id</td>
<td>8, 8</td>
<td><code>010802068B0CEB65</code></td>
<td><code>01301B64DE756466</code></td>
<td>Message ID generated as specified <a href="/mtproto/description#message-identifier-msg-id">here »</a> (unixtime() &lt;&lt; 32) + (N*4)</td>
</tr>
<tr>
<td>message_length</td>
<td>16, 4</td>
<td><code>A4000000</code> (164 in decimal)</td>
<td><code>68000000</code> (104 in decimal)</td>
<td>Message body length</td>
</tr>
<tr>
@ -835,19 +835,19 @@ encrypted_data := AES256_ige_encrypt (data_with_hash, tmp_aes_key, tmp_aes_iv);<
<tr>
<td>nonce</td>
<td>24, 16</td>
<td><code>6C5D0183C09B3D4C650C7A02E4D8BDF8</code></td>
<td><code>0BFE9D6B3D0A6BE137494141F39D2D23</code></td>
<td>Value generated by client in Step 1</td>
</tr>
<tr>
<td>server_nonce</td>
<td>40, 16</td>
<td><code>F39F03F1565D6D002851C6FCAC8ACD0D</code></td>
<td><code>87BB2211926199C99D852A84B61A13B5</code></td>
<td>Value received from server in Step 2</td>
</tr>
<tr>
<td>new_nonce_hash1</td>
<td>56, 16</td>
<td><code>A00A66F3136978A2681EED6DE821EF13</code></td>
<td><code>BC53F0C609544BD667668AD6A40B76E9</code></td>
<td>The 128 lower-order bits of SHA1 of the byte string derived from the <code>new_nonce</code> string by adding a single byte with the value of 1, 2, or 3, and followed by another 8 bytes with <code>auth_key_aux_hash</code>. Different values are required to prevent an intruder from changing server response dh_gen_ok into dh_gen_retry.</td>
</tr>
</tbody>