Why Telegram?
Email alerts get buried. Slack is overkill for a solo project or small team. PagerDuty has a pricing tier. Telegram is free, has a solid bot API, delivers messages instantly to your phone, and setting it up takes about 15 minutes.
This tutorial walks through creating a Telegram bot and building a reusable Ruby class to send notifications from your scripts and applications.
Step 1: Create a Bot via BotFather
Open Telegram and search for @BotFather. Start a conversation and run:
/newbot
BotFather will ask for a name (display name) and a username (must end in bot). After that, it gives you a token that looks like:
7412853690:AAHx3kFgPQ2vNmD8sLuYtR1WoZ4JcBqE5Vk
Save this token. You will need it in every API call.
Step 2: Get Your Chat ID
The bot needs to know where to send messages. Each chat (private or group) has a unique ID.
For a private chat:
- Open a conversation with your new bot and send it any message.
- Make an HTTP request to the
getUpdatesendpoint:
curl "https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates"
The response is JSON. Look for message.chat.id:
{
"result": [{
"message": {
"chat": {
"id": 198765432,
"type": "private"
},
"text": "hello"
}
}]
}
That number (198765432) is your chat ID.
For a group chat:
Add the bot to the group and send a message. The getUpdates response will include the group’s chat ID, which is a negative number like -1001234567890.
Step 3: Send a Test Message
Verify everything works before writing any Ruby:
curl -s -X POST "https://api.telegram.org/bot<YOUR_TOKEN>/sendMessage" \
-d "chat_id=<YOUR_CHAT_ID>" \
-d "text=Hello from the terminal" \
-d "parse_mode=Markdown"
If you see the message arrive in Telegram, you are ready to move on.
Step 4: The TelegramNotifier Ruby Class
This class wraps the Telegram API with a clean interface:
require "net/http"
require "uri"
require "json"
class TelegramNotifier
API_URL = "https://api.telegram.org/bot%s/sendMessage"
def initialize(token: ENV["TELEGRAM_BOT_TOKEN"], chat_id: ENV["TELEGRAM_CHAT_ID"])
@token = token
@chat_id = chat_id
end
def notify(message, level: :info)
prefix = {
info: "INFO",
success: "SUCCESS",
warning: "WARNING",
error: "ERROR"
}[level] || "INFO"
send_message("[#{prefix}] #{message}")
end
private
def send_message(text)
uri = URI(format(API_URL, @token))
response = Net::HTTP.post_form(uri, {
"chat_id" => @chat_id,
"text" => text,
"parse_mode" => "Markdown"
})
unless response.is_a?(Net::HTTPSuccess)
warn "TelegramNotifier: failed to send message (#{response.code})"
end
response
rescue => e
warn "TelegramNotifier: #{e.message}"
nil
end
end
Set the token and chat ID as environment variables:
export TELEGRAM_BOT_TOKEN="7412853690:AAHx3kFgPQ2vNmD8sLuYtR1WoZ4JcBqE5Vk"
export TELEGRAM_CHAT_ID="198765432"
Practical Examples
Backup notifications
notifier = TelegramNotifier.new
begin
# Run backup logic
`pg_dump myapp_production > /backups/db_#{Date.today}.sql`
if $?.success?
notifier.notify("Database backup completed: db_#{Date.today}.sql", level: :success)
else
notifier.notify("Database backup failed — check /backups/ directory", level: :error)
end
rescue => e
notifier.notify("Backup script crashed: #{e.message}", level: :error)
end
Deploy notifications
notifier = TelegramNotifier.new
notifier.notify("Deploy started — branch: #{ENV['BRANCH']} by #{ENV['USER']}", level: :info)
# ... deploy steps ...
notifier.notify("Deploy finished — #{ENV['BRANCH']} is live", level: :success)
Error alerts from a Rails app
In config/application.rb or an initializer:
# app/lib/telegram_notifier.rb — the class above
# In a rescue block or exception handler:
rescue => e
TelegramNotifier.new.notify(
"*Error in #{self.class}*\n`#{e.message}`",
level: :error
)
raise
end
Or as middleware for unhandled exceptions:
# config/application.rb
config.exceptions_app = ->(env) do
exception = env["action_dispatch.exception"]
TelegramNotifier.new.notify("Unhandled exception: #{exception.message}", level: :error)
[500, {}, ["Internal Server Error"]]
end
Monitoring cron job
A simple script that checks if a service is responding and sends an alert if not:
#!/usr/bin/env ruby
require_relative "telegram_notifier"
require "net/http"
SERVICES = {
"API" => "https://api.myapp.com/health",
"Dashboard" => "https://app.myapp.com/health"
}
notifier = TelegramNotifier.new
SERVICES.each do |name, url|
uri = URI(url)
response = Net::HTTP.get_response(uri)
unless response.is_a?(Net::HTTPSuccess)
notifier.notify("#{name} is DOWN — HTTP #{response.code}", level: :error)
end
rescue => e
notifier.notify("#{name} is unreachable — #{e.message}", level: :error)
end
Add to crontab to run every 5 minutes:
*/5 * * * * /usr/bin/ruby /home/deploy/scripts/health_check.rb
Security Notes
- Never hardcode the bot token in source code. Always use environment variables or a secrets manager.
- If you add the bot to a group, anyone in that group can see the messages. Use private chats for sensitive system alerts.
- Consider using
parse_mode=MarkdownV2if you need to send messages with special characters — MarkdownV2 has stricter escaping rules but better rendering.
Summary
| Step | What you do |
|---|---|
| Create bot | Chat with @BotFather, run /newbot |
| Get chat_id | Send a message to the bot, call getUpdates |
| Test | Use curl to send a message |
| Integrate | Use the TelegramNotifier class from your scripts |
Telegram bots are one of the lowest-friction notification solutions available. Once the class is in place, adding a notification to any script is a single line. For small projects and personal infrastructure, it is often all you need.