Getting started

Introduction

Practical Introduction to the Telegram Bot API Guide for PHP Developers: Environment Check, Minimal getMe Request, JSON Response Analysis, and All Sections Map.

Official Telegram Bot API documentation is accurate, but "dry": many methods and few practical scenarios. This guide is a practical layer over core.telegram.org/bots/api: from first getMe to webhook, inline buttons, Mini Apps and battle-tested projects on PHP.

For whom is this section

  • PHP developers (plain PHP, Yii2, Laravel);
  • Mini Apps frontend developers (React / Vue);
  • Those who have already read the official docs and want working patterns: idempotency, secret_token, queues, initData validation.

Business cases and "why a salon bot" remain at блоге. Here — only technique.

Environment check before starting

Make sure PHP sees cURL and can reach api.telegram.org. Run in the terminal:

php -m | grep curl
curl -I https://api.telegram.org

Expected output: curl in the list of modules and HTTP/2 200 (or 301/302) from Telegram. If cURL is missing — apt-get install php-curl / brew install php / enable the extension in php.ini.

Minimal "Hello API" on PHP

Immediately after receiving the token from @BotFather (see следующую главу) verify that the bot is alive. Below is a one-off script without frameworks; in главе про HTTP-клиент we will move it into a reusable function telegramApi().

<?php
// test-token.php — запуск: php test-token.php
$token = getenv('TELEGRAM_BOT_TOKEN');
if (!$token) {
fwrite(STDERR, "TELEGRAM_BOT_TOKEN не задан в окружении\n");
exit(1);
}

$url = "https://api.telegram.org/bot{$token}/getMe";
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => ['Accept: application/json'],
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlErrno = curl_errno($ch);
$curlError = curl_error($ch);
curl_close($ch);

if ($curlErrno) {
fwrite(STDERR, "cURL error {$curlErrno}: {$curlError}\n");
exit(1);
}
if ($httpCode !== 200) {
fwrite(STDERR, "HTTP {$httpCode}: {$response}\n");
exit(1);
}

$data = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
fwrite(STDERR, "Invalid JSON: " . json_last_error_msg() . "\n");
exit(1);
}

if (!($data['ok'] ?? false)) {
fwrite(STDERR, "API error: " . json_encode($data, JSON_UNESCAPED_UNICODE) . "\n");
exit(1);
}

$bot = $data['result'];
echo "OK: @{$bot['username']} (id={$bot['id']}, name={$bot['first_name']})\n";

What Telegram returns — JSON breakdown

On a successful request getMe you get such a response:

{
"ok": true,
"result": {
"id": 123456789,
"is_bot": true,
"first_name": "My Cool Bot",
"username": "mycoolbot",
"can_join_groups": true,
"can_read_all_group_messages": false,
"supports_inline_queries": false,
"can_connect_to_business": false,
"has_main_web_app": false
}
}
  • ok — true means success at the API level. If false — see error_code and description (e.g., 401 Unauthorized — invalid token).
  • result — the object User of the bot. Fields id and username will be needed for deep-linking and checking incoming updates.
  • can_read_all_group_messages — false by default. To make the bot see all messages in a group, disable Privacy Mode in @BotFather → Bot Settings → Group Privacy → Disable.

How to view the result in the terminal

Run the script:

TELEGRAM_BOT_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11 php test-token.php
# OK: @mycoolbot (id=123456789, name=My Cool Bot)

If the token is invalid — you will see:

API error: {"ok":false,"error_code":401,"description":"Unauthorized"}

For debugging complex responses use json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) — then the structure reads instantly.

Guide map (briefly)

Next: Bot API vs MTProto — why bots almost always need the Bot API itself.

"}