turboyap

Telegram text message API

Send text posts to a Telegram channel or group through an API or MCP server: the 4,096-character limit, link previews, connecting Turboyap's bot, example requests, and errors with fixes.

Beta: you can connect a Telegram account and post to it through the API in early access today. It hasn't been proven with a real production post yet. The @turboyap/sdk and @turboyap/mcp packages call the same API. Test mode runs the same requests against a simulated Telegram account.

What a Telegram text message is

A Telegram text message is a post of up to 4,096 characters in a channel or group. Telegram's Bot API sends it with sendMessage. In Turboyap it's type: "text", and the caption is the message.

Turboyap posts through its own bot, which you add as an administrator of your channel or group. Pass link to choose which URL gets the link preview.

Limits

What Telegram accepts for this post type. Turboyap's planner checks every one of these before a post is scheduled (the same data as platform rules), and each value links to the Telegram documentation it comes from.

LimitValueSource
MediaNone (text only)Telegram Bot API: sendMessage
Text4,096 characters (sent as text)Telegram Bot API: sendMessage
Link cardYes: pass link, sent as link_preview_options.urlTelegram Bot API: sendMessage
Rate limitAbout 1 message per second in a chat, and 20 per minute in a groupTelegram bots FAQ: hitting limits
Rate limitOn a flood-control error Turboyap waits the retry_after Telegram sendsTelegram bots FAQ: hitting limits

Compare with other platforms in the social media API limits tracker.

Connect a Telegram account

  1. In Telegram, open your channel or group, then Administrators, then Add Admin, and choose the Turboyap bot. The connect page and GET /v1/connect_methods show its exact @username.
  2. Give it permission to post messages (channels) or send messages (groups). It needs nothing else.
  3. Connect the channel's public @username or t.me link. For a private channel, use its numeric chat ID: open it in Telegram Web (web.telegram.org/a) and copy the number after # in the address bar. It starts with -100.

Turboyap checks that the bot can post there before it saves the account. A human with a live key can connect directly with POST /v1/accounts and { "platform": "telegram", "chat": "@yourchannel" }. Turboyap posts to channels and groups, not to private chats with a person.

An agent never handles the account's credentials: it calls the create_connect_link MCP tool (or POST /v1/connect_links with the platform) and sends the 7-day link to the person who owns the account, whose page walks them through these steps. New accounts start on autonomy level 1, so agent posts wait for approval.

Example requests

All three do the same thing: preview the post with a dry run, then schedule it. The idempotency key makes retries safe: send the same request again with the same key and you get the original post back, not a second one.

Early access: api.turboyap.com is open to early-access users only, and @turboyap/sdk and @turboyap/mcp aren't on npm yet. These examples show the API as built.

curl

# Preview. Remove "dry_run" to create and schedule the post.
curl https://api.turboyap.com/v1/posts \
  -H "Authorization: Bearer $TURBOYAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "text",
    "caption": "New guide: how to tell ice cream from frozen dairy dessert. https://example.com/labels",
    "link": { "url": "https://example.com/labels" },
    "targets": [{ "account_id": "acct_telegram…" }],
    "schedule_at": "2026-10-20T18:00:00-04:00",
    "idempotency_key": "telegram-text-message-2026-10-20",
    "dry_run": true
  }'

TypeScript with @turboyap/sdk

import { TurboyapClient } from "@turboyap/sdk";

const ty = new TurboyapClient({ apiKey: process.env.TURBOYAP_API_KEY! });
const account = (await ty.listAccounts()).find((a) => a.platform === "telegram")!;

const post = {
  type: "text" as const,
  caption: "New guide: how to tell ice cream from frozen dairy dessert. https://example.com/labels",
  link: { "url": "https://example.com/labels" },
  targets: [{ account_id: account.id }],
  schedule_at: "2026-10-20T18:00:00-04:00",
  idempotency_key: "telegram-text-message-2026-10-20",
};

// Preview first: every problem comes back with a fix.
const preview = await ty.createPost({ ...post, dry_run: true });
if (!preview.ok) throw new Error(preview.errors.map((e) => `${e.code}: ${e.fix}`).join("\n"));

const { post: created } = await ty.createPost(post);
console.log(created.targets[0]?.status, created.targets[0]?.next_step);

Claude Code (MCP)

Add the Turboyap MCP server once, with an agent key from your workspace:

claude mcp add turboyap -e TURBOYAP_API_KEY=ty_agent_… -- npx -y @turboyap/mcp

Then ask:

Post our new label guide to the Telegram channel tomorrow at 9am ET, with the preview for https://example.com/labels. Dry-run first and fix anything Telegram rejects.

The agent calls list_accounts, get_platform_rules, create_post with dry_run: true, applies any fixes, calls create_post again to schedule, and reports each account's next_step from get_post. The same server works in Cursor; see the MCP quickstart.

How publishing works

When the scheduled time arrives, Turboyap's bot sends the post with sendMessage. Publishing is immediate: the target moves scheduled → publishing → published. platform_url links to the message in channels and supergroups; basic groups have no message links. Telegram's Bot API has no idempotency key, so if a response is lost Turboyap marks the target unknown_outcome instead of posting again.

Text posts take 4,096 characters; captions on photos and albums take 1,024.

Pass link on a text post to choose which URL gets the link preview.

Video and documents aren't supported yet: Turboyap's media pipeline takes images only.

Common errors and fixes

Every error has a code, the field that caused it, and a fix an agent can apply without asking you. A request with several problems returns all of them in issues; a dry run returns them without creating anything.

CodeWhenFix
too_many_itemsMedia ids on a text post. Text posts take no media.Use type: "image" (one image) or "slideshow" (several) to post media, or remove media_ids.
invalid_requestA text post with no text and no link.Set caption to the text of the post.
caption_too_longText over 4,096 characters.Shorten it, or pass targets[i].caption with a version under 4,096 characters.
schedule_in_pastschedule_at is more than a minute in the past.Use "now" or a future time with a timezone offset.
account_unavailableThe Telegram account needs to be reconnected.Reconnect the account, then retry.
unsupported_platformA target is on a platform Turboyap doesn't support yet.Remove that target. Supported platforms: tiktok, instagram, bluesky (beta), telegram (beta), discord (beta).
insufficient_scopeThe key lacks a scope the request needs, such as publish for schedule_at: "now" (agent keys don't have it by default).Schedule a future time instead of "now", omit schedule_at to save a draft, or use a key with the missing scope. GET /v1/keys/me lists the key's scopes.
account_not_allowedThe key is limited to some accounts, and a target isn't one of them.Remove that target, or use a key whose account_ids include the account.
forbidden_scopeAn agent key tries to approve or reject a post.A human approves agent posts. To skip review for an account, a human sets its autonomy level to 3.
unknown_outcomeTurboyap stopped partway through publishing (for example, a restart) and can't confirm whether the post went out. It doesn't publish it again.Check the account on the platform. If the post isn't there, create it again.

Errors from Telegram itself appear on the target's error with Telegram's own code. Turboyap retries rate limits and temporary failures with backoff, and marks the account for reconnection when the bot can no longer post to the chat.

Approval and audit

Read more in the autonomy dial.

FAQ

How long can a Telegram message be through the Bot API?

4,096 characters for a text message. Captions on photos and albums are shorter: 1,024 characters. Turboyap checks the right limit for each post type before scheduling.

How do I post to a Telegram channel through an API?

Add a bot as an administrator of the channel with permission to post, then call the Bot API's sendMessage with the channel's @username or chat ID. With Turboyap you add the Turboyap bot, connect the channel once, then schedule posts with POST /v1/posts or the MCP server.

Can I choose which link gets the preview in a Telegram post?

Yes. Pass link with a url, and Turboyap sends it as link_preview_options.url, so Telegram previews that page even when the text has other links.

Does it work with private channels and groups?

Yes. Connect a private channel by its numeric chat ID, which starts with -100: open the channel in Telegram Web (web.telegram.org/a) and copy the number after # in the address bar. Groups work too, as long as the bot can send messages there.