Telegram
Overview
The OpenAlgo Telegram Bot provides a convenient interface to your trading account through Telegram. It gives you read access to orders, trades, positions, holdings, funds, P&L, quotes and charts, and it also exposes a small set of remote actions: closing all positions, stopping running Python strategies, and switching the instance between Live and Analyze mode. Order alerts are pushed to you automatically when orders flow through the OpenAlgo API.
Features
Account Linking: Securely link your OpenAlgo account using an API key and host URL
Real-time Data Access: View orderbook, tradebook, positions, holdings, and funds
P&L Tracking: Monitor realized and unrealized profit/loss
Quote Information: Get real-time quotes for any symbol
Chart Generation: Generate intraday and daily candlestick charts with volume
Remote Actions: Close all positions, stop running Python strategies, toggle Live/Analyze mode
Automatic Order Alerts: Every order, basket, split, options and GTT event pushed to your chat
Interactive Menu: Inline button interface for quick access
Programmatic Sends:
POST /api/v1/telegram/notifyandclient.telegram(...)in the Python SDK
Setup
1. Create Your Telegram Bot
Open Telegram and search for @BotFather
Send the
/newbotcommandFollow the instructions to name your bot and choose its username
Copy the bot token provided by BotFather
Use this token in the OpenAlgo configuration below
2. Enable the Telegram Bot in OpenAlgo
Log in to OpenAlgo. From the profile dropdown (top right) click Telegram Bot, or navigate to
/telegramClick Configuration to open
/telegram/configPaste the bot token into the Bot Token field
Optionally adjust Broadcast Messages and Rate Limit (messages per minute), then click Save Configuration
Return to
/telegramand click Start Bot
The status badge on /telegram flips to Online once polling starts. If the bot was running when the server was last shut down, it auto-starts on the next boot, so you normally only press Start Bot once.
3. Link Your Account
Start a conversation with your bot on Telegram and send
/startSend the
/linkcommand with your API key and host URL:The bot validates the credentials by calling
fundsagainst that host. On success it stores the encrypted key, records your OpenAlgo username and broker, and confirms that the account is linked
Both arguments are required. /link with anything other than exactly two arguments returns a usage message.
Available Commands
Account Management
/start- Initialize the bot and see the welcome message/link <api_key> <host_url>- Link your OpenAlgo account/unlink- Unlink your account and delete the stored credentials/status- Check connection status, host URL and link date
Trading Data
/orderbook- View orders (first 10 shown)/tradebook- View executed trades (first 10 shown)/positions- View open positions (first 10 shown)/holdings- View holdings (first 10 shown)/funds- View available cash, collateral, utilized margin and total/pnl- View realized, unrealized and total P&L
Amounts are printed with the currency symbol that matches the broker recorded when you linked: $ for crypto brokers (currently Delta Exchange), otherwise the rupee symbol.
Market Data
/quote <symbol> [exchange]- Get quote for a symbol. Exchange defaults toNSEExample:
/quote RELIANCEExample:
/quote NIFTY NSE_INDEXReturns LTP, change, change percent, open, high, low, previous close and volume
Charts
/chart <symbol> [exchange] [type] [interval] [days]- Generate price chartsExchange: defaults to
NSEType:
intraday(default),daily, orbothInterval: any interval the history API accepts. The bot's own help lists
1m,5m,15m,30m,1handDDays: lookback period. Defaults to 5 for intraday and 252 for daily
Examples:
/chart RELIANCE- 5-minute intraday chart over 5 days/chart RELIANCE NSE intraday 15m 10- 15-minute chart for 10 days/chart RELIANCE NSE daily D 100- Daily chart for 100 days/chart RELIANCE NSE both- Intraday and daily charts sent together as a media group
Remote Actions
These commands change state on the OpenAlgo instance. None of them act on the command alone: each replies with inline buttons, and nothing happens until you press one.
/closeall- Close all open positions. Offers Yes, close all, Close all + Stop strategies, and Cancel. The second option closes every position and then stops every running Python strategy/stoppython- List running Python strategies as buttons. Pick one to stop it, or Stop All to stop every running strategy. Each choice is confirmed before it runs. If nothing is running the bot says so and stops there/mode- Show whether the instance is in Live Mode or Analyze Mode, with a single button to switch to the other. The change is applied server-side and pushed to the web UI over SocketIO
Interactive Interface
/menu- Display the inline button menu. Buttons: Orderbook, Tradebook, Positions, Holdings, Funds, P&L, and Refresh. The Refresh button edits the same message in place and stamps it with the update time/help- Show the help message with all commands
The P&L button and the /pnl command read the same fields from the funds response, so the two always agree.
Order Alerts (Automatic Notifications)
Overview
The bot automatically sends real-time notifications for order-related API activity. No additional commands are needed: alerts are sent when orders are placed through the OpenAlgo API. Delivery goes over a direct HTTPS call to the Telegram Bot API rather than through the polling bot, so alerts do not depend on the polling loop being mid-cycle. They do depend on the bot being started: if the bot is stopped from /telegram, automatic alerts stop with it.
Supported Order Types
Alerts are driven by the internal event bus. The events that produce a Telegram message are:
order.placed
placeorder or placesmartorder succeeded
order.no_action
Smart order evaluated and found nothing to do
order.modified
modifyorder succeeded
order.cancelled
cancelorder succeeded
orders.all_cancelled
cancelallorder succeeded
position.closed
closeposition succeeded
basket.completed
All legs of a basketorder completed
split.completed
All sub-orders of a splitorder completed
options.completed
All legs of an optionsorder completed
multiorder.completed
All legs of an optionsmultiorder completed
gtt.placed
placegttorder succeeded
gtt.modified
modifygttorder succeeded
gtt.cancelled
cancelgttorder succeeded
gtt.triggered
A resting GTT fired and placed its order
gtt.expired
A GTT lapsed past its expires_at without firing
Failure events (order.failed, order.modify_failed, order.cancel_failed, gtt.failed, gtt.modify_failed, gtt.cancel_failed, analyzer.error) deliberately do not send a Telegram message, so a run of validation rejections cannot flood your chat.
gtt.placed, gtt.modified and gtt.cancelled fire in both Live and Analyze mode. gtt.triggered and gtt.expired are published by the sandbox GTT manager, so today they only reach you in Analyze mode: a live GTT fires at the broker, where OpenAlgo does not observe the moment it triggers.
The alert formatter has a dedicated layout for each order API type. GTT events do not have one yet, so they arrive under the generic Order Update heading with the mode line, strategy name and timestamp but no per-trigger detail.
Alert Format
Each alert includes:
Strategy Name: First line, if
strategywas supplied in the API callMode Indicator:
LIVE MODE - Real Orderfor real broker orders,ANALYZE MODE - No Real Orderfor sandbox orders, followed by a horizontal ruleOrder Details: Symbol, action, quantity, price type, exchange, product type
Status: Order ID on success, or an error line with the failure message
Timestamp:
Time: HH:MM:SSon the last line
The bot sends its messages with Telegram Markdown, so mode indicators, strategy names and symbols arrive bold or monospaced rather than decorated with icons. Status markers inside multi-leg alerts are written as plain tags such as [OK] and [FAILED].
Example Notifications
Live order placed:
Analyze mode order:
Configuration
Alerts are enabled by default for every linked user. The gate is the
notifications_enabledflag on the linked-user row, which is shown on/telegram/usersand defaults to onA send that fails (bad token, Telegram API error, timeout) is recorded in the
notification_queuetable at priority 8. There is no background worker that drains this queue, so treat it as a delivery audit trail rather than an automatic retryIf Telegram rejects the message because of a Markdown parsing error, the alert is immediately re-sent as plain text
Zero impact on order execution speed: formatting and sending happen on a five-worker thread pool, never on the order-placement path
Requirements for Receiving Alerts
The Telegram bot must be started (Start Bot on
/telegram, orPOST /telegram/bot/start). While the bot is stopped, automatic alerts are suppressed andPOST /api/v1/telegram/notifyreturns HTTP 409Your account must be linked with the
/linkcommandnotifications_enabledmust be on for your linked user (the default)Orders must be placed through the OpenAlgo API. Orders placed directly on a broker website do not raise events
Chart Features
Intraday Charts
Default interval: 5 minutes
Default period: 5 days
Candlestick price panel plus a volume panel, with volume bars colored green or red by candle direction
Category-type x-axis, so there are no blank gaps for non-trading hours
Daily Charts
Default interval: Daily (
D)Default period: 252 trading days. The history request reaches back 1.5 times that many calendar days to make sure enough sessions are returned, then the series is trimmed to the requested count
Candlestick price panel plus a volume panel, using the same layout as the intraday chart. No moving averages or other overlays are drawn
Chart Customization
Intervals: passed straight through to the history API.
1m,5m,15m,30m,1hfor intraday,Dfor dailyDays: customize the lookback period
Exchange: any exchange the history API supports, for example NSE, BSE, NFO, CDS, MCX, NSE_INDEX, BSE_INDEX
Security
API Key Encryption
API keys are encrypted with Fernet before storage in the
telegram_userstableThe Fernet key is derived with PBKDF2-SHA256 (100,000 iterations) from
API_KEY_PEPPERand theTELEGRAM_KEY_SALTsaltKeys are never stored in plain text and each user's key is isolated
Authentication
/linkrequires a valid API key and is validated against the OpenAlgo server before anything is storedThe bot management pages and routes under
/telegramare behind the Flask login sessionThe public
/api/v1/telegram/*endpoints are authenticated with an OpenAlgo API key, sent either as theapikeybody field or theX-API-KEYheaderPOST /api/v1/telegram/webhookis verified against theX-Telegram-Bot-Api-Secret-Tokenheader. The expected value isTELEGRAM_WEBHOOK_SECRETif set, otherwise the first 32 characters of the SHA-256 digest of the bot token
Privacy
Each Telegram user can only access their own linked account
No cross-user data access
Command usage is logged for security audit
Database Schema
The bot uses SQLAlchemy ORM with the following tables:
TelegramUser
Table
telegram_users. Stores user-bot linkage:telegram_id,openalgo_username,encrypted_api_key,host_url,telegram_username,first_name,last_name,broker,is_active,notifications_enabled,last_command_at
BotConfig
Table
bot_config, a single row withid=1. Holds the encryptedtoken,bot_username,is_active,max_message_length(default 4096),rate_limit_per_minute(default 30) andbroadcast_enabledThere is no webhook URL or polling-mode column. The bot always runs in polling mode; the webhook route exists but does not yet dispatch updates
CommandLog
Table
command_logs. Audit trail of every command and inline-button callback:telegram_id,command,chat_id,parameters,executed_at. This table backs the/telegram/analyticspage andGET /api/v1/telegram/stats
NotificationQueue
Table
notification_queue. Rows written when a send fails, carryingmessage,priority,status,error_message
UserPreference
Table
user_preferences. Per-user flags:order_notifications,trade_notifications,pnl_notifications,daily_summary,summary_time,language,timezone. These are readable and writable throughGET/POST /api/v1/telegram/preferences; the order-alert path currently gates only onnotifications_enabled
Technical Architecture
Components
TelegramBotService (
services/telegram_bot_service.py)Core bot logic and command handlers, built on python-telegram-bot
OpenAlgo Python SDK integration for every data call
Chart generation using Plotly
TelegramAlertService (
services/telegram_alert_service.py)Formats and delivers order alerts using a synchronous
httpx.Clientstraight tohttps://api.telegram.org, so no asyncio or greenlet boundary is crossed under Gunicorn plus eventletOwns the five-worker
alert_executorthread pool
Event bus subscriber (
subscribers/telegram_subscriber.py)Registered in
subscribers/__init__.register_all()on every order, position, batch and GTT topic
Database Layer (
database/telegram_db.py)SQLAlchemy models and queries
Fernet encryption and decryption helpers
Configuration management, with TTL caches on user and preference lookups
Blueprint (
blueprints/telegram.py)Session-authenticated routes for bot management, consumed by the React pages
REST namespace (
restx_api/telegram_bot.py)The public
/api/v1/telegram/*surface
React pages (
frontend/src/pages/telegram/)/telegram,/telegram/config,/telegram/usersand/telegram/analytics
Auto-start Feature
Bot automatically starts on application launch if it was active when the server stopped
State persistence across restarts, configured in
app.py
Threading Model
Bot runs in a separate thread with its own event loop
Non-blocking operation with the main Flask application
Graceful shutdown handling, with automatic reconnect and backoff on Telegram network errors
Chart Generation
Uses Plotly for chart creation
Kaleido engine for PNG export
Pandas for data manipulation
Category-type x-axis to handle gaps
OpenAlgo pins
kaleido==1.3.0. Kaleido 1.x no longer bundles a browser: it drives a real headless Chromium over the Chrome DevTools Protocol, so Chromium must be installed on the host or in the container. Each render spawns a browser process for roughly one to three seconds. A missing Chromium is the usual reason/chartreplies "Failed to generate charts"The render runs on a genuine, un-monkey-patched OS thread. Kaleido calls
asyncio.run()internally, which cannot run inside the bot's live event loop, and eventlet's patchedthreading.Threaddoes not escape it
Troubleshooting
Bot Not Responding
Check that the badge on
/telegramreads OnlineVerify the bot token is correct on
/telegram/configCheck network connectivity to
api.telegram.orgReview the server logs for errors
Chart Generation Issues
Confirm Chromium is installed and reachable. On Docker:
docker exec openalgo-web /usr/bin/chromium --version. On bare metal:which chromium || which chromium-browserEnsure market data is available for the symbol
Check that the exchange is correct
Verify the interval is supported and the date range is valid
Linking Issues
Verify the API key is correct and active
Ensure the host URL is reachable from the machine running the bot, and that you passed both arguments to
/linkCheck that the API key resolves to an OpenAlgo user
Verify the OpenAlgo server is running
Alerts Stopped Arriving
Check whether the bot was stopped. Stopping the bot also stops automatic order alerts
Confirm
notifications_enabledis on for your row on/telegram/usersConfirm the order actually went through the OpenAlgo API
Look for
notification_queuerows, which record sends that failed
Environment Variables
The bot respects the following environment variables:
DATABASE_URL- Database connection string. The Telegram tables live in the main OpenAlgo databaseAPI_KEY_PEPPER- Pepper fed into the PBKDF2 key derivation for the stored API keys and bot tokenTELEGRAM_KEY_SALT- Salt for that derivation. Defaults totelegram-openalgo-saltHOST_SERVER- OpenAlgo server URLTELEGRAM_RATE_LIMIT- Rate limit for the/api/v1/telegram/*endpoints. Defaults to30 per minuteTELEGRAM_MESSAGE_RATE_LIMIT- Rate limit forPOST /telegram/send-message. Defaults to10 per minuteTELEGRAM_WEBHOOK_SECRET- Shared secret for webhook verification. Derived from the bot token when unset
API Endpoints
Web Interface
All routes below are under /telegram and require a logged-in Flask session. The pages themselves (/telegram, /telegram/config, /telegram/users, /telegram/analytics) are React routes served by the single-page app.
POST /telegram/config- Update bot configuration (token,broadcast_enabled,rate_limit_per_minute)POST /telegram/bot/start- Start the botPOST /telegram/bot/stop- Stop the botGET /telegram/bot/status- Bot lifecycle statePOST /telegram/broadcast- Send a message to all users with notifications enabledPOST /telegram/test-message- Send a test message to the logged-in user's linked chatPOST /telegram/send-message- Send a message to onetelegram_idPOST /telegram/user/<telegram_id>/unlink- Unlink a user from the admin UIGET /telegram/api/index- Dashboard payload for the React pageGET /telegram/api/config- Config payload (never returns the token itself)GET /telegram/api/users- Linked users plus 30-day command statsGET /telegram/api/analytics- 7-day and 30-day command stats
There is no restart route. To restart the bot, stop it and start it again.
Public REST API
Mounted at /api/v1/telegram. Authenticate with an OpenAlgo API key in the apikey body field or the X-API-KEY header.
GET /api/v1/telegram/config- Read bot configuration. The token is truncated in the responsePOST /api/v1/telegram/config- Update configuration.rate_limit_per_minutemust be between 1 and 120POST /api/v1/telegram/start- Initialize and start the botPOST /api/v1/telegram/stop- Stop the botGET /api/v1/telegram/users- List linked users. Optionalbrokerandnotifications_enabledquery filtersPOST /api/v1/telegram/notify- Send a message to one linked userPOST /api/v1/telegram/broadcast- Broadcast endpoint. Limited to 5 requests per minute and refuses with HTTP 403 when broadcast is disabled. The fan-out itself is not wired up yet, so it returnssuccess_countandfail_countof 0. Use the Send Broadcast button on/telegram, which posts toPOST /telegram/broadcastand does sendGET /api/v1/telegram/stats- Command usage statistics. Optionaldays(1 to 365, default 7)GET /api/v1/telegram/preferences- Read per-user preferences. Requirestelegram_idPOST /api/v1/telegram/preferences- Update per-user preferencesPOST /api/v1/telegram/webhook- Inbound webhook receiver, verified by secret token
POST /api/v1/telegram/notify takes:
apikey
string
Required. OpenAlgo API key
username
string
Required. OpenAlgo login username, not the Telegram username
message
string
Required. Message body, up to 4096 characters
priority
integer
Optional, 1 to 10, default 5. Out-of-range values fall back to 5
wait_for_delivery
bool
Optional, default false. When true, the call blocks until Telegram replies
The endpoint returns HTTP 409 when the bot is stopped, HTTP 404 when the username has no linked Telegram account, and HTTP 401 for a bad API key.
Python SDK
username, message and priority are keyword-only. username is the OpenAlgo login username, not the Telegram handle.
Error Handling
All errors are logged with context
User-friendly error messages in Telegram
A Markdown parse failure is retried once as plain text
Network errors during polling trigger a reconnect with backoff, up to five attempts
Graceful degradation for missing data
Performance Considerations
Alerts are dispatched on a five-worker thread pool, off the request path
User, credential and preference lookups are served from 30-minute TTL caches
Database queries are optimized with indexes
Chart rendering is the one blocking step: it pauses the bot's event loop for the duration of the Chromium render, which is acceptable for personal, low-volume use
Future Enhancements
Support
For issues or questions:
Check the logs in the OpenAlgo dashboard
Review this documentation
Contact OpenAlgo support
Last updated
Was this helpful?