GLOSSARY

What is a Forum Topic?

A forum topic is a named thread inside a Telegram supergroup that has forum mode enabled, addressed by a message_thread_id which is simply the message ID of the service message that created the topic. Once a group has topics, the chat ID alone no longer identifies a conversation: the real key is the chat and the thread together.

Free forever plan · No credit card required · Cancel anytime

Quick definition

A forum topic is a named thread inside a Telegram supergroup that has forum mode enabled, addressed by a message_thread_id which is simply the message ID of the service message that created the topic. Once a group has topics, the chat ID alone no longer identifies a conversation: the real key is the chat and the thread together.

In a single sentence: one group, many conversations, and a second half to every key you thought was complete.

What it means

A large Telegram group has one stream. Everything anyone says lands in the same place, in order, and a community of a few thousand people produces a chat nobody can follow.

Forum mode is Telegram's answer. Switched on for a supergroup, it splits the group into named threads called topics, each with its own title, colour, icon and unread state. Members pick a topic and talk inside it, and the group's home screen becomes a list of conversations rather than a wall of messages.

Under the hood the mechanism is elegantly cheap. Creating a topic posts a forum_topic_created service message into the group, and the ID of that service message becomes the topic's message_thread_id. Nothing new was invented: a topic is a message that other messages point at.

That has two consequences worth remembering. Topic IDs are message IDs, so they are sparse and unique only within their own chat. And the General topic, created automatically with the forum itself, is thread 1.

The key that stops being unique

Here is the part that quietly breaks integrations, and it has nothing to do with the API surface.

Almost every Telegram tool ever written assumes chat_id identifies a conversation. Conversations are keyed by it, assignments hang off it, unread counts aggregate over it, and automations trigger on it. In a forum group that assumption is simply false. One chat_id can hold a hundred unrelated conversations, and treating them as one produces an inbox entry where a support question about invoicing and a discussion about next month's meetup are the same thread.

The correct key is (chat_id, message_thread_id), with the thread defaulting to General when absent. Retrofitting that into a CRM after the fact is a migration, not a patch, because it changes the primary key of the busiest table in the system.

The reply that lands in the wrong place

The other classic failure is a one-line omission with a very visible symptom.

When a bot answers a message in a forum group and passes only chat_id, the reply goes to General. Not to the thread the question came from, not to an error, just to General. The customer sits in their topic waiting while the answer appears somewhere else entirely, and nothing in your logs suggests a problem.

The fix is to echo message_thread_id from the incoming message on every outgoing one. It is a single field, and it is the first thing to check whenever a bot appears to be answering into the void.

The other message_thread_id

There is a second, unrelated use of the same field name, and it catches people who only ever read the forum documentation.

When a channel has a linked discussion group, each channel post gets its own comment thread in that group, and messages in that thread also carry a message_thread_id. The group is not a forum, no topic exists, and none of the forum methods apply.

The field that disambiguates is is_topic_message on the message. Branch on that, not on whether message_thread_id happens to be present, or your code will try to manage topics in a group that has none.

Permissions and constraints

Forum mode is not available to every group. The chat has to be a supergroup, and Telegram gates the toggle behind a minimum member count, 100 at the time of writing, so a brand new group cannot turn it on straight away.

Topic management is its own permission rather than part of general admin power. Administrators can hold a manage-topics right, and ordinary members can have that right granted or restricted individually, which is how a community lets trusted contributors open threads without handing them the ability to ban people.

Smaller details that shape what you can build: a topic name is 1 to 128 characters, and the icon colour is not free-form. Telegram publishes six permitted values and rejects anything else, which means a "pick your brand colour" feature is not implementable. Topics can also carry a custom emoji as an icon, which is where visual differentiation actually lives.

Why it matters

Topics are what turned Telegram groups into a workable support and operations surface, and that is exactly why they matter to a CRM.

A single forum group with a topic per customer gives an agency the shape they used to build out of a dozen separate group chats: shared membership, one set of permissions, one history, and a thread per client that can be closed when the work is done. Closing rather than deleting is the important habit, because a closed topic keeps its history and can be reopened, while a deleted one takes every message with it.

For the CRM the payoff is routing. Each topic can map to a pipeline, an assignee, or a service-level target. Inbound questions land in the right queue without anybody triaging them, because the customer chose the thread when they asked. That only works if the integration treats threads as first-class objects rather than flattening them back into the parent chat.

Common mistakes

  • Keying conversations on chat_id alone. In a forum every thread collapses into one record, and the inbox becomes unusable.
  • Forgetting message_thread_id on replies. Answers land in General while the customer waits in their topic.
  • Branching on the presence of message_thread_id. Discussion-group comment threads carry it too. Use is_topic_message.
  • Deleting topics to tidy up. Deleting destroys the history. Closing preserves it and is reversible.
  • Sending an arbitrary icon colour. Only six values are accepted. Anything else is rejected.
  • Ignoring topic service messages. Renames, closes and reopens arrive as messages in the group, and a thread list that never reads them drifts out of date.

Related concepts

  • Supergroup: the only chat type that can become a forum.
  • Peer ID: the other half of the conversation key, and why it is no longer sufficient alone.
  • Telegram Bot API: the methods and service messages that manage topics.
  • Webhook: how topic events reach your CRM.
  • AI agent: a per-topic agent can be scoped to one thread instead of a whole group.
  • Invite link hash: how members reach a private forum in the first place.

How Pinlyx handles it

Pinlyx keys conversations on the chat and the thread together, so a forum group with forty topics becomes forty conversations rather than one crowded record. Replies always carry the originating thread, which means an answer arrives where the question was asked. Topic service messages are read, so renames and closures are reflected in the inbox without anyone refreshing anything, and is_topic_message is what decides whether a thread is a real topic or a channel comment thread. Threads can be routed to different pipelines and owners, which is how one community group ends up feeding several queues inside the same Telegram CRM.

Cheat sheet · the one-field bug

Where replies go, and why.

One omitted field is the difference between answering the customer and posting into a general channel nobody is reading.

// Inbound message from a forum group
{
  "message_id": 91422,
  "message_thread_id": 91388,     // the topic, and also a message id
  "is_topic_message": true,       // this is a REAL topic, not a comment thread
  "chat": { "id": -1001234567890, "type": "supergroup", "is_forum": true },
  "from": { "id": 998812345, "first_name": "Customer" },
  "text": "Invoice 4471 has the wrong VAT rate"
}

// WRONG: lands in General. No error, no warning, no log line.
sendMessage({ chat_id: -1001234567890, text: "Looking into it" })

// RIGHT: echo the thread back
sendMessage({
  chat_id: -1001234567890,
  message_thread_id: 91388,
  text: "Looking into it"
})

// Creating a topic. icon_color is NOT free-form: six values, decimal.
createForumTopic({
  chat_id: -1001234567890,
  name: "Billing",                     // 1 to 128 characters
  icon_color: 7322096                  // 0x6FB9F0, one of the six allowed
})
// allowed: 7322096, 16766590, 13338331, 9367192, 16749490, 16478047

// The conversation key, before and after forums existed
key = chat_id                                   // breaks in a forum
key = (chat_id, message_thread_id ?? 1)         // 1 is General

Thread 1 is General

Created with the forum, never deletable, and the default destination for any send without a thread.

Topic ID is a message ID

The creation service message supplies it, which is why the numbers are sparse.

Check is_topic_message

Channel comment threads carry a thread ID too, and are not topics.

Reference · the topic API

Six things worth knowing before you build on topics.

createForumTopicMethod

Creates a topic. The name is 1 to 128 characters, and icon_color must be one of six fixed values Telegram publishes, not an arbitrary RGB.

editForumTopicMethod

Renames a topic or changes its custom emoji icon. Omitted fields keep their current value rather than being cleared.

closeForumTopic / reopenForumTopicMethod

Closing stops new messages without destroying anything. This is the right tool for a resolved support thread.

deleteForumTopicMethod

Removes the topic and every message in it. Irreversible, and not a substitute for closing.

editGeneralForumTopic / hideGeneralForumTopicMethod

General is a special case with its own methods. It can be renamed, closed and hidden, but never deleted.

forum_topic_created / _edited / _closed / _reopenedService message

Topic lifecycle arrives as service messages inside the group, not as a separate update type. Read them to keep your thread list in sync.

Forum readiness checklist

Six rules for supporting topics properly.

  • Key every conversation on (chat_id, message_thread_id), defaulting the thread to 1 for General.
  • Echo message_thread_id on every reply, including automated and AI-generated ones.
  • Use is_topic_message to tell a real topic apart from a channel comment thread.
  • Read topic service messages so renames, closes and reopens stay in sync.
  • Close resolved threads instead of deleting them. Deletion destroys the history.
  • Send only the six permitted icon colour values, and use a custom emoji for real branding.
Watch out for

Forum support is a schema change, not a feature flag.

Every integration written before topics existed keys its conversations on the chat alone, and that assumption is baked into the busiest table in the system plus everything joined to it: assignments, unread counters, automation triggers, analytics. Adding topic support later means changing that key and backfilling. It is much cheaper to store the thread from the first day, even for customers who have never turned forum mode on, because for them the value is simply General and nothing else changes.

Forum topics: FAQ

What changes the moment a Telegram group turns on threads.

It is the identifier of the thread a message belongs to, and it is not a separate counter. When a topic is created, Telegram posts a forum_topic_created service message into the group, and that service message ID becomes the topic ID forever. So a topic ID is a message ID, which is why topic IDs are sparse, unordered relative to creation time in busy groups, and unique only within their own chat.
Because it did not pass message_thread_id. In a forum group, a send with only chat_id goes to the General topic, not to the thread the incoming message came from. There is no error and no warning, so the symptom is answers to support questions appearing in a general channel while the customer waits in their own thread. Echo the message_thread_id from the incoming message on every reply.
Every forum has one, it is created automatically when forum mode is switched on, and it carries message_thread_id 1. It is where every message with no explicit thread ends up. It has its own set of Bot API methods, editGeneralForumTopic, closeGeneralForumTopic, hideGeneralForumTopic and their counterparts, and unlike an ordinary topic it cannot be deleted. Hiding it is the closest thing to removing it.
No, and this catches people out. In a discussion group linked to a channel, replies to a channel post also carry a message_thread_id representing that post's comment thread, even though the group is not a forum. The field that actually tells you which case you are in is is_topic_message on the message. Branch on that flag rather than on the presence of message_thread_id.
The chat has to be a supergroup, and Telegram gates the toggle behind a minimum member count, 100 at the time of writing, so a brand new group cannot enable it immediately. Managing topics afterwards is its own permission: administrators need the manage-topics right, and ordinary members can have it granted or restricted individually, which is how a community lets trusted members open threads without giving them full admin powers.
Topics, in almost every case. One forum group with a topic per customer, per project or per region keeps membership, permissions and history in one place, while giving each conversation its own thread that can be closed when it is resolved. Separate groups mean re-inviting people, duplicating admin setup, and fragmenting history across chats that your CRM then has to stitch back together.
Ready to ship

Every thread its own conversation. Every reply in the right place.

Pinlyx treats Telegram topics as first-class conversations, routes them to different pipelines, and never answers into the wrong thread.

Free forever plan · GDPR-ready · No credit card required

We value your privacy

We use cookies to improve our site, analyze traffic, and personalize ads. You can accept all, reject non-essential, or customize your choices. Read our Cookie Policy.