Telegram Mini App Development with Bitrix24 Integration

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Showing 1 of 1All 1626 services
Telegram Mini App Development with Bitrix24 Integration
Medium
~1-2 weeks
Frequently Asked Questions

Our competencies:

Development stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1356
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Website development for FIXPER company
    943
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    693
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    828
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    731
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    1073

Telegram Mini App Development with Bitrix24 Integration

A manager in the field opens Telegram, sees a lead, and moves it to the next status in 30 seconds. Instead of 5 minutes searching in a browser. This is a typical scenario we cover with a Telegram Mini App + Bitrix24 REST API combination. The Mini App works as a CRM dashboard right in the chat: deal list, stages, contact info, ability to comment. We develop turnkey with full OAuth routing, token storage, and webhook configuration.

Problems the Integration Solves

Authorization without a browser. The Bitrix24 REST API requires an OAuth access_token, but a Mini App is a web page in Telegram WebView where redirect is impossible. The solution is a mediator server that validates the Telegram initData and issues an OAuth link or a ready-made token. We've applied this approach in 15+ projects.

Delays in lead processing. Managers spend up to 5 minutes opening a browser, logging into the CRM, and searching for a card. The Mini App reduces this to 30 seconds: the employee sees the lead immediately and changes the status with one tap. According to our measurements, the speed of reaction to an incoming lead increases by 60–70% — the Telegram Mini App processes leads 3 times faster than through the web interface.

Real-time notifications. Without integration, a manager learns about a new deal via email digests with minutes of delay. Bitrix24 event webhooks send a POST request to the server, which then sends a message to Telegram. The notification arrives in 1–2 seconds.

Use Cases

Scenario Description Target Audience
Mobile CRM Dashboard View leads and deals, change status, add comments Field managers, sales departments
Corporate Ordering Place requests by dealers/agents via Mini App Network companies, distributors
Self-Service Portal Client sees request status and communication history B2C services, tech support
Task Manager Task list, status change, file attachment Teams using Bitrix24

Architecture: OAuth and Server Proxy

Authorization process:

  1. User opens the Mini App. The frontend sends initData to the server.
  2. Server validates initData hash, extracts user_id, and looks up a record in the tg_bx24_tokens table.
  3. If a token is found and not expired — returns a JWT for the Mini App. If not — returns an OAuth authorization link for Bitrix24.
  4. After confirmation, the server exchanges the code for an access_token and saves it linked to the Telegram user_id.
Step Action Participant
1 Open Mini App, send initData User -> Mini App
2 Validate initData, search for token Server
3 Return JWT or OAuth link Server -> Mini App
4 Confirm OAuth (if needed) User -> Bitrix24
5 Exchange code for token, save Server

The OAuth callback handling code is standard for all our integrations:

class Bx24OAuthController
{
    public function callback(Request $request): Response
    {
        $code     = $request->get('code');
        $tgUserId = $request->session()->get('pending_tg_user_id');

        $tokenData = $this->exchangeCode($code);

        \Local\TgBx24\TokenStorage::save($tgUserId, [
            'access_token'  => $tokenData['access_token'],
            'refresh_token' => $tokenData['refresh_token'],
            'expires_at'    => time() + $tokenData['expires_in'],
            'domain'        => $tokenData['domain'],
            'user_id'       => $tokenData['user_id'],
        ]);

        $this->bot->sendMessage($tgUserId, 'Bitrix24 authorization successful.');

        return redirect('/auth/success');
    }

    private function exchangeCode(string $code): array
    {
        $response = Http::post('https://oauth.bitrix.info/oauth/token/', [
            'grant_type'    => 'authorization_code',
            'client_id'     => config('bx24.client_id'),
            'client_secret' => config('bx24.client_secret'),
            'code'          => $code,
        ]);

        return $response->json();
    }
}

Tokens are stored in a separate table or Redis. We use automatic refresh 5 minutes before expiration to ensure users don't lose access. All secrets are encrypted.

class TokenStorage
{
    private const TABLE = 'tg_bx24_tokens';

    public static function save(int $tgUserId, array $tokenData): void
    {
        $encrypted = \Local\Crypto::encrypt(json_encode($tokenData));

        \Bitrix\Main\Application::getConnection()->queryExecute(
            "INSERT INTO " . self::TABLE . " (tg_user_id, token_data, updated_at)
             VALUES (?, ?, NOW())
             ON DUPLICATE KEY UPDATE token_data = ?, updated_at = NOW()",
            [$tgUserId, $encrypted, $encrypted]
        );
    }

    public static function getValidToken(int $tgUserId): ?array
    {
        $result = \Bitrix\Main\Application::getConnection()->query(
            "SELECT token_data FROM " . self::TABLE . " WHERE tg_user_id = ?",
            [$tgUserId]
        );

        $row = $result->fetch();
        if (!$row) return null;

        $data = json_decode(\Local\Crypto::decrypt($row['token_data']), true);

        if ($data['expires_at'] < time() + 300) {
            $data = self::refreshToken($data);
        }

        return $data;
    }

    private static function refreshToken(array $data): array
    {
        $response = \Bitrix\Main\Web\HttpClient::post(
            'https://oauth.bitrix.info/oauth/token/',
            [
                'grant_type'    => 'refresh_token',
                'client_id'     => \Bitrix\Main\Config\Option::get('local.tg_bx24', 'client_id'),
                'client_secret' => \Bitrix\Main\Config\Option::get('local.tg_bx24', 'client_secret'),
                'refresh_token' => $data['refresh_token'],
            ]
        );

        return $newData;
    }
}

Why a Mediator Server?

A direct request from the Mini App to the Bitrix24 API is impossible due to CORS and the lack of secure token storage on the client. The mediator server acts as a cryptographic switch: all requests to the REST API go through it, tokens never leave the server. This is the security standard for OAuth in mobile applications.

Real-Time Data Exchange with Webhooks

Bitrix24 allows setting up event webhooks — for example, ONCRMDEALUPDATE. When an event triggers, Bitrix24 sends a POST to our server. The server identifies the responsible person (ASSIGNED_BY_ID), finds their Telegram user_id via the token table, and sends a message via sendMessage. Delay is no more than 2 seconds.

How automatic token refresh works We store tokens in the `tg_bx24_tokens` table with an `expires_at` field. 5 minutes before expiration, the server automatically requests a new token via refresh_token. If the refresh_token is also expired, the user is prompted to go through OAuth again. All secrets are encrypted.

React Mini App: Employee CRM Dashboard

The frontend is built with React using the Telegram WebApp SDK. This allows embedding the interface into a bot button and using native controls (e.g., haptic feedback).

import { useEffect, useState } from 'react';
const tg = window.Telegram.WebApp;

interface Deal {
    ID: string;
    TITLE: string;
    OPPORTUNITY: string;
    STAGE_ID: string;
    CONTACT_NAME: string;
}

function CrmDashboard() {
    const [deals, setDeals] = useState<Deal[]>([]);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        tg.ready();
        tg.expand();

        loadDeals();
    }, []);

    async function loadDeals() {
        const res = await fetch('/tg-api/crm/deals', {
            headers: { 'X-Tg-Init-Data': tg.initData },
        });
        const data = await res.json();
        setDeals(data.deals);
        setLoading(false);
    }

    async function updateStage(dealId: string, stageId: string) {
        await fetch(`/tg-api/crm/deals/${dealId}/stage`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
                'X-Tg-Init-Data': tg.initData,
            },
            body: JSON.stringify({ stage_id: stageId }),
        });
        tg.HapticFeedback.notificationOccurred('success');
        loadDeals();
    }

    // ... render
}

On the server, a proxy class encapsulates calls to the REST API. It automatically fetches the token from storage and handles authorization errors:

class CrmDealsProxy
{
    public function getDeals(int $tgUserId): array
    {
        $tokenData = TokenStorage::getValidToken($tgUserId);
        if (!$tokenData) {
            throw new \RuntimeException('Not authorized', 401);
        }

        $bx24 = new \Local\TgBx24\Bx24Client($tokenData['access_token'], $tokenData['domain']);

        $result = $bx24->call('crm.deal.list', [
            'filter' => ['ASSIGNED_BY_ID' => $tokenData['user_id'], 'CLOSED' => 'N'],
            'select' => ['ID', 'TITLE', 'OPPORTUNITY', 'STAGE_ID', 'CONTACT_ID'],
            'order'  => ['DATE_MODIFY' => 'DESC'],
            'start'  => 0,
        ]);

        return $result['result'] ?? [];
    }

    public function updateDealStage(int $tgUserId, int $dealId, string $stageId): bool
    {
        $tokenData = TokenStorage::getValidToken($tgUserId);
        $bx24      = new \Local\TgBx24\Bx24Client($tokenData['access_token'], $tokenData['domain']);

        $result = $bx24->call('crm.deal.update', [
            'id'     => $dealId,
            'fields' => ['STAGE_ID' => $stageId],
        ]);

        return !empty($result['result']);
    }
}

What's Included in the Work

  • Bitrix24 application registration (OAuth), Mini App setup in @BotFather
  • Mediator server: initData validation, OAuth token storage and renewal (PHP 8.1, MariaDB)
  • React Mini App for the chosen scenario (deal dashboard, requests, tasks)
  • REST proxy to Bitrix24 API with automatic token renewal
  • Bitrix24 event webhooks for Telegram notifications
  • User onboarding: account linking and test launch
  • Installation and support documentation

Process and Timelines

We follow a structured approach: data collection → audit/analysis → design → estimation → development → testing → launch.

  • MVP for one scenario: from 3 to 5 weeks
  • Full-featured application with multiple sections: from 8 to 14 weeks

Cost is determined individually after analyzing the technical specifications. We provide a 30-day guarantee on the integration's functionality. Experience: 10+ years, over 50 integrations with external services. Certified Bitrix developers.

Contact us for a consultation — we'll conduct a free audit of your CRM and propose an architecture that will reduce your sales team's reaction time.

Open Lines: Where It All Begins and Breaks

The Open Lines module (imopenlines) is the standard Bitrix24 mechanism for omnichannel communications. It connects an external channel to an internal chat via the Im\Model\ChatTable entity. The problem is that out-of-the-box routing settings are primitive: "in turn" or "all at once." For a real sales department with 15+ managers, VIP clients, and SLA response times, this is not enough. We enhance routing via event handlers OnImOpenLinesChatStart and the REST API.

A manager switching between five windows loses messages, forgets to reply—the client leaves for a competitor who responded in 30 seconds. Bitrix24 messenger configuration gathers all channels into one interface, and CRM records every touch. Experience shows that after setup, average first response time drops by 40% within the first week.

How we implement messenger integration

We connect Telegram, WhatsApp, Viber, VK, online chat, email, and other channels via standard connectors or REST API. Each channel requires its own configuration, but the result is unified—all messages end up in open lines, and from there into the client card. We guarantee no message gets lost: we use tagged caching and agents to check queues.

How to connect WhatsApp to Bitrix24?

WhatsApp is the main business channel. Integration via WhatsApp Business API with a verified account. We configure sending and receiving messages from the Bitrix24 interface—they fall into an open line. We create HSM templates for initiating dialog (abandoned cart reminders, order status). Templates go through Meta moderation—allow 2-3 days. We ensure file, image, and document transfer. We link conversations to contacts and deals via CRM_ENTITY_TYPE and CRM_ENTITY_ID.

Method Nuances Payment Model
WhatsApp Business API (Cloud) Verification via Meta Business, templates, bulk messaging Per conversation window (24h)
Provider (Edna, Wazzup, Chat2Desk) Quick start, intermediary service, own limits Subscription fee
Bitrix24 CRM Marketing Built-in integration, minimal setup Included in Professional+ tariff

Telegram: Free Channel with High Reach

Telegram Bot API is free and well-documented—a pleasant rarity among messengers. Integration into Bitrix24 is done via the imopenlines connector. Setup: connect the bot to open lines, configure the connector to Telegram. Receiving messages, photos, videos, documents—all mapped to the Bitrix24 chat. Inline buttons and reply keyboards for navigation. Webhook on https://yourdomain/rest/imconnector.register—register the connector. CRM integration: incoming message creates a lead via crm.lead.add or an activity in the deal.

Telegram is indispensable for:

  • Support via bot—standard questions resolved without an operator (up to 70% of inquiries).
  • Notifications: orders, delivery, payment—via Telegram Bot API sendMessage.
  • Lead collection: bot asks qualifying questions → creates a lead.

Viber and VK: Audience 35+ and Social Network

Viber maintains positions in regions. We connect a business account via the open lines connector. We use Viber Business Messages—bulk messaging with action buttons and rich content. Receiving and sending from CRM works immediately.

VK (Vkontakte) is the largest social network in Russia. Integration via the imopenlines community messages connector. Process messages and comments from a single interface. Auto-creation of a lead—handler OnImOpenLinesCrmCreate. Integration with VK Ads for tracking sources via UTM. Bot for auto-replies—VK Bot API + Callback API.

Why is proper routing of inquiries important?

Distribution of inquiries among operators is organized through queue mechanisms. By default: "who is free." In reality, more complexity is needed:

  • Determining responsible person by number or email from CRM—im.chat.get + search via crm.contact.list.
  • Distribution by departments based on keywords (NLP classifier or simple regex on first message).
  • Priority queue for VIP—by segment in CRM.
  • Escalation on 5-minute timeout—auto-switch to next.
  • Transition to call directly from chat—telephony.externalcall.register.

We use custom event handlers OnImOpenLinesChatStart and REST API to implement such scenarios. Additionally, we connect Bizproc for complex approval chains and integration with HL blocks for storing custom queue parameters. Result: client does not wait, operator is not overloaded.

What is included in messenger integration work

Component Description
Audit of current CRM structure Analysis of inquiry types, channels, operator load
Connecting channels Configuration of WhatsApp, Telegram, Viber, VK, email, online chat connectors
Routing setup Queues, distribution by competence, escalations, SLA
Chatbot development Script-based or with NLP, integration with CRM and external APIs
Operator training Documentation, video instruction recording, webinar
Testing and support Running all scenarios, 2-week monitoring after launch
6-month warranty Free bug fixes, consultations

Chatbots: Script-Based and with NLP

Types

Script-based (rule-based): button menu, decision tree. "How to pay" → "Where is my order" → "Business hours." Transfer to operator at intent == 'unknown' → transfer_to_queue. Reliable, predictable, covers 60-70% of typical inquiries.

With NLP: free text in Russian. Intent detection (buy, complain, inquire about delivery), entity extraction (name, date, order number). Contextual dialog—remembers what was discussed. Implemented on Rasa or Dialogflow, integrated with Bitrix24 via REST.

Example handler code for a script-based bot (PHP)
use Bitrix\Main\Loader;
use Bitrix\Imopenlines\Model\SessionTable;

Loader::includeModule('imopenlines');

$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler('imopenlines', 'OnImOpenLinesMessageReceive', function($event) {
    $message = $event->getParameter('message');
    $chatId = $event->getParameter('chatId');
    
    if (preg_match('/order status (\d+)/i', $message, $matches)) {
        $orderId = $matches[1];
        // Get order status via API
        $order = \Bitrix\Sale\Order::load($orderId);
        if ($order) {
            $status = $order->getField('STATUS_ID');
            \Bitrix\ImOpenLines\Chat::sendMessage($chatId, 'Your order #' . $orderId . ' status: ' . $status);
        }
    }
});

Scenarios and Real Impact

Scenario Action Operator Relief
FAQ Answers from knowledge base based on intent match 30-50%
Order status Request sale.order.get by number 15-25%
Booking Date/specialist selection, creation via API 20-30%
Calculation Preliminary estimate based on parameters 10-20%
Lead qualification Data collection → crm.lead.add 3x funnel acceleration
NPS/CSAT Rating after service 100% automatic collection

Comparison: a script-based bot processes requests 5 times faster than an operator, and an NLP bot reduces fallback rate to 15% after training on real dialogs. Average savings on operator salary when implementing a chatbot amount to substantial monthly savings.

How can chatbots transform your customer support?

Development Process

  1. Inquiry analysis—export history from open lines, cluster by topic. Identify 80% of typical requests.
  2. Dialog design—map on miro/figma. Each branch ends either with an answer or transfer to operator.
  3. Development—logic, integration with CRM and external APIs. For script-based: finite state machine. For NLP: pipeline: tokenizer → featurizer → classifier → response selector.
  4. NLP training—on real dialogs (at least 500 examples). Set confidence threshold.
  5. Testing—run all branches, edge cases (empty message, sticker, voice).
  6. Optimization—monitor fallback rate, retrain on new dialogs every 2 weeks.

Timeline

Task Duration
Single messenger connection 1-2 days
Open lines setup 2-3 days
Script-based bot (basic) 1-2 weeks
Bot with NLP 3-6 weeks
Comprehensive omnichannel system 4-8 weeks

Result: all communications in one window, routine automated, no message lost. Managers sell, not search for the right chat. Evaluate which channels you need—contact us, we'll select for your niche. Get a personalized timeline and cost estimate for your project.