---
title: "Telegram bot for new deals"
description: "Poll new CRM deals every two minutes; notify a Telegram chat with an HTML-formatted card."
canonical_url: "https://bitrix24.github.io/b24jssdk/docs/examples/telegram-bot"
last_updated: "2026-06-02"
---
# Telegram bot for new deals

> Poll new CRM deals every two minutes; notify a Telegram chat with an HTML-formatted card.

## What it does

Watches `crm.item.list` for deals with `id > lastSeenDealId` and base stage `NEW`. For every new deal it loads the related contact (`crm.item.get`), formats an HTML card, and posts it to a Telegram chat via `grammy`. Provides `/start` and `/status` slash commands.

## Stack

Node.js 18+, `grammy`, `node-cron`.

## Install

```bash
pnpm add grammy node-cron
```

## Environment

```bash
export B24_HOOK='https://your.bitrix24.com/rest/1/secret'
export TELEGRAM_BOT_TOKEN='...'   # @BotFather
export TELEGRAM_CHAT_ID='...'     # destination chat
```

## Run

```bash
npx tsx 06-telegram-bot.ts
```

## Source

[`skills/b24jssdk-recipes/examples/06-telegram-bot.ts`](https://github.com/bitrix24/b24jssdk/blob/main/skills/b24jssdk-recipes/examples/06-telegram-bot.ts).

## Notes

- `lastSeenDealId` lives in memory — persist it to survive restarts.
- For interactive actions (assign, mark as junk) extend with grammy's `InlineKeyboard`.
- HTML escaping is handled inline. If you change the message format keep `parse_mode: 'HTML'` and escape user-controlled strings.
- When the per-tick batch is large (lots of new deals at once), replace the per-deal `fetchContactName` call with a single `actions.v2.batch.make` that fetches every contact in one round-trip. Example shape: `actions.v2.batch.make({ calls: deals.map((d) => ['crm.item.get', { entityTypeId: 3, id: d.contactId }]) })`.

## Sitemap

See the full [sitemap](/b24jssdk/sitemap.md) for all pages.
