# Send a message to a Telegram channel with the API
URL: https://skedcast.com/developers/guides/publish-to-telegram-api

Connect the channel first. Each connected Telegram account is one channel (your bot token plus the channel's @username or -100… id), and a post goes to the channel its account was connected as. The bot must be an admin of the channel with "Post Messages" rights. To post to another channel, connect that channel too.

## What do you need before you publish?
You need one connected account for the platform. Connect it in the SkedCast console. If a client owns the account, create a connect link with `POST /v1/clients/{id}/connect-invites` and send it to them. They authorize from that page without a SkedCast login.
`GET /v1/accounts` lists the connected accounts with their ids. Pass that id in `targets.accountIds` below.

## Schedule a Telegram channel message from code, through your own bot.
![Illustration: a code editor card with a send arrow and a clock badge, linked by a dotted line through a small bot icon to a paper-plane channel card full of message bubbles.](https://skedcast.com/images/articles/developers-publish-to-telegram-api/hero.webp)

*Schedule a Telegram channel message from code, through your own bot.*

## How do you schedule a Telegram post with the API?
```bash
curl -X POST https://api.skedcast.com/v1/posts \
  -H "Authorization: Bearer sked_live_YOUR_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "<clientId>",
    "content": "Launch day is here 🚀",
    "mediaIds": ["<mediaAssetId>"],
    "targets": { "mode": "selection", "accountIds": ["<telegramAccountId>"] },
    "schedule": { "type": "at", "scheduledAt": "2030-01-15T15:00:00Z" }
  }'
```

## Which Telegram fields can you set?
Put everything platform-specific in one `variants` entry with `"platform": "telegram"` and an `overrides` object. Send only `telegram` keys on a `telegram` variant. SkedCast reads the keys in the table below and ignores the rest.

## Reference
Field | Type | Values / default | Notes
`parseMode` | enum | `MarkdownV2` \| `HTML` \| `Markdown` | How the message text is parsed.
`disableNotification` | boolean | `false` | Post without a notification sound.
`protectContent` | boolean | `false` | Prevent forwarding and saving.
`firstComment` | string | — | Posted as a reply to the published message in the same chat. Best-effort: a failed comment never fails the post. The outcome is reported as `firstCommentIssue` on `GET /v1/post-targets/{id}`.

## Unknown keys are ignored without an error
A misspelled or unknown key in `overrides` is not an error and not a warning. It is dropped, so check the field names in the table above, especially a required one.
A YouTube-only key (such as `privacyStatus`, `captions` or `chapters`) sent on another platform's variant is ignored and returns an `override_key_wrong_platform` warning.

## How do you add Telegram-specific settings?
```json
{
  "clientId": "<clientId>",
  "content": "*New release* is live.",
  "mediaIds": [],
  "targets": { "mode": "selection", "accountIds": ["<telegramChannelAccountId>"] },
  "variants": [
    { "platform": "telegram", "overrides": { "parseMode": "MarkdownV2" } }
  ],
  "schedule": { "type": "at", "scheduledAt": "2030-01-15T15:00:00Z" }
}
```

## How do you connect a Telegram channel?
With a bot you own, in four steps. Telegram's Bot API only lets a bot post to a channel where it is an administrator with the Post Messages right (`can_post_messages`).
- Create a bot with @BotFather in Telegram and copy its token.
- Add the bot to your channel as an administrator, with Post Messages turned on.
- In the SkedCast console, connect Telegram with the bot token and the channel's @username (or its -100… id).
- Call `GET /v1/accounts` and use the new channel account's id in `targets.accountIds`.

## What are Telegram's message limits?
Limit | Value
Message text | 4096 characters
Caption once media is attached | 1024 characters
Media per post | Up to 10 (sent as one album)
Formatting | `parseMode`: MarkdownV2, HTML or Markdown

## No native scheduling
Telegram has no native scheduling, so SkedCast always publishes Telegram targets at the scheduled time. `scheduleMode: "native"` has no effect here. It applies only to Facebook and YouTube targets.

## How do you check that the post published?
Publishing creates one post target per account. `GET /v1/post-targets/{id}` (or `GET /v1/posts/{id}`) reports `status`, plus `externalId` (Telegram's own post id) and `permalink` (its public URL) once published. To avoid polling, subscribe to the `target.published` and `target.failed` webhooks (see the webhooks guide).

## From a bot token to a scheduled Telegram message.
![Diagram: create a bot with BotFather, make it a channel admin with Post Messages, connect the channel in SkedCast, then POST /v1/posts with the channel account and check the post target.](https://skedcast.com/images/articles/developers-publish-to-telegram-api/telegram-api-flow.svg)

*From a bot token to a scheduled Telegram message.*

## FAQ
**Q: Why does my Telegram post fail with a permissions error?**
A: The bot is not an admin with Post Messages rights in that channel. See the requirement above, then reconnect the channel.

**Q: How long can a Telegram message be?**
A: 4096 characters of text, or 1024 as a caption once a photo, video or document is attached. SkedCast checks the limit when you compose and returns a 422 before anything is scheduled.

**Q: Can I post silently or stop forwarding?**
A: Yes. Set disableNotification: true to post without a notification sound, and protectContent: true to stop subscribers forwarding and saving the message.

**Q: Can one bot post to more than one channel?**
A: Yes. Connect each channel as its own account with the same bot token, then put the channel accounts you want in targets.accountIds. Each post goes to the channel its account was connected as. There is no per-post destination field.
