curl --request POST \
--url https://api.example.com/v1/account/auth/telegram \
--header 'Content-Type: application/json' \
--data '
{
"id": 123,
"auth_date": 123,
"hash": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"username": "<string>",
"photo_url": "<string>"
}
'import requests
url = "https://api.example.com/v1/account/auth/telegram"
payload = {
"id": 123,
"auth_date": 123,
"hash": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"username": "<string>",
"photo_url": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
id: 123,
auth_date: 123,
hash: '<string>',
first_name: '<string>',
last_name: '<string>',
username: '<string>',
photo_url: '<string>'
})
};
fetch('https://api.example.com/v1/account/auth/telegram', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/account/auth/telegram",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'id' => 123,
'auth_date' => 123,
'hash' => '<string>',
'first_name' => '<string>',
'last_name' => '<string>',
'username' => '<string>',
'photo_url' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/account/auth/telegram"
payload := strings.NewReader("{\n \"id\": 123,\n \"auth_date\": 123,\n \"hash\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"username\": \"<string>\",\n \"photo_url\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v1/account/auth/telegram")
.header("Content-Type", "application/json")
.body("{\n \"id\": 123,\n \"auth_date\": 123,\n \"hash\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"username\": \"<string>\",\n \"photo_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/account/auth/telegram")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"id\": 123,\n \"auth_date\": 123,\n \"hash\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"username\": \"<string>\",\n \"photo_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"customer": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"locale": "ru",
"timezone": "<string>",
"status": "active"
},
"expiresAt": "2023-11-07T05:31:56Z"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"request_id": "<string>"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"request_id": "<string>"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"request_id": "<string>"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"request_id": "<string>"
}Post v1accountauthtelegram
Verifies a Telegram Login Widget payload. The hash is checked against the bot token and the auth_date must be recent, so a captured payload cannot be replayed indefinitely. The body is the object the widget hands to its data-onauth callback, posted as is: id and auth_date are JSON numbers, the other fields strings. Like every session-opening POST under /v1/account/auth, it requires Content-Type application/json and refuses a request a browser marks as cross-site (403 cross_origin_request), so a third-party page cannot sign a visitor into another account.
curl --request POST \
--url https://api.example.com/v1/account/auth/telegram \
--header 'Content-Type: application/json' \
--data '
{
"id": 123,
"auth_date": 123,
"hash": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"username": "<string>",
"photo_url": "<string>"
}
'import requests
url = "https://api.example.com/v1/account/auth/telegram"
payload = {
"id": 123,
"auth_date": 123,
"hash": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"username": "<string>",
"photo_url": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
id: 123,
auth_date: 123,
hash: '<string>',
first_name: '<string>',
last_name: '<string>',
username: '<string>',
photo_url: '<string>'
})
};
fetch('https://api.example.com/v1/account/auth/telegram', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/account/auth/telegram",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'id' => 123,
'auth_date' => 123,
'hash' => '<string>',
'first_name' => '<string>',
'last_name' => '<string>',
'username' => '<string>',
'photo_url' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/account/auth/telegram"
payload := strings.NewReader("{\n \"id\": 123,\n \"auth_date\": 123,\n \"hash\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"username\": \"<string>\",\n \"photo_url\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v1/account/auth/telegram")
.header("Content-Type", "application/json")
.body("{\n \"id\": 123,\n \"auth_date\": 123,\n \"hash\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"username\": \"<string>\",\n \"photo_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/account/auth/telegram")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"id\": 123,\n \"auth_date\": 123,\n \"hash\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"username\": \"<string>\",\n \"photo_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"customer": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"locale": "ru",
"timezone": "<string>",
"status": "active"
},
"expiresAt": "2023-11-07T05:31:56Z"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"request_id": "<string>"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"request_id": "<string>"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"request_id": "<string>"
}{
"type": "<string>",
"title": "<string>",
"status": 123,
"detail": "<string>",
"request_id": "<string>"
}Body
The document Telegram's Login Widget produces. Every field except hash participates in the signature in its textual form, so the server keeps the digits of the numeric fields verbatim rather than parsing them as floating point.