gfn / telegram-php-sdk
A PHP SDK for the Telegram-API.
Requires
- php: >=8.4
- ext-json: *
- guzzlehttp/guzzle: ^7.12.0
- mlocati/ip-lib: ^1.22.0
Requires (Dev)
- phpunit/phpunit: ^13.2.0
This package is auto-updated.
Last update: 2026-07-20 16:55:26 UTC
README
An SDK written in PHP to communicate with the Telegram Bot API.
Last supported Bot API Version: 10.2 (2026-07-14)
All useful Information to Telegram Bots can you find on the official Website.
This is only an SDK, not a Bot itself.
Disclaimer
This project and its author are neither associated nor affiliated with Telegram in any way.
Data Protection / GDPR (DSGVO)
Telegram is an external third-party service. Any application built on this SDK transmits data to Telegram's infrastructure whenever it sends or receives messages — this SDK itself does not collect, store, or process personal data beyond what is required to make a single API call.
What may be transmitted, depending on which methods you use: chat and user identifiers,
message text and captions, uploaded media (photos, documents, voice notes, etc.), contact and
location data, and any other content you pass to a request class. On the incoming side, every
webhook payload Telegram sends you may contain personal data about the sender (name, username,
language, etc. — see User).
You, the developer integrating this SDK, are the data controller for your bot. Using this SDK does not by itself make you GDPR/DSGVO-compliant — you remain responsible for:
- having a lawful basis (Art. 6 GDPR) for processing the personal data your bot handles,
- informing end users how their data is processed (transparency, Art. 13/14 GDPR),
- the fact that Telegram may process and store data outside your own infrastructure, potentially involving a transfer to a third country — review Telegram's Privacy Policy and, where applicable, put a data-processing agreement in place with Telegram,
- not logging or persisting personal data (message content, user identifiers, bot tokens) beyond what your own lawful basis and retention policy permit.
This section is guidance, not legal advice — consult your own data-protection counsel for your specific use case.
License
This project is released under the MIT License.
Requirements
- PHP >= 8.4
Installation
The easiest way is the installation via Composer: composer require gfn/telegram-php-sdk
Alternatively you can add this GIT-Repository to your composer.json:
{
"repositories": [
{
"type": "git",
"url": "https://gitlab.german-furs.net/german-furs/telegram-php-sdk.git",
"no-api": true
}
]
}
Usage
First you need to create a bot via BotFather and authorize it. Save the token and hold it save.
All classes have links to the original documentation. If you are not sure how to use the class, check out the documentation.
Using this SDK with AI agents
If you are an AI agent (or a developer directing one) integrating this SDK into a bot, read docs/AGENT_USAGE.md first — it documents the request/response pattern, webhook handling, polymorphic types, and error handling in detail. For the exact, current set of available Types and Request classes, see the local mirror of the official documentation at docs/api-reference/, which is kept in sync with this SDK's implementation (see CLAUDE.md for the governance rules this project follows).
Examples requests outgoing
getMe
With the getMe method, you can request all information about your bot.
$bot_token = 'xxx';
$get_me = new \GfnTelegramPhpSdk\Core\Request\GetMe();
try {
$get_me->execute($bot_token)
var_dump($get_me->getResponse());
} catch (\GfnTelegramPhpSdk\Exception\GfnTelegramPhpSdkException $e) {
var_dump($e);
}
sendMessage
With the sendMessage method, you can send a message to a user or chat.
$bot_token = 'xxx';
$chat_id = 000;
$sm = new SendMessage();
$sm->chat_id = $chat_id;
$sm->text = 'Test Message';
// Example with inline buttons.
// Buttons One & Two are on line 1, Button Three is on line 2.
// Each InlineKeyboardButton needs a purpose, so I used the callback_data.
$button_one_data = [
'text' => 'Button One',
'callback_data' => 'callback_one'
];
$button_two_data = [
'text' => 'Button Two',
'callback_data' => 'callback_two'
];
$button_three_data = [
'text' => 'Button Three',
'callback_data' => 'callback_three'
];
$inline_keyboard_markup = new \GfnTelegramPhpSdk\Core\Type\InlineKeyboardMarkup(['inline_keyboard' => [[$button_one_data, $button_two_data],[$button_three_data]]]);
$sm->reply_markup = $inline_keyboard_markup;
try {
$sm->execute($bot_token)
var_dump($sm->getResponse());
} catch (\GfnTelegramPhpSdk\Exception\GfnTelegramPhpSdkException $e) {
var_dump($e);
}
File Upload
To send files to users or chats, use the respective methods with file paths or file IDs.
Sending Documents
Use sendDocument to send general files like ZIP archives, PDFs, etc.
$bot_token = 'xxx';
$chat_id = 000;
// Send a ZIP file from local file system
$sd = new \GfnTelegramPhpSdk\Core\Request\SendDocument();
$sd->chat_id = $chat_id;
$sd->document = new \CURLFile('/path/to/archive.zip', 'application/zip', 'archive.zip');
$sd->caption = 'Here is your archive';
try {
$sd->execute($bot_token);
var_dump($sd->getResponse());
} catch (\GfnTelegramPhpSdk\Exception\GfnTelegramPhpSdkException $e) {
var_dump($e);
}
// Alternatively, use a file_id from a previously uploaded file
$sd->document = 'BQACAgIAAxkBAAI...'; // file_id from previous upload
Sending Photos
Use sendPhoto to send images.
$bot_token = 'xxx';
$chat_id = 000;
// Send a photo from local file system
$sp = new \GfnTelegramPhpSdk\Core\Request\SendPhoto();
$sp->chat_id = $chat_id;
$sp->photo = new \CURLFile('/path/to/photo.jpg', 'image/jpeg', 'photo.jpg');
$sp->caption = 'This is a photo';
try {
$sp->execute($bot_token);
var_dump($sp->getResponse());
} catch (\GfnTelegramPhpSdk\Exception\GfnTelegramPhpSdkException $e) {
var_dump($e);
}
// Alternatively, use a file_id from a previously uploaded file
$sp->photo = 'AgACAgIAAxkBAAI...'; // file_id from previous upload
Rich Messages
Bot API 10.1 introduces Rich Messages — highly structured, formatted content (headings, lists, tables, block quotes, media blocks, LaTeX, maps, collages and more).
To send a rich message, build an InputRichMessage from Rich Markdown or Rich HTML (exactly one of both) and pass it to sendRichMessage.
$bot_token = 'xxx';
$chat_id = 000;
// Build the content from Rich Markdown (or use the html: parameter instead)
$input_rich_message = new \GfnTelegramPhpSdk\Core\Type\InputRichMessage(
markdown: "# Title\n\nSome **bold** and *italic* text with a [link](https://telegram.org)."
);
$srm = new \GfnTelegramPhpSdk\Core\Request\SendRichMessage();
$srm->chat_id = $chat_id;
$srm->rich_message = $input_rich_message;
try {
$srm->execute($bot_token);
var_dump($srm->getResponse());
} catch (\GfnTelegramPhpSdk\Exception\GfnTelegramPhpSdkException $e) {
var_dump($e);
}
You can stream a partial message while it is being generated (e.g. for AI-generated replies) with sendRichMessageDraft. The draft is ephemeral (a 30-second preview); call sendRichMessage with the complete message afterwards to persist it.
A received rich message is available on the Message object via $message->rich_message (a RichMessage holding an array of RichBlock elements).
Examples requests incoming
All incoming traffic is checked. If the request does not come from the Telegram network, it will be ignored.
It's important to send a reply in all possible cases, even if Telegram doesn't process it. It's only correct if you receive a response to your request.
If you do not send code 200 as a reply, Telegram will consider this a failed communication attempt and try to send the message again later.
// Cancel the request if it does not come from the Telegram network or is invalid
try {
if (!Update::isValidRequest()) {
header('Content-Type: application/json');
echo '{"success":false,"status":403}';
exit;
}
} catch (\GfnTelegramPhpSdk\Exception\GfnTelegramPhpSdkException) {
header('Content-Type: application/json');
echo '{"success":false,"status":400}';
exit;
}
$request_class_name = Update::getRequestType();
$type_name = Update::getRequestName();
// Unknown type of request
if (empty($request_class_name) || empty($type_name)) {
header('Content-Type: application/json');
echo '{"success":false,"status":404}';
exit;
}
try {
$request_class = new $request_class_name(Update::getRequestDecoded()[$type_name]);
if ($request_class instanceof GfnTelegramPhpSdk\Core\Type\BotSubscriptionUpdated) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\BusinessConnection) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\BusinessMessagesDeleted) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\CallbackQuery) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\ChatBoostRemoved) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\ChatBoostUpdated) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\ChatJoinRequest) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\ChatMemberUpdated) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\ChosenInlineResult) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\InlineQuery) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\ManagedBotUpdated) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\Message) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\MessageReactionCountUpdated) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\MessageReactionUpdated) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\PaidMediaPurchased) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\Poll) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\PollAnswer) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\PreCheckoutQuery) {
// do code
} elseif ($request_class instanceof GfnTelegramPhpSdk\Core\Type\ShippingQuery) {
// do code
} else {
header('Content-Type: application/json');
echo '{"success":false,"status":404}';
exit;
}
} catch (\GfnTelegramPhpSdk\Exception\GfnTelegramPhpSdkException $e) {
header('Content-Type: application/json');
echo '{"success":false,"status":400}';
exit;
}
// Request was successful
header('Content-Type: application/json');
echo '{"success":true,"status":200}';