LINE Messaging APIで既読をつける[TypeScript]

に公開

概要

この記事では2025/11/5に公開されたLINE Messaging APIの既読をつける機能をTypeScript(JavaScript)で使用する方法を解説します。

ニュース

2025/11/5 LINE Messaging APIで既読をつけることができるようになりました。
https://developers.line.biz/ja/news/2025/11/05/mark-as-read/

これまでも所定の申請を行った法人ユーザーは既読API(旧)を使うことができたのですが、今回の変更により誰でもAPIで既読をつけることができるようになりました。

既読API(新)のリファレンスは以下です。
https://developers.line.biz/ja/docs/messaging-api/mark-as-read/

これまで既読の挙動

まず、既読機能の前提となる設定について確認しておきましょう。

LINE Botを機能させるには、LINE Official Account Managerの応答設定で「Webhook」をオンにしておく必要があります。

Webhookオンリー

チャットを利用する場合は応答設定で「チャット」をオンにしておく必要があります。

Webhook・チャット併用

2022年12月1日からは「Webhook」と「チャット」を併用することができるようになりました。

参考: 2022/12/1「Webhook」と「チャット」の機能が併用可能になりました | LINE Official Account Manager

この設定の違いにより、既読の挙動が異なります。

Webhookのみオンの場合

ユーザーがメッセージを送信すると、すぐに既読がつきます。

Webhookとチャットを併用している場合

チャットでメッセージを確認するまで、既読はつきません。
Botがリプライメッセージを送信しても、ユーザーが送ったメッセージに既読はつきません。

既読APIを活用する条件

Webhookのみオンの場合は即座に既読がついてしまうため、既読APIを活用する場合はWebhookとチャットを併用するパターンのときに使うことになります。

そのため、既読APIを使いたい場合は、チャットを利用しない場合でもチャットをオンにする必要があります。

既読トークンの取得

既読APIを使うには既読トークンを取得する必要があります。
下記のようにWebhookのメッセージイベントオブジェクトのmarkAsReadTokenというプロパティが追加されています。これが既読トークンです。

{
  "destination": "xxxxxxxxxx",
  "events": [
    {
      "type": "message",
      "webhookEventId": "01FZ74A0TDDPYRVKNK77XKC3ZR",
      "message": {
        "id": "444573844083572737",
        "type": "text",
        "quoteToken": "q3Plxr4AgKd...",
        "markAsReadToken": "30yhdy232...", // 既読トークン
        "text": "Hello, world!"
      },
      // 省略
    }
  ]
}

line-bot-sdk-nodejsを利用している場合、2025/11/6現在、まだ既読トークンの型定義が反映されていないので、下記のように既存の型を拡張してあげる必要があります。

import { messagingApi } from '@line/bot-sdk';
import type { webhook } from '@line/bot-sdk';

// 中略
const parsedBody = JSON.parse(body) as webhook.CallbackRequest;
const events = parsedBody.events;
for (const event of parsedBody.events) {
  if (event.type === 'message' && event.message.type === 'text') {
    const message = event.message as MarkAsReadableTextEventMessage;
       // as stringをつけないと`undefined` 許容になってしまう。
       const markAsReadToken = event.message.markAsReadToken as string;
       // 既読トークンの保存や使用

既読をつける

既読をつけるのは簡単で下記のコードで実行可能です。

const client = new messagingApi.MessagingApiClient({
  // LINE_CHANNEL_ACCESS_TOKENは実際の値に書き換えてください。
  channelAccessToken: LINE_CHANNEL_ACCESS_TOKEN
});
const markAsReadToken = event.message.markAsReadToken as string;
await client.markMessagesAsReadByToken({ markAsReadToken });

全体のコード

全体のコードは下記になります。
メッセージ受信から10秒後に既読、さらに10秒後にオウム返しで返信するCloudflare Workersのコード例になります。

import { messagingApi } from '@line/bot-sdk';
import type { webhook } from '@line/bot-sdk';

export default {
  async fetch(request, env, ctx): Promise<Response> {
    // 環境変数の取得
    const LINE_CHANNEL_ACCESS_TOKEN = env.LINE_CHANNEL_ACCESS_TOKEN;

    // LINE Messaging APIクライアントの生成
    const client = new messagingApi.MessagingApiClient({
      channelAccessToken: LINE_CHANNEL_ACCESS_TOKEN
    });

    // Webhookイベントの解析
    const body = await request.text();
    const parsedBody = JSON.parse(body) as webhook.CallbackRequest;
    const events = parsedBody.events;

    // 非同期処理を開始(レスポンスは待たない)
    ctx.waitUntil(
      (async () => {
        for (const event of events) {
          // テキストメッセージのみ対応
          if (event.type === 'message' && event.message.type === 'text') {
            const markAsReadToken = event.message.markAsReadToken as string;
            // 10秒経ってから既読を付ける
            await new Promise((resolve) => setTimeout(resolve, 10000));
            await client.markMessagesAsReadByToken({ markAsReadToken });
            // 10秒経ってからオウム返し
            await new Promise((resolve) => setTimeout(resolve, 10000));
            await client.replyMessage({
              replyToken: event.replyToken as string,
              messages: [
                {
                  type: 'text',
                  text: event.message.text,
                },
              ],
            });
          }
        }
      })()
    );

    // すぐに200 OKを返す
    return new Response('OK');
  },
} satisfies ExportedHandler<Env>;

既読APIの使い所

この既読APIが特に有効なのは、公式のチャット画面ではなく、Messaging APIを利用したサードパーティー製のチャット管理ツールや自社開発のチャット管理画面を使用している場合かと思います。

これまでは、ユーザーがメッセージを送信すると無条件に既読がついていました。そのため、「既読になったのになかなか返信が来ない」という状況が発生し、ユーザーの不満につながることがありました。
既読APIを使えば、オペレーターが実際にメッセージを確認したタイミングで既読をつけることができるため、こうした問題の解消が期待できますね!

最後に

line-bot-sdk-nodejsがまだ既読APIに対応していなかったので、プルリク送ってみようと思います👍

(最近はアップデート早めなので間に合わないかもしれませんが...)

API公開の翌々日の2025/11/7にline-bot-sdk-nodejsも対応していました!
記事の内容もSDKを使ったものに書き換えています。

最近はSDKの対応が早くて好印象ですね。

ボイスアップラボ

Discussion