← 全記事
チュートリアル

WhatsAppの過去メッセージをオンデマンドで読み込む方法

UnifyPortでWhatsAppの過去メッセージを読み込むには、まず conversation.history を購読し、保存済みメッセージを before アンカーとして履歴をリクエストします。HTTPレスポンスにメッセージ本文は含まれません。202 と status: accepted は受付を示すだけで、取得可能な履歴は非同期で届きます。実装すべきなのはベストエフォートの**「以前のメッセージを読み込む」**機能であり、完全なアーカイブの出力や、履歴の終端を自動判定するページングではありません。

要点

  • 対象は provider=whatsapp の個別チャットです。グループ、チャンネル、whatsapp-protocol は対象外です。
  • リクエスト前に購読と永続保存を準備します。
  • 実際のネイティブなコンテンツメッセージのID、送信時刻、方向でアンカーを進めます。
  • バッチは重複、遅延、複数回到着、未到着のいずれもあり得ます。無応答は完了ではありません。
  • 履歴はタイムラインの補完に使い、新着メッセージ用の自動返信を起動しないようにします。

受付レスポンスと履歴データを分ける

履歴リクエストのリファレンス は POST /v1/accounts/{account_id}/conversations/history/request を定義しています。これは非同期配信を要求する操作であり、保存済みメッセージを直接返すREST読み取りAPIではありません。

観測したもの確認できること確認できないこと
HTTP 202、data.status: acceptedリクエストが受け付けられたメッセージの到着や処理完了
HTTP request_idHTTPリクエストの調査用識別子タスクIDやコールバックの相関キー
data.history.source: on_demand を持つ conversation.historyオンデマンド履歴バッチの到着唯一の結果、または最後の結果であること
空または短いバッチそのバッチの内容履歴の終端
HTTPタイムアウトクライアントが確定的な応答を得られなかったリクエストが作用しなかったこと

メッセージングアカウントのランタイム復旧ガイド は接続の復旧を扱います。履歴の補完とは別の作業です。再接続も履歴リクエストも、停止中に失われたすべてのメッセージを復元する保証にはなりません。

ボタンより先に受信側を準備する

受信トレイに必要な既存イベントを残したまま、エンドポイントの購読に conversation.history を追加します。リアルタイムの受信には引き続き message.received を使います。既存エンドポイントの変更では webhook設定リファレンス を参照し、誤って signing_secret を空にしないでください。

配信仕様 に従い、X-Device-Timestamp、ピリオド、リクエストの生の本文を連結した値に対するHMAC-SHA256で X-Device-Signature を検証します。タイムスタンプの鮮度も確認し、検証済み配信を永続化してから2xxを返します。

履歴には専用の重複処理が必要です。WhatsApp HistorySyncでは別のチャンクでトップレベルのイベントIDが再利用される場合があります。見覚えのあるイベントIDというだけでバッチ全体を破棄してはいけません。ワークスペース内でprovider、account_id、data.conversation.id、各 data.messages[].id を組み合わせ、メッセージ単位で統合します。

履歴はリアルタイム自動返信の対象から外します。古い質問が今日届いたことは、顧客が今日もう一度質問した証拠ではありません。

有効なbeforeアンカーを作る

同じメッセージングアカウント、同じ個別チャットで観測したメッセージを選択します。必要な値は message_id、sent_at、direction です。チャット名、受信時刻、電話番号から推測してはいけません。

次は文書化された形式に沿ったリクエスト本文の例です。サンプルの識別子は保存済みの実際の値に置き換えます。

{
  "conversation_id": "100000000000002@lid",
  "before": {
    "message_id": "MSG_HISTORY_ANCHOR_001",
    "sent_at": "2026-09-28T03:00:00Z",
    "direction": "inbound"
  },
  "limit": 50
}

バックエンドで保持する X-Api-Key を使って、上記POST操作を呼び出します。account_id は空白やスラッシュを含まない、空でない単一のパスセグメントである必要があります。エンコードされたスラッシュも使えません。会話IDをアカウント用のパスセグメントに入れないでください。

続けて取得する際は、受信済みの中で最も古く、アンカー項目がそろったネイティブなコンテンツメッセージを選びます。type: call の合成レコードは除外します。次のJavaScriptは、選択・検証済みのメッセージからアンカーを作るだけです。受信サーバーや自動ページング処理ではありません。

function beforeFromMessage(message) {
  if (!message || message.type === 'call' ||
      typeof message.id !== 'string' || !message.id ||
      typeof message.sent_at !== 'string' ||
      !Number.isFinite(Date.parse(message.sent_at)) ||
      !['inbound', 'outbound'].includes(message.direction)) {
    throw new Error('Select a native content message with complete anchor fields');
  }
  return {
    message_id: message.id,
    sent_at: message.sent_at,
    direction: message.direction
  };
}

type は before にコピーしません。有効なアンカーがなければ操作を無効にし、理由を示します。合成通話レコードや作り出した過去の時刻で代用しないでください。

不確実性を受信トレイに表示する

以下はアプリケーション側の推奨動作であり、新しいAPIステータスではありません。

  1. **送信前:**アカウント、会話、アンカー、ローカルの要求時刻を記録します。同一会話の操作員リクエストは直列化し、重複する作業を減らします。
  2. 受付後:「受付済み。取得可能な履歴を待っています」と表示します。リアルタイムメッセージは独立して受信し続けます。
  3. **バッチ到着ごと:**子メッセージを冪等に統合します。ライブで受けた編集や削除の抑止情報を維持し、古い履歴で新しい状態を上書きしないようにします。
  4. **古い内容を受信した後:**最も古い適格なアンカーで、明示的な次のリクエストを許可します。より古い適格なアンカーがなければ「以前のアンカーは未受信」と表示し、「全履歴を読み込みました」とは表示しません。
  5. **タイムアウトやコールバック未着:**不確定な状態を保持し、遅れて届くバッチを受け付けます。同じリクエストを自動再送しません。

次ページのカーソルや完了ステータスは文書化されていません。account.history.synced はHistorySyncのバッチまたはチャンクの集計であり、オンデマンド要求の完了やアーカイブの完全性を証明しません。独自にタスク完了イベントと解釈しないでください。

履歴の引用関係と送信機能も分けます。履歴メッセージには reply_token がありません。引用返信ガイド では、親メッセージIDで代用できない理由を説明しています。取得できない添付ファイルも、ダウンロード済みとせず利用不可と表示します。

エラーと受け入れテスト

400 には invalid_request、合成通話アンカーなどに対する provider_invalid_request、unsupported_conversation_type があります。他のproviderには 501 unsupported_by_provider が返ります。再試行ループではなく、対象範囲や入力を修正してください。HTTP request_id は調査用に保存しますが、コールバック相関には使いません。

本番前に、重複バッチ、同じイベントIDを持つ異なるチャンク、HTTPタイムアウト後のコールバック、履歴とライブ受信の交錯、方向が欠けたアンカーをテストしてください。これらは推奨テストであり、実施済みの結果ではありません。

UnifyPortは非公式インターフェースを提供します。この機能は会話の背景をベストエフォートで補うものであり、完全なバックアップ、保証された再配信、任意のアカウントへのアクセスではありません。自社で許可されたメッセージ保存と保持管理を続ける必要があります。

よくある質問

202は過去メッセージの取得成功を意味しますか?

いいえ。リクエストの受付を意味します。取得可能なメッセージは非同期の履歴イベントで届きます。

短いバッチが来るまでリクエストを続けてもよいですか?

短いバッチを終了条件にしないでください。件数だけでは完全性を判断できず、自動リクエストが遅延結果と重なる可能性もあります。

WhatsAppグループやLINE、Zaloでも使えますか?

この操作は provider=whatsapp の個別チャット向けです。LINEと同じ受信トレイで扱っていても、統一webhook形式から履歴要求の対応範囲を推測してはいけません。

次のステップと出典

ボタンを有効にする前に、会話履歴リクエストのリファレンス に沿って受信と不確定状態の管理を実装してください。

公式資料の確認日:2026-09-30。

UnifyPort API

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

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