← 全記事
チュートリアル

LINEの編集済みメッセージをmessage.updated Webhookで処理する方法

LINEは2026年8月12日、Messaging APIに編集イベントを追加しました。LINE公式アカウントを含む対象のグループトークで、ユーザーが送信済みテキストを編集すると、LINEはmessageEdited Webhookイベントを送信できます。共有受信箱では新しいメッセージを追加するのではなく、元のメッセージを更新します。UnifyPortでは、対応する標準イベントはmessage.updatedで、元のdata.message.idをキーにします。

要点

  • LINEネイティブのイベント名はmessageEdited、UnifyPortの標準名はmessage.updatedです。
  • メッセージアカウント、会話、data.message.idの組み合わせで元メッセージを特定します。
  • 編集は状態変更であり、新規受信メッセージとして再カウントしません。
  • JSONを解析する前に、HMAC-SHA256署名を検証します。
  • LINEの編集イベントを受信できることと、UnifyPortからLINEメッセージを編集できることは別の機能です。

LINEのグループトークで変わったこと

LINEのMessaging API公式ニュースには、2026年8月12日の更新として、LINE公式アカウントを含むグループトークでユーザーがメッセージを編集できるようになり、WebhookイベントオブジェクトにmessageEditedが追加されたことが記載されています。現在のMessaging APIリファレンスにも、WebhookイベントオブジェクトとしてEdit eventが掲載されています。

日本のサポート運用ではLINEが主要窓口になることも多いため、この変更は共有受信箱、CRMの履歴、検索インデックス、AIに渡す会話コンテキストに影響します。顧客が注文番号や住所を修正したのに旧テキストを使い続けると、後続処理は古い情報を参照します。一方、編集後のテキストを新規メッセージとして追加すると、件数が二重になり、LINE上の会話とも一致しません。

正しいモデルは、1つのプロバイダーメッセージに対する状態更新です。

LINE messageEditedとUnifyPort message.updatedの対応

LINE公式のペイロードはLINE固有の構造です。UnifyPortは更新を共通エンベロープへ正規化し、他の対応プロバイダーの編集と同じハンドラーで扱えるようにします。

{
  "id": "evt_7f42c18a9d",
  "type": "message.updated",
  "provider": "line",
  "account_id": "acc_8c21d0",
  "occurred_at": "2026-08-22T09:15:30Z",
  "data": {
    "conversation": {
      "id": "c8f2a4d91e",
      "type": "group",
      "title": "注文サポート"
    },
    "sender": {
      "id": "u71b9d420f",
      "type": "user",
      "name": "Jordan Lee"
    },
    "message": {
      "id": "551842037194",
      "text": "訂正:注文番号はA1234です。",
      "direction": "inbound",
      "sent_at": "2026-08-22T09:12:04Z"
    },
    "event": {
      "kind": "message_updated"
    }
  }
}

2つのIDを混同しないことが重要です。

  • トップレベルのidはWebhookイベントを識別し、再配信の重複排除に使います。
  • data.message.idは、内容が変更された元メッセージを識別します。

現在のプロバイダー別対応状況は、Webhook標準イベントの差異で確認できます。LINEのmessage.updated対応が掲載されていますが、実際のフィールドは上流アカウントやデプロイ状況によって異なる場合があります。

重複を作らず編集を反映する

プロバイダーのメッセージIDがグローバルに一意だと仮定せず、次の複合キーを使います。

(account_id, conversation_id, provider_message_id)

編集を冪等な状態遷移として処理します。

  1. 生のリクエストボディに対する署名を検証する。
  2. WebhookイベントIDで再配信を重複排除する。
  3. account_iddata.conversation.iddata.message.idで保存済み行を検索する。
  4. 現在の本文をdata.message.textで更新する。
  5. occurred_atを編集の観測時刻として保存する。
  6. 初回受信時刻は残し、監査が必要なら内部リビジョン履歴を別に保持する。
  7. 永続化が成功してから2xxを返す。

以下は最小構成のExpressハンドラーです。データベース処理を抽象化し、実際のイベントフィールドを明確にしています。

import crypto from 'crypto';
import express from 'express';

const app = express();
const secret = process.env.WEBHOOK_SIGNING_SECRET;

app.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
  const timestamp = req.get('X-Device-Timestamp') || '';
  const signature = req.get('X-Device-Signature') || '';
  const expected = crypto.createHmac('sha256', secret)
    .update(timestamp + '.')
    .update(req.body)
    .digest('hex');

  const valid = signature.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
  if (!valid) return res.sendStatus(401);

  const event = JSON.parse(req.body.toString('utf8'));
  if (await db.hasWebhookEvent(event.id)) return res.sendStatus(200);

  if (event.type === 'message.updated') {
    await db.applyMessageEdit({
      accountId: event.account_id,
      conversationId: event.data.conversation.id,
      messageId: event.data.message.id,
      text: event.data.message.text,
      editedAt: event.occurred_at
    });
  }

  await db.rememberWebhookEvent(event.id);
  return res.sendStatus(200);
});

署名文字列、再試行条件、順序に関する注意点はWebhook配信と署名検証を参照してください。古いタイムスタンプの拒否や永続的な冪等性は、Webhook HMACのリプレイ対策チュートリアルで詳しく解説しています。

元メッセージがない、または順序が逆の場合

Webhookの配信順序は保証されません。編集イベントが元メッセージのコミットより先にワーカーへ届くことがあります。また、受信側の停止中に元メッセージだけを失う可能性もあります。この時点で通常のタイムライン項目を作成したり、受信件数を増やしたりしないでください。

代わりに、複合メッセージキーを使う短期保留テーブルへ更新を置きます。元のmessage.receivedが到着したら、表示前に保留中の本文を適用します。元メッセージが届かない場合は、完全なメッセージとして見せず、「元データがない編集観測」としてオペレーター確認に回します。

絵文字リアクションも同じ状態管理の考え方で処理できます。統一Webhookでメッセージリアクションを処理する方法では、イベントと、そのイベントが変更するメッセージ状態を分けて説明しています。

UnifyPortが適する場面と制限

LINEに加えてWhatsApp、Telegram、TikTok、Zalo、Xを扱う小規模チームが、署名付きの単一イベント契約を下流で使いたい場合、UnifyPortの非公式インターフェースによりプロバイダー別パーサーを減らせます。ハンドラーはmessage.updatedを基準に分岐できます。

LINE公式アカウントを中心に構築し、LINE固有機能や元のプロバイダーペイロードが必要なシステムには、公式Messaging APIが適しています。また、現在のアクション境界にも注意してください。UnifyPortは受信したLINEメッセージ更新を正規化できますが、POST /v1/messages/editによるLINE向け送信済みメッセージ編集には現在対応していません。編集の受信と編集の実行は別機能です。

よくある質問

LINEのmessageEditedとは何ですか?

対象となるメッセージ編集を通知するLINE Messaging APIの公式Webhookイベントです。LINEは2026年8月12日、LINE公式アカウントを含むグループトーク向けに追加を発表しました。

UnifyPortではどのイベントを購読しますか?

message.updatedを購読します。公開標準イベントをすべて受ける設計なら"*"も使えますが、本番の明示的なフィルターでは正確なイベント名を指定します。

編集済みLINEメッセージは受信箱に新規追加しますか?

追加しません。data.message.idで既存メッセージを特定し、現在の内容を更新します。監査上必要な場合だけ、変更履歴を別保存します。

UnifyPortからLINEメッセージを編集できますか?

現在はできません。現行のプロバイダーアクション表では、LINEの送信済みメッセージ編集は対応対象外です。本記事は編集イベントの受信と反映を扱います。

次のステップ

プロバイダー別Webhookイベント表を確認し、message.updatedを購読対象へ追加してください。本番の共有受信箱で有効にする前に、冪等更新と順序逆転のケースをテストします。

公式情報源

2026年8月22日に確認:

UnifyPort API

メッセージ連携を安定したプロダクトパイプラインへ。

まずは 1 つの API で送信を始め、標準イベントですべての inbound メッセージを業務システムへ戻しましょう。