Telegram Channel
Telegram Outreach
Automated Telegram messaging using Telethon user accounts with intelligent account pooling, rate limiting, and warmup tracking.
Why User Accounts?
The Telegram Bot API cannot initiate DMs to users who have not started the bot. User accounts (via Telethon) can message anyone by username, which is critical for outreach campaigns. Account pooling distributes risk and increases throughput.
Architecture
telegram-worker/
telegram-worker/ ├── main.py # FastAPI app with all endpoints ├── account_manager.py # Telethon client pool + auth flow + send logic ├── db.py # Database operations (messages, accounts) ├── config.py # Environment config (rate limits, delays) ├── requirements.txt └── Dockerfile # Railway deployment (port 7861)
Worker API Endpoints
POST
/api/sendPOST
/api/accounts/addPOST
/api/accounts/:id/verifyGET
/api/accountsGET
/api/healthAccount Pooling
The Telegram worker manages a pool of user accounts. When a message needs to be sent, it automatically selects the best account based on:
- Account with the fewest daily sends (load balancing)
- Daily message limit not exceeded (default: 30/account)
- Account status is active (not banned, not in cooldown)
- Account is assigned to the requesting organization
Account Statuses
warming_up
New account, limited sends
active
Ready to send
assigned
Assigned to an org
banned
Blocked by Telegram
cooldown
Temporarily paused
Rate Limiting
The worker implements several layers of rate limiting to avoid Telegram bans:
| Limit | Default | Configurable |
|---|---|---|
| Max daily messages per account | 30 | MAX_DAILY_MESSAGES_PER_ACCOUNT |
| Min delay between sends | 30 seconds | MESSAGE_DELAY_MIN |
| Max delay between sends | 90 seconds | MESSAGE_DELAY_MAX |
| Inter-lead campaign delay | 60 seconds | Hardcoded in executor |
Message Flow
Send Message Sequence
POST /api/send { orgId, username, message }
|
v
1. manager.get_available_account(orgId)
-> Select account with fewest daily sends
-> Check daily limit not exceeded
|
v
2. Random delay (30-90 seconds)
|
v
3. manager.send_message()
-> client.get_entity(username)
-> client.send_message(entity, message)
-> db.increment_daily_sent()
|
v
4. db.log_message() -> INSERT INTO messages
|
v
5. Return { success: true, messageId: "..." }