Telegram API
Post to Telegram channels and groups with Late API - Text, images, videos, and media albums
Quick Start
Post to a Telegram channel or group:
curl -X POST https://getlate.dev/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Hello from Late API! Check out our latest update.",
"platforms": [
{"platform": "telegram", "accountId": "YOUR_ACCOUNT_ID"}
],
"publishNow": true
}'const response = await fetch('https://getlate.dev/api/v1/posts', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
content: 'Hello from Late API! Check out our latest update.',
platforms: [
{ platform: 'telegram', accountId: 'YOUR_ACCOUNT_ID' }
],
publishNow: true
})
});
const { post } = await response.json();
console.log('Posted to Telegram!', post._id);import requests
response = requests.post(
'https://getlate.dev/api/v1/posts',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
json={
'content': 'Hello from Late API! Check out our latest update.',
'platforms': [
{'platform': 'telegram', 'accountId': 'YOUR_ACCOUNT_ID'}
],
'publishNow': True
}
)
post = response.json()
print(f"Posted to Telegram! {post['post']['_id']}")Connect a Telegram Account
Late provides a managed bot (@LateScheduleBot) for Telegram integration. No need to create your own bot - just add Late's bot to your channel or group.
Option 1: Access Code Flow (Recommended)
This is the easiest way to connect a Telegram channel or group.
Step 1: Generate an Access Code
curl -X GET "https://getlate.dev/api/v1/connect/telegram?profileId=YOUR_PROFILE_ID" \
-H "Authorization: Bearer YOUR_API_KEY"const response = await fetch(
'https://getlate.dev/api/v1/connect/telegram?profileId=YOUR_PROFILE_ID',
{
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}
);
const { code, botUsername, instructions } = await response.json();
console.log(`Your access code: ${code}`);
console.log(`Bot to message: @${botUsername}`);response = requests.get(
'https://getlate.dev/api/v1/connect/telegram',
params={'profileId': 'YOUR_PROFILE_ID'},
headers={'Authorization': 'Bearer YOUR_API_KEY'}
)
data = response.json()
print(f"Your access code: {data['code']}")
print(f"Bot to message: @{data['botUsername']}")Response:
{
"code": "LATE-ABC123",
"expiresAt": "2025-01-15T12:30:00.000Z",
"expiresIn": 900,
"botUsername": "LateScheduleBot",
"instructions": [
"1. Add @LateScheduleBot as an administrator in your channel/group",
"2. Open a private chat with @LateScheduleBot",
"3. Send: LATE-ABC123 @yourchannel (replace @yourchannel with your channel username)",
"4. Wait for confirmation - the connection will appear in your dashboard",
"Tip: If your channel has no public username, forward a message from it along with the code"
]
}Step 2: Add the Bot to Your Channel/Group
For Channels:
- Go to your channel settings
- Add
@LateScheduleBotas an Administrator - Grant permission to Post Messages
For Groups:
- Add
@LateScheduleBotto the group - Make the bot an Administrator (required for posting)
Step 3: Send the Access Code
- Open a private chat with @LateScheduleBot
- Send your access code with your channel:
LATE-ABC123 @yourchannel - For private channels without a username, forward any message from the channel to the bot along with the code
Step 4: Poll for Connection Status
curl -X PATCH "https://getlate.dev/api/v1/connect/telegram?code=LATE-ABC123" \
-H "Authorization: Bearer YOUR_API_KEY"// Poll every 3 seconds until connected
const checkStatus = async (code) => {
const response = await fetch(
`https://getlate.dev/api/v1/connect/telegram?code=${code}`,
{
method: 'PATCH',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}
);
return response.json();
};
// Example polling loop
const pollConnection = async (code) => {
while (true) {
const status = await checkStatus(code);
if (status.status === 'connected') {
console.log(`Connected to ${status.chatTitle}!`);
console.log(`Account ID: ${status.account._id}`);
return status.account;
}
if (status.status === 'expired') {
throw new Error('Access code expired. Generate a new one.');
}
// Wait 3 seconds before next check
await new Promise(resolve => setTimeout(resolve, 3000));
}
};import time
def check_status(code):
response = requests.patch(
'https://getlate.dev/api/v1/connect/telegram',
params={'code': code},
headers={'Authorization': 'Bearer YOUR_API_KEY'}
)
return response.json()
# Poll until connected
def poll_connection(code):
while True:
status = check_status(code)
if status['status'] == 'connected':
print(f"Connected to {status['chatTitle']}!")
print(f"Account ID: {status['account']['_id']}")
return status['account']
if status['status'] == 'expired':
raise Exception('Access code expired. Generate a new one.')
time.sleep(3) # Wait 3 secondsStatus Response (Pending):
{
"status": "pending",
"expiresAt": "2025-01-15T12:30:00.000Z",
"expiresIn": 542
}Status Response (Connected):
{
"status": "connected",
"chatId": "-1001234567890",
"chatTitle": "My Channel",
"chatType": "channel",
"account": {
"_id": "64e1f0a9e2b5af0012ab34cd",
"platform": "telegram",
"username": "mychannel",
"displayName": "My Channel"
}
}Option 2: Direct Connection (Power Users)
If you already know your chat ID and the Late bot is already an administrator in your channel/group:
curl -X POST https://getlate.dev/api/v1/connect/telegram \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"profileId": "YOUR_PROFILE_ID",
"chatId": "-1001234567890"
}'const response = await fetch('https://getlate.dev/api/v1/connect/telegram', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
profileId: 'YOUR_PROFILE_ID',
chatId: '-1001234567890' // or '@mychannel' for public channels
})
});
const { account } = await response.json();
console.log('Connected:', account._id);response = requests.post(
'https://getlate.dev/api/v1/connect/telegram',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
json={
'profileId': 'YOUR_PROFILE_ID',
'chatId': '-1001234567890' # or '@mychannel' for public channels
}
)
data = response.json()
print(f"Connected: {data['account']['_id']}")Response:
{
"message": "Telegram channel connected successfully",
"account": {
"_id": "64e1f0a9e2b5af0012ab34cd",
"platform": "telegram",
"username": "mychannel",
"displayName": "My Channel",
"isActive": true,
"chatType": "channel"
}
}Finding Your Chat ID
For Public Channels:
- Use the channel username with
@prefix:@mychannel
For Private Channels:
- Forward a message from the channel to @userinfobot
- The bot will reply with the numeric chat ID (starts with
-100)
For Groups:
- Add @userinfobot to your group temporarily
- It will display the group's chat ID (negative number)
- Remove the bot after getting the ID
Overview
Telegram supports text messages, images, videos, and mixed media albums. Posts can be sent to channels or groups where the Late bot has posting permissions.
| Feature | Support |
|---|---|
| Text posts | Up to 4096 characters |
| Media captions | Up to 1024 characters |
| Images | Up to 10 per album |
| Videos | Up to 10 per album |
| Mixed media | Images and videos in same album |
| Scheduling | Yes |
| Analytics | Not available (platform limitation) |
Media Requirements
Images
| Property | Requirement |
|---|---|
| Max Images | 10 per album |
| Formats | JPEG, PNG, GIF, WebP |
| Max File Size | 10 MB |
| Max Resolution | 10000 × 10000 px |
Videos
| Property | Requirement |
|---|---|
| Max Videos | 10 per album |
| Formats | MP4, MOV |
| Max File Size | 50 MB |
| Max Duration | No limit |
| Codec | H.264 recommended |
Platform-Specific Options
Telegram supports several message options:
curl -X POST https://getlate.dev/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "<b>Important Update!</b>\n\nCheck out our <a href=\"https://example.com\">new feature</a>.",
"platforms": [{
"platform": "telegram",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"parseMode": "HTML",
"disableWebPagePreview": false,
"disableNotification": false,
"protectContent": false
}
}],
"publishNow": true
}'const response = await fetch('https://getlate.dev/api/v1/posts', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
content: '<b>Important Update!</b>\n\nCheck out our <a href="https://example.com">new feature</a>.',
platforms: [{
platform: 'telegram',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: {
parseMode: 'HTML',
disableWebPagePreview: false,
disableNotification: false,
protectContent: false
}
}],
publishNow: true
})
});response = requests.post(
'https://getlate.dev/api/v1/posts',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
json={
'content': '<b>Important Update!</b>\n\nCheck out our <a href="https://example.com">new feature</a>.',
'platforms': [{
'platform': 'telegram',
'accountId': 'YOUR_ACCOUNT_ID',
'platformSpecificData': {
'parseMode': 'HTML',
'disableWebPagePreview': False,
'disableNotification': False,
'protectContent': False
}
}],
'publishNow': True
}
)Available Options
| Option | Type | Default | Description |
|---|---|---|---|
parseMode | string | HTML | Text formatting mode: HTML, Markdown, or MarkdownV2 |
disableWebPagePreview | boolean | false | Disable link preview generation for URLs |
disableNotification | boolean | false | Send message silently (no notification sound) |
protectContent | boolean | false | Prevent message from being forwarded or saved |
Text Formatting
HTML Mode (Default)
<b>bold</b>
<i>italic</i>
<u>underline</u>
<s>strikethrough</s>
<code>inline code</code>
<pre>code block</pre>
<a href="https://example.com">link</a>Markdown Mode
*bold*
_italic_
[link](https://example.com)
`inline code`MarkdownV2 Mode
*bold*
_italic_
__underline__
~strikethrough~
||spoiler||
`inline code`Note: MarkdownV2 requires escaping special characters:
_,*,[,],(,),~,`,>,#,+,-,=,|,{,},.,!
Posting with Media
Single Image
curl -X POST https://getlate.dev/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Check out this photo!",
"mediaItems": [
{"url": "https://example.com/image.jpg"}
],
"platforms": [
{"platform": "telegram", "accountId": "YOUR_ACCOUNT_ID"}
],
"publishNow": true
}'const response = await fetch('https://getlate.dev/api/v1/posts', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
content: 'Check out this photo!',
mediaItems: [
{ url: 'https://example.com/image.jpg' }
],
platforms: [
{ platform: 'telegram', accountId: 'YOUR_ACCOUNT_ID' }
],
publishNow: true
})
});response = requests.post(
'https://getlate.dev/api/v1/posts',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
json={
'content': 'Check out this photo!',
'mediaItems': [
{'url': 'https://example.com/image.jpg'}
],
'platforms': [
{'platform': 'telegram', 'accountId': 'YOUR_ACCOUNT_ID'}
],
'publishNow': True
}
)Media Album (Multiple Images/Videos)
{
"content": "Our latest product gallery!",
"mediaItems": [
{"url": "https://example.com/image1.jpg"},
{"url": "https://example.com/image2.jpg"},
{"url": "https://example.com/video.mp4"},
{"url": "https://example.com/image3.jpg"}
],
"platforms": [
{"platform": "telegram", "accountId": "YOUR_ACCOUNT_ID"}
],
"publishNow": true
}Note: Media albums support up to 10 items. Images and videos can be mixed in the same album.
Channel vs Group Posts
| Destination | Author Display |
|---|---|
| Channel | Channel name and logo |
| Group | Bot name (LateScheduleBot) |
When posting to a channel, the post appears as if sent by the channel itself. When posting to a group, the post shows as sent by the Late bot.
Character Limits
| Content Type | Limit |
|---|---|
| Text-only messages | 4096 characters |
| Media captions | 1024 characters |
Silent Messages
Send messages without triggering notification sounds:
{
"content": "Late night update - didn't want to wake anyone!",
"platforms": [{
"platform": "telegram",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"disableNotification": true
}
}]
}Protected Content
Prevent users from forwarding or saving your content:
{
"content": "Exclusive content for channel members only!",
"platforms": [{
"platform": "telegram",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"protectContent": true
}
}]
}Analytics Limitations
Important: Telegram analytics are not available via API. The Telegram Bot API does not expose message analytics (views, forwards, reactions).
- View counts are only visible to channel admins directly in the Telegram app
- This is a Telegram platform limitation that affects all third-party tools
- Message IDs are returned for tracking purposes
Common Issues
"Bot is not a member of the channel"
- Ensure
@LateScheduleBotis added to the channel/group as an administrator - Grant the bot permission to post messages
"Message is too long"
- Text-only messages: max 4096 characters
- Media captions: max 1024 characters
- Split long content into multiple messages
"Wrong file identifier/HTTP URL specified"
- Ensure media URLs are publicly accessible
- Use HTTPS URLs
- Check that the URL directly points to the file (no redirects)
"Can't parse entities"
- Check your HTML/Markdown syntax
- Ensure special characters are properly escaped in MarkdownV2
- Verify all tags are properly closed in HTML mode
Media not displaying
- Verify file format is supported
- Check file size limits (10 MB for images, 50 MB for videos)
- Ensure the URL is publicly accessible without authentication
"Access code expired"
- Access codes are valid for 15 minutes
- Generate a new code with
GET /v1/connect/telegram
Related API Endpoints
- Connect Telegram Account — Access code connection flow
- Create Post — Post creation and scheduling
- Upload Media — Image and video uploads