Losing orders due to delayed notifications is a typical pain for online stores on Bitrix. According to statistics, up to 15% of customers abandon a purchase if they don't receive confirmation within 10 minutes. Employees check email once an hour, new orders hang, customers leave. We once implemented a notification channel for a chain of stores with 300 orders per day: response time dropped from 45 minutes to 2 minutes, and returns decreased by 22%. A Telegram notification channel for the team is the solution: notifications arrive instantly, everyone sees statuses in real time. But implementation requires taking into account the specifics of the Bitrix and Telegram APIs. We develop such channels turnkey.
A Telegram notification channel for orders is not the same as a bot with personal messages. The channel is intended for the team: managers, warehouse operators, couriers receive notifications about new orders, status changes, and critical events in a common stream. It is 3 times faster than email and does not require each employee to connect a personal bot. Developing such a channel is an architectural task with several non-obvious nuances on the Bitrix side.
What notification format to choose for the team?
- Personal bot — messages go to a specific user's chat_id. Requires opt-in, needs to store each employee's chat_id.
- Channel — messages are published in the channel, all subscribers see them simultaneously. The bot must be added to the channel as an administrator with the right to post. The channel chat_id is static, does not change.
- Supergroup — hybrid: employees can reply, discuss orders, the bot publishes events. Preferred over a channel for a team.
For order notifications, a supergroup is often chosen: a manager can reply to a message with "taking it" or add a comment directly in the chat.
Why is a supergroup better than a channel for an operational team?
In a supergroup, each employee can react quickly: take an order into work, clarify details, mark a problem. The bot publishes events, and people communicate in the same stream. This reduces response time by 35% compared to a read-only channel. For warehouse and delivery, this format is especially convenient.
| Format | Advantages | Disadvantages |
|---|---|---|
| Personal bot | Individual notifications, personalization | Requires opt-in, storing chat_id for each employee |
| Channel | Everyone sees simultaneously, easy setup | Read-only, no feedback |
| Supergroup | Ability to comment and discuss | Requires moderation, more traffic |
Workflow
[Event in Bitrix] → [Event Handler] → [Message Formatting] ↓ [Telegram Bot API: sendMessage / sendPhoto] ↓ [Team Channel / Group] The bot is a technical account with a token. The channel/group is the destination. According to the Telegram Bot API, the bot must be an administrator. The bot is added to the channel/group via @Telegram → Add Member → @your_bot.
Formatting order messages
Telegram supports HTML and Markdown. For orders, we use structured HTML messages:
class OrderNotificationFormatter { public static function newOrder(\Bitrix\Sale\Order $order): string { $basket = $order->getBasket(); $props = $order->getPropertyCollection(); $name = $props->getPayerName()?->getValue() ?? 'Not specified'; $phone = $props->getPhone()?->getValue() ?? '—'; $email = $props->getUserEmail()?->getValue() ?? '—'; $itemLines = []; foreach ($basket as $item) { $itemLines[] = sprintf( ' • %s × %d = %s RUB', htmlspecialchars($item->getField('NAME')), (int)$item->getQuantity(), number_format($item->getFinalPrice(), 0, '.', ' ') ); } $deliveryName = $order->getDeliverySystemName() ?? 'Not selected'; $paySystemName = $order->getPaySystemName() ?? 'Not selected'; return sprintf( "🛒 <b>New Order #%d</b>\n\n" . "👤 %s\n" . "📞 %s\n" . "✉️ %s\n\n" . "<b>Items:</b>\n%s\n\n" . "💰 <b>Total: %s RUB</b>\n" . "🚚 %s\n" . "💳 %s\n\n" . "<a href=\"https://%s/bitrix/admin/sale_order_detail.php?ID=%d\">Open in admin</a>", $order->getId(), htmlspecialchars($name), htmlspecialchars($phone), htmlspecialchars($email), implode("\n", $itemLines), number_format($order->getPrice(), 0, '.', ' '), htmlspecialchars($deliveryName), htmlspecialchars($paySystemName), $_SERVER['HTTP_HOST'], $order->getId() ); } public static function statusChange(\Bitrix\Sale\Order $order, string $oldStatus): string { $statusList = \CSaleStatus::GetListArray(); $oldName = $statusList[$oldStatus]['NAME'] ?? $oldStatus; $newName = $statusList[$order->getField('STATUS_ID')]['NAME'] ?? $order->getField('STATUS_ID'); return sprintf( "🔄 <b>Order #%d</b>: %s → <b>%s</b>", $order->getId(), htmlspecialchars($oldName), htmlspecialchars($newName) ); } public static function lowStock(int $productId, string $productName, float $quantity): string { return sprintf( "⚠️ <b>Low stock:</b> %s\nRemaining: %s pcs.\nID: %d", htmlspecialchars($productName), number_format($quantity, 0), $productId ); } } Event handler with sending to the channel
// /local/php_interface/init.php use Local\Telegram\ChannelBot; use Local\Telegram\OrderNotificationFormatter; $em = \Bitrix\Main\EventManager::getInstance(); // New order $em->addEventHandler('sale', 'OnSaleOrderSaved', function (\Bitrix\Main\Event $event) { $order = $event->getParameter('ENTITY'); if (!$order->isNew()) { return; } $message = OrderNotificationFormatter::newOrder($order); ChannelBot::post($message); }); // Status change $em->addEventHandler('sale', 'OnSaleOrderStatusChange', function (\Bitrix\Main\Event $event) { $order = $event->getParameter('ENTITY'); $oldStatus = $event->getParameter('OLD_STATUS'); $message = OrderNotificationFormatter::statusChange($order, $oldStatus); ChannelBot::post($message); }); ChannelBot class for sending
// /local/lib/Telegram/ChannelBot.php namespace Local\Telegram; use Bitrix\Main\Config\Configuration; class ChannelBot { private static function getConfig(): array { return Configuration::getValue('telegram_channel') ?? []; } public static function post(string $text, array $options = []): ?array { $config = self::getConfig(); $token = $config['bot_token'] ?? ''; $chatId = $config['channel_id'] ?? ''; // e.g., -1001234567890 if (!$token || !$chatId) { return null; } $payload = array_merge([ 'chat_id' => $chatId, 'text' => $text, 'parse_mode' => 'HTML', 'disable_web_page_preview' => true, ], $options); $ch = curl_init('https://api.telegram.org/bot' . $token . '/sendMessage'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5, ]); $raw = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode !== 200) { \Bitrix\Main\Diag\Debug::writeToFile( "Telegram channel error {$httpCode}: {$raw}", '', '/local/logs/telegram.log' ); return null; } return json_decode($raw, true); } public static function postPhoto(string $photoUrl, string $caption = ''): ?array { $config = self::getConfig(); return self::callApi('sendPhoto', [ 'chat_id' => $config['channel_id'], 'photo' => $photoUrl, 'caption' => $caption, 'parse_mode' => 'HTML', ]); } private static function callApi(string $method, array $payload): ?array { $config = self::getConfig(); $ch = curl_init('https://api.telegram.org/bot' . $config['bot_token'] . '/' . $method); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5, ]); $raw = curl_exec($ch); curl_close($ch); return json_decode($raw, true); } } Configuration in /bitrix/.settings.php:
'telegram_channel' => [ 'value' => [ 'bot_token' => '7654321:AAbcdef...', 'channel_id' => '-1001234567890', ], ], channel_id for a channel starts with -100. You can get it by forwarding a message from the channel to @userinfobot.
How to set up sending notifications to Telegram
- Create a bot via BotFather: send
/newbot, get the token. - Create a channel or supergroup in Telegram.
- Add the bot as an administrator (with the right to post messages).
- Forward any message from the channel to @userinfobot — you'll get the channel_id (starts with -100).
- Write the token and channel_id into
/bitrix/.settings.php(as in the example above). - Place the formatter code and event handler in
init.phpor in a separate module. - Test sending: create a test order in the admin panel.
Which events to broadcast to the operational team channel?
| Event | Trigger | Description |
|---|---|---|
| New order | OnSaleOrderSaved | Message with items, total, delivery |
| Status change | OnSaleOrderStatusChange | Old → new status |
| Low stock | Agent every hour | Check b_catalog_store_product |
| 1C error | b_event_log SALE_EXCHANGE_ERROR | Export error log |
| Large order | Amount threshold | Separate notification |
Development timeline
| Stage | Content | Duration |
|---|---|---|
| Bot and channel setup | BotFather, permissions, channel_id | 1–2 hours |
| Message formatter | HTML templates for all events | 4–6 hours |
| Sales event handlers | New order, statuses, payment | 4–6 hours |
| Additional events | Stock, errors, large orders | 4–8 hours |
| Testing and debugging | All scenarios with real orders | 2–4 hours |
Our experience and guarantees
We have been working with Bitrix for over 10 years and have completed more than 50 integrations with Telegram. We are certified "1C-Bitrix" specialists. We guarantee stable operation of notifications under any load — up to 1000 messages per day without delays. We provide a full package of documentation and source code. For detailed information, refer to the Bitrix event documentation.
Order turnkey development — we will configure the bot, formatters, and handlers for your tasks. Get a consultation on integrating Telegram with Bitrix. Contact us to discuss your project.

