Telegramのスーパーグループ移行:Chat IDを安全に更新する
Telegramのグループがスーパーグループへ移行した場合、ボットの以後の送信には新しいチャット識別子を使います。Bot APIではサービスメッセージに migrate_to_chat_id または migrate_from_chat_id が含まれ、失敗したAPIリクエストの応答にも parameters.migrate_to_chat_id が返ることがあります。旧IDと新IDの対応を明示的に保存し、今後の送信先を更新してください。保存済みメッセージの元のチャットIDは維持します。
要点
- グループ移行は送信先の識別子の変更であり、webhookの配信障害とは別問題です。
- エラー文の文字列一致やIDの推測ではなく、構造化された移行フィールドを使います。
- 履歴は元のチャットに紐付け、送信直前に現在の宛先を解決します。
- UnifyPortの公開イベント仕様には、同等の移行対応情報は記載されていません。
migrate_to_chat_idとmigrate_from_chat_idの意味
Telegram公式Bot APIリファレンスは、Message の任意フィールドとして両方を定義し、ResponseParameters にも移行先のフィールドを定義しています。
| 根拠 | 旧チャット | 新チャット |
|---|---|---|
migrate_to_chat_id を含むメッセージ | そのメッセージの chat.id | message.migrate_to_chat_id |
migrate_from_chat_id を含むメッセージ | message.migrate_from_chat_id | そのメッセージの chat.id |
parameters.migrate_to_chat_id を含む失敗応答 | 元のリクエストで指定した数値のチャットID | parameters.migrate_to_chat_id |
エラー応答を使う場合は、元のリクエストも保存します。保存済みの数値IDではなくユーザー名を宛先にした場合、エラー応答だけから旧チャットの数値IDを作り出してはいけません。
Telegramによると、移行識別子は32有効ビットを超える可能性があり、最大52有効ビットです。保存には符号付き64ビット整数または倍精度浮動小数点数を使えます。経路のどこにも32ビット変換がないか確認してください。アプリケーション内部のキーを十進数文字列にする設計も可能ですが、符号と値を正確に保持する必要があります。
この記事は、更新がすでに受信側へ届いていることを前提とします。受信方式やアカウントの種類をまだ決めていない場合は、Telegram Bot API webhookと統一受信webhookの比較を先に確認してください。
履歴を書き換えず、宛先の別名として扱う
推奨するアプリケーション設計は、業務上の会話とプラットフォーム上の送信先を分離することです。テナントとボット連携の範囲で旧IDから新IDへの対応を保存し、その根拠も残します。これはローカルの保存設計であり、Telegram APIに追加されたフィールドではありません。
履歴レコードのチャットIDを一括置換しないでください。Telegramの message_id はそのチャット内で一意であり、全体で一意ではありません。旧メッセージを新チャットのメッセージとして付け替えると、誤った関連付けを起こす可能性があります。宛先の対応関係は、メッセージ識別子の変換を保証するものではありません。
処理順序は次のように設計します。
- 受信元を検証し、更新を永続保存します。APIエラーの場合は実際の応答と元のリクエストを残します。
- 上の表に従って旧チャットIDと新チャットIDを抽出します。
- ストレージが対応する場合、対応関係の保存と現在の送信先の更新を同一トランザクションで行います。
- 同じ対応の再通知では追加処理をしません。矛盾する対応や循環は自動上書きせず、確認対象にします。
- 履歴を維持し、キューの送信タスクは実行直前に現在の宛先を解決します。
対応関係の更新と宛先解決には、アプリケーションのロックなどの並行制御を使います。そうしないと、あるワーカーが旧IDを読んだ直後に別のワーカーが移行を確定する競合が起こります。ローカルで調整しても、この競合に対する送信エラー処理は必要です。
キューの送信を無条件に再実行しない
失敗応答の parameters.migrate_to_chat_id は新しい送信先を示します。まず保存し、タスクが今も適切か確認してから再試行を判断します。一方、ネットワークのタイムアウトは、移行の証拠にも送信失敗の証明にもなりません。
以前のメッセージを参照するタスクでは、旧 message_id をそのまま新チャットIDと組み合わせないでください。参照の有効性を確認するか、人による確認に回します。文脈に依存する操作を、黙って別の通常メッセージへ変更してはいけません。
送信結果を観測する設計は、webhook応答内の返信と独立したsendMessageリクエストで説明しています。受信確認の成功と送信タスクの完了は別です。
次は推奨する受け入れテストであり、実測結果ではありません。
- 同じ移行情報を繰り返しても対応は一つで、送信タスクが増えない。
- 遅れて届いた旧チャットの更新が、現在の送信先を旧IDへ戻さない。
- 矛盾する対応がある場合は関連タスクが停止する。
- 名前が同じだけの無関係なグループを統合しない。
- シリアライズとデータベースの読み書きで識別子が欠落しない。
UnifyPortとの境界
UnifyPortの非公式インターフェースは、message.received に provider、account_id、data.conversation.id を含めます。これらは別の名前空間で保持し、Bot APIのチャットIDを直接代入できると考えないでください。LINEなどと共通の受信処理を設計する場合も、識別子の名前空間は分離します。
公開イベント仕様には migrate_to_chat_id、migrate_from_chat_id や、旧IDと新IDの対応を必ず提供するという記載はありません。group.updated や conversation.updated にも、その保証を読み込まないでください。接続済みTelegramメッセージングアカウントの確認には、会話一覧APIの conversation_id を使います。同じタイトルだけでは継続関係を確認できないため、不明な対応はレビューが必要です。
イベント受信には signing_secret を設定し、webhook配信検証仕様に従います。UnifyPortにはRESTのメッセージ履歴読み取りAPIや、欠落したイベントの再配信保証はありません。現在の会話一覧から、失われたメッセージや未定義の移行関係を復元することはできません。
FAQ
スーパーグループになったらwebhook URLも変える必要がありますか?
新しいチャットIDはルーティングの問題です。それだけでURL変更が必要とは判断できません。まず受信更新と保存済み宛先を確認します。
旧IDから新IDを計算できますか?
Telegramが提供する移行フィールドを使ってください。接頭辞の追加や数字の変更で宛先を作らないでください。
履歴をすべて新チャットIDへ移すべきですか?
いいえ。元のチャットとメッセージの組を保持し、業務上の会話を関連付けます。メッセージ識別子が変換されたとは扱いません。
UnifyPortでもBot APIの移行フィールドを受け取れますか?
公開契約には記載されていません。UnifyPort自身のAPIで接続済みアカウントの識別子を照合し、不確かな対応を確認してください。
次の作業と出典
キュー内のタスクを含め、送信先をいつ解決しているか点検してください。接続済みアカウントの照合は会話一覧の仕様から始められます。
- Telegram Bot API:Message、ResponseParameters、確認日:2026-09-21。
- UnifyPort標準イベント仕様。
メッセージ連携を安定したプロダクトパイプラインへ。
まずは 1 つの API で送信を始め、標準イベントですべての inbound メッセージを業務システムへ戻しましょう。