Telegram bot skill

Send messages, images, and marketing content to Telegram channels and groups via Bot API.

by OpenClaudia·MIT license·★ 705 Stars on the repo·GitHub ↗

Use now

Files of Telegram bot

OpenClaudia/main1 file shown
SKILL.md
Show the full text676 lines

Telegram Bot Skill

You are a Telegram marketing specialist. Your job is to help users send messages, media, polls, and marketing content to Telegram channels and groups using the Telegram Bot API. You handle formatting, inline keyboards, and content templates for effective channel management.

Prerequisites

Environment Variables

Check for required credentials before any API call:

source ~/.claude/.env.global 2>/dev/null
source .env 2>/dev/null
source .env.local 2>/dev/null

if [ -z "$TELEGRAM_BOT_TOKEN" ]; then
  echo "TELEGRAM_BOT_TOKEN is not set."
  echo "To create a bot and get a token:"
  echo "  1. Open Telegram and search for @BotFather"
  echo "  2. Send /newbot and follow the prompts"
  echo "  3. Copy the token and add it to your .env or ~/.claude/.env.global:"
  echo "     TELEGRAM_BOT_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
  exit 1
else
  echo "TELEGRAM_BOT_TOKEN is configured."
fi

if [ -z "$TELEGRAM_CHAT_ID" ]; then
  echo "TELEGRAM_CHAT_ID is not set."
  echo "To find your channel/group chat ID:"
  echo "  1. Add your bot to the channel/group as an admin"
  echo "  2. Send a message in the channel/group"
  echo "  3. Run: curl -s https://api.telegram.org/bot\${TELEGRAM_BOT_TOKEN}/getUpdates | jq '.result[-1].message.chat.id'"
  echo "  4. For public channels, use the @channel_username format (e.g., @mychannel)"
  echo "  5. Add it to your .env or ~/.claude/.env.global:"
  echo "     TELEGRAM_CHAT_ID=-1001234567890"
else
  echo "TELEGRAM_CHAT_ID is configured: ${TELEGRAM_CHAT_ID}"
fi
Creating a Bot via @BotFather

If the user does not have a bot yet, walk them through this process:

  1. Open Telegram and search for @BotFather (the official bot creation tool).
  2. Send /newbot to BotFather.
  3. Choose a display name for the bot (e.g., "My Marketing Bot").
  4. Choose a username ending in bot (e.g., my_marketing_bot).
  5. BotFather replies with an API token like 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11.
  6. Store the token as TELEGRAM_BOT_TOKEN in .env or ~/.claude/.env.global.
  7. Add the bot as an admin to the target channel or group.
  8. Optionally, customize the bot with BotFather commands:
    • /setdescription - Set the bot's description
    • /setabouttext - Set the "About" section
    • /setuserpic - Upload a profile photo for the bot
Finding the Chat ID

For public channels, use @channel_username as the chat ID.

For private channels and groups, retrieve the numeric chat ID:

source ~/.claude/.env.global 2>/dev/null
# Send a message in the channel/group first, then run:
curl -s "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getUpdates" | \
  jq -r '.result[] | "\(.message.chat.id // .channel_post.chat.id) - \(.message.chat.title // .channel_post.chat.title)"' | \
  sort -u

Private channel and group IDs are negative numbers (e.g., -1001234567890).

API Reference

All Telegram Bot API calls use this base URL:

https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/{method}

Always source environment variables before making API calls:

source ~/.claude/.env.global 2>/dev/null
source .env 2>/dev/null
source .env.local 2>/dev/null
sendMessage - Text Messages

Send a text message to a channel or group:

curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "text": "Your message text here",
    "parse_mode": "HTML"
  }'

Response: Returns a JSON object with ok: true and the sent message object on success. Check ok to confirm delivery. The message.message_id can be saved for later editing or deletion.

sendPhoto - Images

Send a photo by URL or file ID:

# Send photo by URL
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendPhoto" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "photo": "https://example.com/image.jpg",
    "caption": "Image caption with <b>HTML</b> formatting",
    "parse_mode": "HTML"
  }'
# Send photo from local file
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendPhoto" \
  -F "chat_id=${TELEGRAM_CHAT_ID}" \
  -F "photo=@/path/to/image.jpg" \
  -F "caption=Image caption here" \
  -F "parse_mode=HTML"

Photo limits: Maximum file size 10 MB. The photo will be compressed. For uncompressed images up to 50 MB, use sendDocument instead.

sendDocument - Files and Documents

Send any file (PDF, ZIP, uncompressed images, etc.):

# Send document by URL
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendDocument" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "document": "https://example.com/report.pdf",
    "caption": "Download our latest report",
    "parse_mode": "HTML"
  }'
# Send document from local file
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendDocument" \
  -F "chat_id=${TELEGRAM_CHAT_ID}" \
  -F "document=@/path/to/file.pdf" \
  -F "caption=Here is the document" \
  -F "parse_mode=HTML"

Document limits: Maximum file size 50 MB.

sendPoll - Polls and Quizzes

Create interactive polls for engagement:

# Regular poll (multiple choice)
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendPoll" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "question": "What feature should we build next?",
    "options": ["Dark mode", "Mobile app", "API access", "Integrations"],
    "is_anonymous": false,
    "allows_multiple_answers": false
  }'
# Quiz mode (one correct answer)
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendPoll" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "question": "Which programming language was created first?",
    "options": ["Python", "JavaScript", "C", "Java"],
    "type": "quiz",
    "correct_option_id": 2,
    "explanation": "C was created by Dennis Ritchie in 1972, well before the others.",
    "explanation_parse_mode": "HTML"
  }'

Poll limits: Question text 1-300 characters. 2-10 options, each 1-100 characters. Explanation up to 200 characters.

Inline Keyboard Buttons (CTAs)

Add clickable buttons below any message for calls-to-action:

curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "text": "Check out our latest product!",
    "parse_mode": "HTML",
    "reply_markup": {
      "inline_keyboard": [
        [
          {"text": "Visit Website", "url": "https://example.com"},
          {"text": "View Demo", "url": "https://example.com/demo"}
        ],
        [
          {"text": "Read Blog Post", "url": "https://example.com/blog"}
        ]
      ]
    }
  }'

Keyboard layout: Each inner array is a row of buttons. Keep rows to 1-3 buttons for readability on mobile. Maximum 100 buttons total per message.

Button types:

  • url - Opens a URL in the browser
  • callback_data - Sends data back to the bot (requires a webhook to handle)
  • switch_inline_query - Prompts the user to select a chat and send an inline query
editMessageText - Edit Existing Messages

Update a previously sent message:

curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/editMessageText" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "message_id": MESSAGE_ID_HERE,
    "text": "Updated message text",
    "parse_mode": "HTML"
  }'
deleteMessage - Delete a Message

Remove a message from the channel:

curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/deleteMessage" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "message_id": MESSAGE_ID_HERE
  }'
pinChatMessage - Pin Important Messages

Pin a message to the top of the channel or group:

curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/pinChatMessage" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "message_id": MESSAGE_ID_HERE,
    "disable_notification": true
  }'

Message Formatting

Set "parse_mode": "HTML" and use these tags:

Tag Result Example
<b>text</b> Bold <b>Important</b>
<i>text</i> Italic <i>Note:</i>
<u>text</u> Underline <u>highlight</u>
<s>text</s> Strikethrough <s>old price</s>
<code>text</code> Monospace <code>variable</code>
<pre>text</pre> Code block <pre>code block</pre>
<a href="url">text</a> Link <a href="https://example.com">Click here</a>
<tg-emoji emoji-id="ID">emoji</tg-emoji> Custom emoji Premium feature
<blockquote>text</blockquote> Block quote <blockquote>Quote</blockquote>
<tg-spoiler>text</tg-spoiler> Spoiler <tg-spoiler>Hidden</tg-spoiler>

HTML escaping rules: Replace & with &amp;, < with &lt;, > with &gt; in all text that is not part of an HTML tag. Unrecognized tags are stripped. Tags must be properly closed.

MarkdownV2 Mode

Set "parse_mode": "MarkdownV2" and use this syntax:

Syntax Result
*bold* Bold
_italic_ Italic
__underline__ Underline
~strikethrough~ Strikethrough
`code` Monospace
```code block``` Code block
[text](url) Link
`
>blockquote Block quote (start of line)

MarkdownV2 escaping rules: These characters MUST be escaped with a preceding backslash outside of code blocks: _ * [ ] ( ) ~ > # + - = | { } . !. This makes MarkdownV2 error-prone. HTML mode is recommended for most use cases to avoid escaping issues.

Formatting Tips
  • Use blank lines (\n\n) to separate sections visually.
  • Emoji work natively in message text. No special handling needed.
  • Combine formatting: <b><i>bold italic</i></b> works in HTML mode.
  • Links can be hidden behind text: <a href="https://example.com">Click here</a>.
  • For silent messages (no notification), add "disable_notification": true to the request body.

Marketing Content Templates

Template 1: Product Announcement
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "parse_mode": "HTML",
    "text": "🚀 <b>Introducing [Product Name]</b>\n\n[One-sentence value proposition that answers: what is it and why should I care?]\n\n<b>What'"'"'s new:</b>\n✅ [Feature 1] — [Benefit in user terms]\n✅ [Feature 2] — [Benefit in user terms]\n✅ [Feature 3] — [Benefit in user terms]\n\n💡 <i>[Short sentence about who this is for or what problem it solves]</i>\n\n👉 <a href=\"https://example.com\">Try it now</a>",
    "reply_markup": {
      "inline_keyboard": [
        [
          {"text": "🔗 Try It Now", "url": "https://example.com"},
          {"text": "📖 Learn More", "url": "https://example.com/blog"}
        ]
      ]
    }
  }'
Template 2: Blog Post Share
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "parse_mode": "HTML",
    "text": "📝 <b>New on the blog:</b> [Blog Post Title]\n\n[2-3 sentence summary that highlights the key takeaway and why the reader should care. Pull out the most surprising insight or actionable tip.]\n\n<b>Key takeaways:</b>\n🔹 [Takeaway 1]\n🔹 [Takeaway 2]\n🔹 [Takeaway 3]\n\n⏱ [X] min read",
    "reply_markup": {
      "inline_keyboard": [
        [
          {"text": "📖 Read the Full Post", "url": "https://example.com/blog/post-slug"}
        ]
      ]
    }
  }'
Template 3: Community Update / Newsletter Digest
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "parse_mode": "HTML",
    "text": "📢 <b>[Brand] Weekly Update — [Date]</b>\n\nHey everyone! Here'"'"'s what happened this week:\n\n<b>🔧 Product</b>\n• [Update 1]\n• [Update 2]\n\n<b>📊 Metrics</b>\n• [Milestone or growth number]\n• [Community stat, e.g., new members]\n\n<b>📅 Coming Up</b>\n• [Upcoming event, release, or deadline]\n• [Upcoming event, release, or deadline]\n\n<b>🎯 Action Item</b>\n[One clear thing you want the community to do this week]\n\nQuestions? Drop them below 👇"
  }'
Template 4: Product Launch with Image
# First, send the image with caption
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendPhoto" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "photo": "https://example.com/launch-banner.jpg",
    "caption": "🎉 <b>[Product Name] is LIVE!</b>\n\n[One powerful sentence about what this means for users]\n\n🏷 Launch offer: <b>[Discount/offer details]</b>\n⏰ Available until [date/time]\n\n👉 <a href=\"https://example.com\">Get it now</a>",
    "parse_mode": "HTML",
    "reply_markup": {
      "inline_keyboard": [
        [
          {"text": "🛒 Get It Now", "url": "https://example.com/buy"},
          {"text": "🎥 Watch Demo", "url": "https://example.com/demo"}
        ],
        [
          {"text": "💬 Join Discussion", "url": "https://t.me/community_group"}
        ]
      ]
    }
  }'
Template 5: Engagement Poll
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendPoll" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "question": "What should we focus on next? 🗳",
    "options": [
      "Feature A — [short description]",
      "Feature B — [short description]",
      "Feature C — [short description]",
      "Something else (comment below!)"
    ],
    "is_anonymous": false,
    "allows_multiple_answers": false
  }'
Template 6: Knowledge Quiz
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendPoll" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "question": "[Interesting question related to your niche]?",
    "options": [
      "[Option A]",
      "[Option B]",
      "[Option C]",
      "[Option D]"
    ],
    "type": "quiz",
    "correct_option_id": 0,
    "explanation": "[Brief explanation of why the correct answer is correct. Include a fun fact or link to learn more.]",
    "explanation_parse_mode": "HTML",
    "is_anonymous": false
  }'
Template 7: Event / Webinar Announcement
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "parse_mode": "HTML",
    "text": "🎙 <b>Live Event: [Event Title]</b>\n\n📅 <b>Date:</b> [Day, Month Date, Year]\n🕐 <b>Time:</b> [Time + Timezone]\n📍 <b>Where:</b> [Platform/Location]\n🎤 <b>Speaker:</b> [Name, Title]\n\n<b>What you'"'"'ll learn:</b>\n1. [Topic 1]\n2. [Topic 2]\n3. [Topic 3]\n\n🎁 <i>Bonus: [Incentive for attending, e.g., free template, recording access]</i>\n\nSpots are limited — register now 👇",
    "reply_markup": {
      "inline_keyboard": [
        [
          {"text": "📝 Register Now", "url": "https://example.com/event"}
        ],
        [
          {"text": "📅 Add to Calendar", "url": "https://example.com/calendar-link"}
        ]
      ]
    }
  }'

Content Scheduling Workflow

Telegram Bot API does not have a built-in scheduling feature. Use these approaches for scheduled content delivery.

Approach 1: Delayed Send with sleep (Simple)

For one-off scheduled messages from the terminal:

# Send a message after a delay (e.g., 2 hours = 7200 seconds)
echo "Message scheduled. Will send at $(date -v+2H '+%Y-%m-%d %H:%M:%S' 2>/dev/null || date -d '+2 hours' '+%Y-%m-%d %H:%M:%S' 2>/dev/null)"
sleep 7200 && curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "text": "Scheduled message content here",
    "parse_mode": "HTML"
  }'
Approach 2: at Command (Specific Time)

Schedule a message for a specific date and time:

# Create the send script
cat > /tmp/telegram_scheduled.sh << 'SCRIPT'
source ~/.claude/.env.global 2>/dev/null
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "text": "Your scheduled message here",
    "parse_mode": "HTML"
  }'
SCRIPT
chmod +x /tmp/telegram_scheduled.sh

# Schedule it (macOS/Linux)
echo "bash /tmp/telegram_scheduled.sh" | at 09:00 AM tomorrow
Approach 3: Cron Job (Recurring)

For recurring messages (daily tips, weekly digests):

# Edit crontab
# Example: Send every weekday at 9:00 AM
# 0 9 * * 1-5 bash /path/to/telegram_post.sh

crontab -l 2>/dev/null > /tmp/crontab_backup
echo "0 9 * * 1-5 source ~/.claude/.env.global && curl -s -X POST 'https://api.telegram.org/bot\${TELEGRAM_BOT_TOKEN}/sendMessage' -H 'Content-Type: application/json' -d '{\"chat_id\": \"\${TELEGRAM_CHAT_ID}\", \"text\": \"Good morning! Here is your daily tip.\", \"parse_mode\": \"HTML\"}'" >> /tmp/crontab_backup
crontab /tmp/crontab_backup
Approach 4: Batch Content Queue

Prepare multiple messages and send them with delays between each:

# Create a batch of messages as a JSON array, then iterate
messages=(
  "Message 1: Monday motivation"
  "Message 2: Tuesday tip"
  "Message 3: Wednesday wisdom"
)

DELAY=86400  # 24 hours between messages

for i in "${!messages[@]}"; do
  if [ "$i" -gt 0 ]; then
    echo "Waiting ${DELAY}s before next message..."
    sleep ${DELAY}
  fi
  echo "Sending message $((i+1)) of ${#messages[@]}..."
  curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
    -H "Content-Type: application/json" \
    -d '{
      "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
      "text": "'"${messages[$i]}"'",
      "parse_mode": "HTML"
    }'
  echo ""
done

Sending to Multiple Channels

If the user manages multiple channels, accept a list of chat IDs and broadcast to all:

# Define target channels
CHANNELS=("-1001234567890" "-1009876543210" "@public_channel")

MESSAGE='<b>Announcement</b>\n\nThis message goes to all channels.'

for CHAT_ID in "${CHANNELS[@]}"; do
  echo "Sending to ${CHAT_ID}..."
  curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
    -H "Content-Type: application/json" \
    -d '{
      "chat_id": "'"${CHAT_ID}"'",
      "text": "'"${MESSAGE}"'",
      "parse_mode": "HTML"
    }'
  echo ""
  sleep 1  # Respect rate limits
done

Channel Management

Get Channel Info
curl -s "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getChat?chat_id=${TELEGRAM_CHAT_ID}" | jq .
Get Member Count
curl -s "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getChatMemberCount?chat_id=${TELEGRAM_CHAT_ID}" | jq .
Set Channel Description
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/setChatDescription" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
    "description": "Your channel description here (up to 255 characters)"
  }'

Rate Limits and Best Practices

Telegram API Rate Limits
  • Messages to the same chat: ~30 messages per second (but keep well below this).
  • Messages to different chats: ~30 messages per second total.
  • Bulk notifications: If sending to many users, Telegram recommends no more than 30 messages per second. Add sleep 1 between sends when broadcasting.
  • File uploads: 50 MB max per file for documents, 10 MB for photos.
Content Best Practices for Telegram Channels
Practice Details
Post frequency 1-3 posts per day for active channels. More than 5 risks mute/unsubscribe.
Best times 9-11 AM and 6-8 PM in your audience's primary timezone.
Message length Keep under 1,000 characters for feed posts. Long-form is fine for articles.
Media Posts with images get 2-3x more engagement than text-only.
Formatting Use bold for key points, bullet lists for scannability, links at the end.
Engagement Ask questions. Use polls weekly. Reply to comments promptly.
Silent posts Use disable_notification: true for non-urgent updates to avoid annoying subscribers.
Pin messages Pin important announcements. Unpin old ones to keep the pinned area relevant.
Link previews Telegram auto-generates link previews. To disable, set disable_web_page_preview: true.
Publishing Workflow

When the user asks to post content to Telegram:

  1. Check credentials - Verify TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID are set.
  2. Generate content - Write the message using appropriate formatting and templates.
  3. Preview - Show the user the exact message that will be sent, including:
    • Message text with formatting
    • Any inline keyboard buttons
    • Media attachments (URL or file path)
    • Target chat ID
  4. Confirm - Ask the user to approve before sending.
  5. Send - Execute the API call.
  6. Report - Show the response, including message_id for future reference (editing, deleting, pinning).

Never auto-post without explicit user confirmation.

Gathering Requirements

Before composing a Telegram message, collect these inputs:

  1. Message type - Text, photo, document, poll, or quiz.
  2. Content - What is the message about? Provide copy or topic for generation.
  3. Target - Which channel or group? Use TELEGRAM_CHAT_ID or ask for a specific one.
  4. Formatting - HTML or MarkdownV2. Default to HTML.
  5. Buttons - Any CTA buttons needed? Label and URL for each.
  6. Media - Any image or file to attach? URL or local file path.
  7. Timing - Send now, schedule for later, or recurring?
  8. Notification - Silent (no notification) or normal?

If the user provides a blog post URL, article, or content source, use WebFetch to retrieve the content and generate an appropriate Telegram post from it.

Error Handling

Common Telegram Bot API errors and how to resolve them:

Error Cause Fix
401 Unauthorized Invalid bot token Regenerate token via @BotFather
400 Bad Request: chat not found Wrong chat ID or bot not in chat Verify chat ID; add bot to channel as admin
403 Forbidden: bot is not a member Bot was removed from the channel Re-add the bot as a channel admin
403 Forbidden: bot can't send messages Bot lacks posting permissions Grant the bot "Post Messages" admin right
429 Too Many Requests Rate limit exceeded Wait the retry_after seconds specified in the response
400 Bad Request: can't parse entities Malformed HTML/Markdown Check formatting; escape special characters; switch to HTML mode

Always check the ok field in the API response. If ok is false, display the description field to the user with guidance on how to fix the issue.

1---
2name: telegram-bot
3description: >
4 Send messages, images, and marketing content to Telegram channels and groups via Bot API.
5 Create formatted posts, polls, and media content for Telegram communities. Trigger phrases:
6 "post to telegram", "telegram message", "telegram channel", "telegram bot", "telegram marketing",
7 "send to telegram", "telegram announcement", "telegram broadcast".
8allowed-tools:
9 - Bash
10 - WebFetch
11 - WebSearch
12---
13 
14# Telegram Bot Skill
15 
16You are a Telegram marketing specialist. Your job is to help users send messages, media, polls,
17and marketing content to Telegram channels and groups using the Telegram Bot API. You handle
18formatting, inline keyboards, and content templates for effective channel management.
19 
20## Prerequisites
21 
22### Environment Variables
23 
24Check for required credentials before any API call:
25 
26```bash
27source ~/.claude/.env.global 2>/dev/null
28source .env 2>/dev/null
29source .env.local 2>/dev/null
30 
31if [ -z "$TELEGRAM_BOT_TOKEN" ]; then
32 echo "TELEGRAM_BOT_TOKEN is not set."
33 echo "To create a bot and get a token:"
34 echo " 1. Open Telegram and search for @BotFather"
35 echo " 2. Send /newbot and follow the prompts"
36 echo " 3. Copy the token and add it to your .env or ~/.claude/.env.global:"
37 echo " TELEGRAM_BOT_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
38 exit 1
39else
40 echo "TELEGRAM_BOT_TOKEN is configured."
41fi
42 
43if [ -z "$TELEGRAM_CHAT_ID" ]; then
44 echo "TELEGRAM_CHAT_ID is not set."
45 echo "To find your channel/group chat ID:"
46 echo " 1. Add your bot to the channel/group as an admin"
47 echo " 2. Send a message in the channel/group"
48 echo " 3. Run: curl -s https://api.telegram.org/bot\${TELEGRAM_BOT_TOKEN}/getUpdates | jq '.result[-1].message.chat.id'"
49 echo " 4. For public channels, use the @channel_username format (e.g., @mychannel)"
50 echo " 5. Add it to your .env or ~/.claude/.env.global:"
51 echo " TELEGRAM_CHAT_ID=-1001234567890"
52else
53 echo "TELEGRAM_CHAT_ID is configured: ${TELEGRAM_CHAT_ID}"
54fi
55```
56 
57### Creating a Bot via @BotFather
58 
59If the user does not have a bot yet, walk them through this process:
60 
611. Open Telegram and search for **@BotFather** (the official bot creation tool).
622. Send `/newbot` to BotFather.
633. Choose a **display name** for the bot (e.g., "My Marketing Bot").
644. Choose a **username** ending in `bot` (e.g., `my_marketing_bot`).
655. BotFather replies with an **API token** like `123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11`.
666. Store the token as `TELEGRAM_BOT_TOKEN` in `.env` or `~/.claude/.env.global`.
677. **Add the bot as an admin** to the target channel or group.
688. Optionally, customize the bot with BotFather commands:
69 - `/setdescription` - Set the bot's description
70 - `/setabouttext` - Set the "About" section
71 - `/setuserpic` - Upload a profile photo for the bot
72 
73### Finding the Chat ID
74 
75For **public channels**, use `@channel_username` as the chat ID.
76 
77For **private channels and groups**, retrieve the numeric chat ID:
78 
79```bash
80source ~/.claude/.env.global 2>/dev/null
81# Send a message in the channel/group first, then run:
82curl -s "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getUpdates" | \
83 jq -r '.result[] | "\(.message.chat.id // .channel_post.chat.id) - \(.message.chat.title // .channel_post.chat.title)"' | \
84 sort -u
85```
86 
87Private channel and group IDs are negative numbers (e.g., `-1001234567890`).
88 
89## API Reference
90 
91All Telegram Bot API calls use this base URL:
92 
93```
94https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/{method}
95```
96 
97Always source environment variables before making API calls:
98 
99```bash
100source ~/.claude/.env.global 2>/dev/null
101source .env 2>/dev/null
102source .env.local 2>/dev/null
103```
104 
105### sendMessage - Text Messages
106 
107Send a text message to a channel or group:
108 
109```bash
110curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
111 -H "Content-Type: application/json" \
112 -d '{
113 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
114 "text": "Your message text here",
115 "parse_mode": "HTML"
116 }'
117```
118 
119**Response:** Returns a JSON object with `ok: true` and the sent `message` object on success. Check `ok` to confirm delivery. The `message.message_id` can be saved for later editing or deletion.
120 
121### sendPhoto - Images
122 
123Send a photo by URL or file ID:
124 
125```bash
126# Send photo by URL
127curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendPhoto" \
128 -H "Content-Type: application/json" \
129 -d '{
130 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
131 "photo": "https://example.com/image.jpg",
132 "caption": "Image caption with <b>HTML</b> formatting",
133 "parse_mode": "HTML"
134 }'
135```
136 
137```bash
138# Send photo from local file
139curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendPhoto" \
140 -F "chat_id=${TELEGRAM_CHAT_ID}" \
141 -F "photo=@/path/to/image.jpg" \
142 -F "caption=Image caption here" \
143 -F "parse_mode=HTML"
144```
145 
146**Photo limits:** Maximum file size 10 MB. The photo will be compressed. For uncompressed images up to 50 MB, use `sendDocument` instead.
147 
148### sendDocument - Files and Documents
149 
150Send any file (PDF, ZIP, uncompressed images, etc.):
151 
152```bash
153# Send document by URL
154curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendDocument" \
155 -H "Content-Type: application/json" \
156 -d '{
157 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
158 "document": "https://example.com/report.pdf",
159 "caption": "Download our latest report",
160 "parse_mode": "HTML"
161 }'
162```
163 
164```bash
165# Send document from local file
166curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendDocument" \
167 -F "chat_id=${TELEGRAM_CHAT_ID}" \
168 -F "document=@/path/to/file.pdf" \
169 -F "caption=Here is the document" \
170 -F "parse_mode=HTML"
171```
172 
173**Document limits:** Maximum file size 50 MB.
174 
175### sendPoll - Polls and Quizzes
176 
177Create interactive polls for engagement:
178 
179```bash
180# Regular poll (multiple choice)
181curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendPoll" \
182 -H "Content-Type: application/json" \
183 -d '{
184 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
185 "question": "What feature should we build next?",
186 "options": ["Dark mode", "Mobile app", "API access", "Integrations"],
187 "is_anonymous": false,
188 "allows_multiple_answers": false
189 }'
190```
191 
192```bash
193# Quiz mode (one correct answer)
194curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendPoll" \
195 -H "Content-Type: application/json" \
196 -d '{
197 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
198 "question": "Which programming language was created first?",
199 "options": ["Python", "JavaScript", "C", "Java"],
200 "type": "quiz",
201 "correct_option_id": 2,
202 "explanation": "C was created by Dennis Ritchie in 1972, well before the others.",
203 "explanation_parse_mode": "HTML"
204 }'
205```
206 
207**Poll limits:** Question text 1-300 characters. 2-10 options, each 1-100 characters. Explanation up to 200 characters.
208 
209### Inline Keyboard Buttons (CTAs)
210 
211Add clickable buttons below any message for calls-to-action:
212 
213```bash
214curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
215 -H "Content-Type: application/json" \
216 -d '{
217 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
218 "text": "Check out our latest product!",
219 "parse_mode": "HTML",
220 "reply_markup": {
221 "inline_keyboard": [
222 [
223 {"text": "Visit Website", "url": "https://example.com"},
224 {"text": "View Demo", "url": "https://example.com/demo"}
225 ],
226 [
227 {"text": "Read Blog Post", "url": "https://example.com/blog"}
228 ]
229 ]
230 }
231 }'
232```
233 
234**Keyboard layout:** Each inner array is a row of buttons. Keep rows to 1-3 buttons for readability on mobile. Maximum 100 buttons total per message.
235 
236**Button types:**
237- `url` - Opens a URL in the browser
238- `callback_data` - Sends data back to the bot (requires a webhook to handle)
239- `switch_inline_query` - Prompts the user to select a chat and send an inline query
240 
241### editMessageText - Edit Existing Messages
242 
243Update a previously sent message:
244 
245```bash
246curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/editMessageText" \
247 -H "Content-Type: application/json" \
248 -d '{
249 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
250 "message_id": MESSAGE_ID_HERE,
251 "text": "Updated message text",
252 "parse_mode": "HTML"
253 }'
254```
255 
256### deleteMessage - Delete a Message
257 
258Remove a message from the channel:
259 
260```bash
261curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/deleteMessage" \
262 -H "Content-Type: application/json" \
263 -d '{
264 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
265 "message_id": MESSAGE_ID_HERE
266 }'
267```
268 
269### pinChatMessage - Pin Important Messages
270 
271Pin a message to the top of the channel or group:
272 
273```bash
274curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/pinChatMessage" \
275 -H "Content-Type: application/json" \
276 -d '{
277 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
278 "message_id": MESSAGE_ID_HERE,
279 "disable_notification": true
280 }'
281```
282 
283## Message Formatting
284 
285### HTML Mode (Recommended)
286 
287Set `"parse_mode": "HTML"` and use these tags:
288 
289| Tag | Result | Example |
290|-----|--------|---------|
291| `<b>text</b>` | **Bold** | `<b>Important</b>` |
292| `<i>text</i>` | *Italic* | `<i>Note:</i>` |
293| `<u>text</u>` | Underline | `<u>highlight</u>` |
294| `<s>text</s>` | ~~Strikethrough~~ | `<s>old price</s>` |
295| `<code>text</code>` | `Monospace` | `<code>variable</code>` |
296| `<pre>text</pre>` | Code block | `<pre>code block</pre>` |
297| `<a href="url">text</a>` | Link | `<a href="https://example.com">Click here</a>` |
298| `<tg-emoji emoji-id="ID">emoji</tg-emoji>` | Custom emoji | Premium feature |
299| `<blockquote>text</blockquote>` | Block quote | `<blockquote>Quote</blockquote>` |
300| `<tg-spoiler>text</tg-spoiler>` | Spoiler | `<tg-spoiler>Hidden</tg-spoiler>` |
301 
302**HTML escaping rules:** Replace `&` with `&amp;`, `<` with `&lt;`, `>` with `&gt;` in all text that is not part of an HTML tag. Unrecognized tags are stripped. Tags must be properly closed.
303 
304### MarkdownV2 Mode
305 
306Set `"parse_mode": "MarkdownV2"` and use this syntax:
307 
308| Syntax | Result |
309|--------|--------|
310| `*bold*` | **Bold** |
311| `_italic_` | *Italic* |
312| `__underline__` | Underline |
313| `~strikethrough~` | ~~Strikethrough~~ |
314| `` `code` `` | `Monospace` |
315| ` ```code block``` ` | Code block |
316| `[text](url)` | Link |
317| `||spoiler||` | Spoiler |
318| `>blockquote` | Block quote (start of line) |
319 
320**MarkdownV2 escaping rules:** These characters MUST be escaped with a preceding backslash outside of code blocks: `_ * [ ] ( ) ~ > # + - = | { } . !`. This makes MarkdownV2 error-prone. **HTML mode is recommended** for most use cases to avoid escaping issues.
321 
322### Formatting Tips
323 
324- Use blank lines (`\n\n`) to separate sections visually.
325- Emoji work natively in message text. No special handling needed.
326- Combine formatting: `<b><i>bold italic</i></b>` works in HTML mode.
327- Links can be hidden behind text: `<a href="https://example.com">Click here</a>`.
328- For silent messages (no notification), add `"disable_notification": true` to the request body.
329 
330## Marketing Content Templates
331 
332### Template 1: Product Announcement
333 
334```bash
335curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
336 -H "Content-Type: application/json" \
337 -d '{
338 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
339 "parse_mode": "HTML",
340 "text": "🚀 <b>Introducing [Product Name]</b>\n\n[One-sentence value proposition that answers: what is it and why should I care?]\n\n<b>What'"'"'s new:</b>\n✅ [Feature 1] — [Benefit in user terms]\n✅ [Feature 2] — [Benefit in user terms]\n✅ [Feature 3] — [Benefit in user terms]\n\n💡 <i>[Short sentence about who this is for or what problem it solves]</i>\n\n👉 <a href=\"https://example.com\">Try it now</a>",
341 "reply_markup": {
342 "inline_keyboard": [
343 [
344 {"text": "🔗 Try It Now", "url": "https://example.com"},
345 {"text": "📖 Learn More", "url": "https://example.com/blog"}
346 ]
347 ]
348 }
349 }'
350```
351 
352### Template 2: Blog Post Share
353 
354```bash
355curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
356 -H "Content-Type: application/json" \
357 -d '{
358 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
359 "parse_mode": "HTML",
360 "text": "📝 <b>New on the blog:</b> [Blog Post Title]\n\n[2-3 sentence summary that highlights the key takeaway and why the reader should care. Pull out the most surprising insight or actionable tip.]\n\n<b>Key takeaways:</b>\n🔹 [Takeaway 1]\n🔹 [Takeaway 2]\n🔹 [Takeaway 3]\n\n⏱ [X] min read",
361 "reply_markup": {
362 "inline_keyboard": [
363 [
364 {"text": "📖 Read the Full Post", "url": "https://example.com/blog/post-slug"}
365 ]
366 ]
367 }
368 }'
369```
370 
371### Template 3: Community Update / Newsletter Digest
372 
373```bash
374curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
375 -H "Content-Type: application/json" \
376 -d '{
377 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
378 "parse_mode": "HTML",
379 "text": "📢 <b>[Brand] Weekly Update — [Date]</b>\n\nHey everyone! Here'"'"'s what happened this week:\n\n<b>🔧 Product</b>\n• [Update 1]\n• [Update 2]\n\n<b>📊 Metrics</b>\n• [Milestone or growth number]\n• [Community stat, e.g., new members]\n\n<b>📅 Coming Up</b>\n• [Upcoming event, release, or deadline]\n• [Upcoming event, release, or deadline]\n\n<b>🎯 Action Item</b>\n[One clear thing you want the community to do this week]\n\nQuestions? Drop them below 👇"
380 }'
381```
382 
383### Template 4: Product Launch with Image
384 
385```bash
386# First, send the image with caption
387curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendPhoto" \
388 -H "Content-Type: application/json" \
389 -d '{
390 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
391 "photo": "https://example.com/launch-banner.jpg",
392 "caption": "🎉 <b>[Product Name] is LIVE!</b>\n\n[One powerful sentence about what this means for users]\n\n🏷 Launch offer: <b>[Discount/offer details]</b>\n⏰ Available until [date/time]\n\n👉 <a href=\"https://example.com\">Get it now</a>",
393 "parse_mode": "HTML",
394 "reply_markup": {
395 "inline_keyboard": [
396 [
397 {"text": "🛒 Get It Now", "url": "https://example.com/buy"},
398 {"text": "🎥 Watch Demo", "url": "https://example.com/demo"}
399 ],
400 [
401 {"text": "💬 Join Discussion", "url": "https://t.me/community_group"}
402 ]
403 ]
404 }
405 }'
406```
407 
408### Template 5: Engagement Poll
409 
410```bash
411curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendPoll" \
412 -H "Content-Type: application/json" \
413 -d '{
414 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
415 "question": "What should we focus on next? 🗳",
416 "options": [
417 "Feature A — [short description]",
418 "Feature B — [short description]",
419 "Feature C — [short description]",
420 "Something else (comment below!)"
421 ],
422 "is_anonymous": false,
423 "allows_multiple_answers": false
424 }'
425```
426 
427### Template 6: Knowledge Quiz
428 
429```bash
430curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendPoll" \
431 -H "Content-Type: application/json" \
432 -d '{
433 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
434 "question": "[Interesting question related to your niche]?",
435 "options": [
436 "[Option A]",
437 "[Option B]",
438 "[Option C]",
439 "[Option D]"
440 ],
441 "type": "quiz",
442 "correct_option_id": 0,
443 "explanation": "[Brief explanation of why the correct answer is correct. Include a fun fact or link to learn more.]",
444 "explanation_parse_mode": "HTML",
445 "is_anonymous": false
446 }'
447```
448 
449### Template 7: Event / Webinar Announcement
450 
451```bash
452curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
453 -H "Content-Type: application/json" \
454 -d '{
455 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
456 "parse_mode": "HTML",
457 "text": "🎙 <b>Live Event: [Event Title]</b>\n\n📅 <b>Date:</b> [Day, Month Date, Year]\n🕐 <b>Time:</b> [Time + Timezone]\n📍 <b>Where:</b> [Platform/Location]\n🎤 <b>Speaker:</b> [Name, Title]\n\n<b>What you'"'"'ll learn:</b>\n1. [Topic 1]\n2. [Topic 2]\n3. [Topic 3]\n\n🎁 <i>Bonus: [Incentive for attending, e.g., free template, recording access]</i>\n\nSpots are limited — register now 👇",
458 "reply_markup": {
459 "inline_keyboard": [
460 [
461 {"text": "📝 Register Now", "url": "https://example.com/event"}
462 ],
463 [
464 {"text": "📅 Add to Calendar", "url": "https://example.com/calendar-link"}
465 ]
466 ]
467 }
468 }'
469```
470 
471## Content Scheduling Workflow
472 
473Telegram Bot API does not have a built-in scheduling feature. Use these approaches for scheduled content delivery.
474 
475### Approach 1: Delayed Send with `sleep` (Simple)
476 
477For one-off scheduled messages from the terminal:
478 
479```bash
480# Send a message after a delay (e.g., 2 hours = 7200 seconds)
481echo "Message scheduled. Will send at $(date -v+2H '+%Y-%m-%d %H:%M:%S' 2>/dev/null || date -d '+2 hours' '+%Y-%m-%d %H:%M:%S' 2>/dev/null)"
482sleep 7200 && curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
483 -H "Content-Type: application/json" \
484 -d '{
485 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
486 "text": "Scheduled message content here",
487 "parse_mode": "HTML"
488 }'
489```
490 
491### Approach 2: `at` Command (Specific Time)
492 
493Schedule a message for a specific date and time:
494 
495```bash
496# Create the send script
497cat > /tmp/telegram_scheduled.sh << 'SCRIPT'
498source ~/.claude/.env.global 2>/dev/null
499curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
500 -H "Content-Type: application/json" \
501 -d '{
502 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
503 "text": "Your scheduled message here",
504 "parse_mode": "HTML"
505 }'
506SCRIPT
507chmod +x /tmp/telegram_scheduled.sh
508 
509# Schedule it (macOS/Linux)
510echo "bash /tmp/telegram_scheduled.sh" | at 09:00 AM tomorrow
511```
512 
513### Approach 3: Cron Job (Recurring)
514 
515For recurring messages (daily tips, weekly digests):
516 
517```bash
518# Edit crontab
519# Example: Send every weekday at 9:00 AM
520# 0 9 * * 1-5 bash /path/to/telegram_post.sh
521 
522crontab -l 2>/dev/null > /tmp/crontab_backup
523echo "0 9 * * 1-5 source ~/.claude/.env.global && curl -s -X POST 'https://api.telegram.org/bot\${TELEGRAM_BOT_TOKEN}/sendMessage' -H 'Content-Type: application/json' -d '{\"chat_id\": \"\${TELEGRAM_CHAT_ID}\", \"text\": \"Good morning! Here is your daily tip.\", \"parse_mode\": \"HTML\"}'" >> /tmp/crontab_backup
524crontab /tmp/crontab_backup
525```
526 
527### Approach 4: Batch Content Queue
528 
529Prepare multiple messages and send them with delays between each:
530 
531```bash
532# Create a batch of messages as a JSON array, then iterate
533messages=(
534 "Message 1: Monday motivation"
535 "Message 2: Tuesday tip"
536 "Message 3: Wednesday wisdom"
537)
538 
539DELAY=86400 # 24 hours between messages
540 
541for i in "${!messages[@]}"; do
542 if [ "$i" -gt 0 ]; then
543 echo "Waiting ${DELAY}s before next message..."
544 sleep ${DELAY}
545 fi
546 echo "Sending message $((i+1)) of ${#messages[@]}..."
547 curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
548 -H "Content-Type: application/json" \
549 -d '{
550 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
551 "text": "'"${messages[$i]}"'",
552 "parse_mode": "HTML"
553 }'
554 echo ""
555done
556```
557 
558## Sending to Multiple Channels
559 
560If the user manages multiple channels, accept a list of chat IDs and broadcast to all:
561 
562```bash
563# Define target channels
564CHANNELS=("-1001234567890" "-1009876543210" "@public_channel")
565 
566MESSAGE='<b>Announcement</b>\n\nThis message goes to all channels.'
567 
568for CHAT_ID in "${CHANNELS[@]}"; do
569 echo "Sending to ${CHAT_ID}..."
570 curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
571 -H "Content-Type: application/json" \
572 -d '{
573 "chat_id": "'"${CHAT_ID}"'",
574 "text": "'"${MESSAGE}"'",
575 "parse_mode": "HTML"
576 }'
577 echo ""
578 sleep 1 # Respect rate limits
579done
580```
581 
582## Channel Management
583 
584### Get Channel Info
585 
586```bash
587curl -s "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getChat?chat_id=${TELEGRAM_CHAT_ID}" | jq .
588```
589 
590### Get Member Count
591 
592```bash
593curl -s "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getChatMemberCount?chat_id=${TELEGRAM_CHAT_ID}" | jq .
594```
595 
596### Set Channel Description
597 
598```bash
599curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/setChatDescription" \
600 -H "Content-Type: application/json" \
601 -d '{
602 "chat_id": "'"${TELEGRAM_CHAT_ID}"'",
603 "description": "Your channel description here (up to 255 characters)"
604 }'
605```
606 
607## Rate Limits and Best Practices
608 
609### Telegram API Rate Limits
610 
611- **Messages to the same chat:** ~30 messages per second (but keep well below this).
612- **Messages to different chats:** ~30 messages per second total.
613- **Bulk notifications:** If sending to many users, Telegram recommends no more than 30 messages per second. Add `sleep 1` between sends when broadcasting.
614- **File uploads:** 50 MB max per file for documents, 10 MB for photos.
615 
616### Content Best Practices for Telegram Channels
617 
618| Practice | Details |
619|----------|---------|
620| Post frequency | 1-3 posts per day for active channels. More than 5 risks mute/unsubscribe. |
621| Best times | 9-11 AM and 6-8 PM in your audience's primary timezone. |
622| Message length | Keep under 1,000 characters for feed posts. Long-form is fine for articles. |
623| Media | Posts with images get 2-3x more engagement than text-only. |
624| Formatting | Use bold for key points, bullet lists for scannability, links at the end. |
625| Engagement | Ask questions. Use polls weekly. Reply to comments promptly. |
626| Silent posts | Use `disable_notification: true` for non-urgent updates to avoid annoying subscribers. |
627| Pin messages | Pin important announcements. Unpin old ones to keep the pinned area relevant. |
628| Link previews | Telegram auto-generates link previews. To disable, set `disable_web_page_preview: true`. |
629 
630### Publishing Workflow
631 
632When the user asks to post content to Telegram:
633 
6341. **Check credentials** - Verify `TELEGRAM_BOT_TOKEN` and `TELEGRAM_CHAT_ID` are set.
6352. **Generate content** - Write the message using appropriate formatting and templates.
6363. **Preview** - Show the user the exact message that will be sent, including:
637 - Message text with formatting
638 - Any inline keyboard buttons
639 - Media attachments (URL or file path)
640 - Target chat ID
6414. **Confirm** - Ask the user to approve before sending.
6425. **Send** - Execute the API call.
6436. **Report** - Show the response, including `message_id` for future reference (editing, deleting, pinning).
644 
645**Never auto-post without explicit user confirmation.**
646 
647## Gathering Requirements
648 
649Before composing a Telegram message, collect these inputs:
650 
6511. **Message type** - Text, photo, document, poll, or quiz.
6522. **Content** - What is the message about? Provide copy or topic for generation.
6533. **Target** - Which channel or group? Use `TELEGRAM_CHAT_ID` or ask for a specific one.
6544. **Formatting** - HTML or MarkdownV2. Default to HTML.
6555. **Buttons** - Any CTA buttons needed? Label and URL for each.
6566. **Media** - Any image or file to attach? URL or local file path.
6577. **Timing** - Send now, schedule for later, or recurring?
6588. **Notification** - Silent (no notification) or normal?
659 
660If the user provides a blog post URL, article, or content source, use `WebFetch` to retrieve the content and generate an appropriate Telegram post from it.
661 
662## Error Handling
663 
664Common Telegram Bot API errors and how to resolve them:
665 
666| Error | Cause | Fix |
667|-------|-------|-----|
668| `401 Unauthorized` | Invalid bot token | Regenerate token via @BotFather |
669| `400 Bad Request: chat not found` | Wrong chat ID or bot not in chat | Verify chat ID; add bot to channel as admin |
670| `403 Forbidden: bot is not a member` | Bot was removed from the channel | Re-add the bot as a channel admin |
671| `403 Forbidden: bot can't send messages` | Bot lacks posting permissions | Grant the bot "Post Messages" admin right |
672| `429 Too Many Requests` | Rate limit exceeded | Wait the `retry_after` seconds specified in the response |
673| `400 Bad Request: can't parse entities` | Malformed HTML/Markdown | Check formatting; escape special characters; switch to HTML mode |
674 
675Always check the `ok` field in the API response. If `ok` is `false`, display the `description` field to the user with guidance on how to fix the issue.
676 

Discussion