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_id | HTTPリクエストの調査用識別子 | タスク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ステータスではありません。
- **送信前:**アカウント、会話、アンカー、ローカルの要求時刻を記録します。同一会話の操作員リクエストは直列化し、重複する作業を減らします。
- 受付後:「受付済み。取得可能な履歴を待っています」と表示します。リアルタイムメッセージは独立して受信し続けます。
- **バッチ到着ごと:**子メッセージを冪等に統合します。ライブで受けた編集や削除の抑止情報を維持し、古い履歴で新しい状態を上書きしないようにします。
- **古い内容を受信した後:**最も古い適格なアンカーで、明示的な次のリクエストを許可します。より古い適格なアンカーがなければ「以前のアンカーは未受信」と表示し、「全履歴を読み込みました」とは表示しません。
- **タイムアウトやコールバック未着:**不確定な状態を保持し、遅れて届くバッチを受け付けます。同じリクエストを自動再送しません。
次ページのカーソルや完了ステータスは文書化されていません。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。
メッセージ連携を安定したプロダクトパイプラインへ。
まずは 1 つの API で送信を始め、標準イベントですべての inbound メッセージを業務システムへ戻しましょう。