Splitting Long Telegram Posts into X Threads: Reply Chains, Partial Failures, and Per-URL Costs in 2026
A Telegram channel post can run to 4096 characters. An X Post holds 280 weighted characters on a default account. Telegram→X schedulers usually handle the gap in one of three ways: they reject the draft, they truncate it silently, or they split it into a thread. Splitting is the most useful option and the easiest to get wrong. A thread is several API writes in a fixed order, each one depending on the ID returned by the one before it, and the X API's 2026 rules on replies, mentions, and pricing all affect how that chain should be built. This is engineering guidance, not a reach or growth promise. This guide covers how to plan, approve, publish, and recover a thread from a Telegram bot. It builds on our posts about weighted character counts and idempotent publish retries.
What the X API documents for threads in 2026
Check these pages before you ship, because the self-serve tiers changed several times this year:
- A thread is a reply chain. The Create Post reference for
POST /2/tweetstakes areplyobject whose required field isin_reply_to_tweet_id. The Manage Posts overview names "create threads" as a supported use. Segment 1 is a normal Post. Each later segment replies to the ID of the segment before it. - Replies are restricted on self-serve tiers. The X API changelog entry for 2026-02-23 says programmatic replies are now only permitted when the original Post's author has "summoned" the replier by @mentioning that account or quoting one of its Posts. It also restricts programmatic @mentions and quotes. Enterprise access is not affected. A self-thread replies to your own Posts, so it is the supported case, but the same rule means a reply aimed at someone else's Post will be refused.
- Every segment is a billed write. X's pay-per-use pricing page lists Post create at $0.015 per request and Post create with a URL at $0.200 per request, a change the changelog dates to 2026-04-20.
- Limits apply per Post, not per thread. The Create Post page allows up to 4 photos, 1 animated GIF, or 1 video per Post. The Manage Posts page limits self-serve Posts to 1 cashtag each. X's counting characters page defines the 280 weighted limit, with every URL counted as 23.
Where a segment is allowed to end
Do the split on the converted X text, after entity mapping and NFC normalization, not on the raw Telegram string. The Telegram MessageEntity reference measures offsets in UTF-16 code units. If you split before converting, a link or a bold span can break across two segments and the offsets stop matching. Measure every candidate segment with the twitter-text library, not len().
A workable boundary order:
- Paragraph breaks first. Telegram authors already use blank lines to separate ideas, and those make the most natural thread breaks.
- Sentence ends next. Cut after
.,!, or?followed by whitespace. Watch for abbreviations and decimal numbers. - Word boundaries as a last resort. Never cut mid-word.
Some spans must never be split, whatever the count says: a URL (it counts 23 as a unit), a mapped entity span, an emoji or ZWJ sequence, and a hashtag or cashtag. If one of these crosses the limit, move the whole span into the next segment.
Reserve room for the counter
If you number segments ("1/5"), the counter is part of the Post text and costs weighted characters. Its width also depends on the total, which you only know after splitting. The simplest fix is two passes: split with a reserve sized for a two-digit counter (" 10/10" is 6 characters), then render the real counters and re-count every segment. If any segment fails the re-count, split again. Many operators set a hard cap, say 8 segments, and send anything longer back to the author instead of publishing a wall of replies.
Plan the whole thread before the first request
A thread is one approval but many writes. Store a thread plan record before anything is sent:
- a thread job ID, plus the Telegram
chat_idandmessage_idit came from; - an ordered list of segments, each with its final text, its weighted count, any media IDs, and a content hash;
- per-segment state (
planned,sending,posted,retry,blocked) and the X Post ID once posted; - the twitter-text version and the account's character limit at planning time.
The operator approves the plan, meaning every segment exactly as it will appear. If they edit the Telegram source afterward, throw the plan away and split again. Never patch one segment by hand, because its neighbours' boundaries and counters will no longer match. The approval gate should show all segments in a single Telegram message with their counts, plus the estimated cost described below.
Publishing in order, and recovering from partial failure
Publish strictly in sequence from one worker holding a lease on the thread job. Parallel sends are impossible anyway, because segment n needs the ID returned for segment n−1. For each segment:
- Mark it
sendingand sendPOST /2/tweetswithreply.in_reply_to_tweet_idset to the previous segment's stored ID (no reply for segment 1). - On success, store the returned
data.idand mark itpostedbefore moving on. That stored ID is the only thing that lets you resume. - On 429 or 5xx, back off and retry the same segment, using the patterns in our retry and dead-letter post. If a timeout leaves the result unknown, check the account's recent Posts for the segment's hash before re-sending, so a retry doesn't create a duplicate reply.
- On 403 for a reply, mark it
blockedand stop. Under the February 2026 rules a refused reply is a policy decision, and retrying will not change it. Alert the operator in Telegram.
The awkward case is a half-published thread: segments 1–3 are live and segment 4 failed for good. Give the operator three explicit buttons rather than guessing:
- Resume from segment 4 once the cause is fixed. The chain continues from the stored ID of segment 3.
- Close out by publishing a short final reply that links to the full text on your site, if the remainder can't go out.
- Withdraw by deleting the posted segments in reverse order with DELETE /2/tweets/:id, which only works on Posts the authenticated user wrote.
Log whichever option was chosen against the thread job, so the duplicate-content guard doesn't later block a corrected re-run as a repeat.
Where the link goes, and why it now matters for cost
Under the pricing above, a URL changes what a segment costs, not just its length. Take a six-segment thread. If every segment carries the same link, that is 6 × $0.200 = $1.20. Put the link once, in the last segment, and it is 5 × $0.015 + $0.200 = $0.275.
The same per-Post thinking applies to the rest of the payload:
- Albums. A Telegram album (
sendMediaGroupaccepts 2–10 items, grouped bymedia_group_id) can hold more photos than one X Post. Spread photos across segments, at most 4 per segment, and upload each one through the media pipeline before the thread starts, so a failed upload can't strand a half-posted chain. - Mentions and cashtags. Given the 2026 restrictions on programmatic @mentions, strip or rewrite handles carried over from Telegram rather than spreading them through every segment. Allow at most one cashtag per segment on self-serve tiers.
- Budgets. Count a thread as n writes in your rate-limit and credit budget, and reserve all n before segment 1 goes out. A thread that runs out of credits halfway is the half-published case above.
Test cases worth keeping in CI
- A URL that straddles the boundary, which should move whole to the next segment.
- A simulated 403 on segment 2, which should leave the job
blockedwith segment 1's ID stored and no retries. - A worker crash after segment 3 is posted, which should resume at segment 4 without re-posting the root.
Practical checklist
- Split converted, NFC-normalized text, and count each segment with twitter-text.
- Split on paragraphs, then sentences, then words. Never cut through URLs, entities, emoji, or tags.
- Store a full thread plan and have the operator approve every segment and the estimated cost.
- Publish sequentially from one leased worker and store each Post ID before sending the next segment.
- Retry on 429 and 5xx. Stop on 403 and give the operator resume, close-out, or withdraw options.
- Put the link in one segment and limit each segment to 4 photos and 1 cashtag.
Key takeaways
- A thread is an ordered chain of
POST /2/tweetscalls, each replying to the previous segment's ID. The stored IDs are your recovery path. - Since 2026-02-23, self-serve replies are limited to conversations where you were summoned. Self-threads are the supported case, and a 403 on a reply means stop, not retry.
- Each segment is billed, and Posts with a URL cost far more, so link placement is a cost decision.
- Operators should approve the exact segments that will be published, never a raw Telegram message.
Endpoint behavior, reply restrictions, and prices summarized here come from X's public developer documentation, changelog, and pricing page, and from the Telegram Bot API reference, as of 2026-10-07. They change often, so confirm them on docs.x.com and core.telegram.org before relying on them. No affiliate links. Last verified 2026-10-07.