> ## Documentation Index
> Fetch the complete documentation index at: https://cogno.studio/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# WhatsApp接続APIを使う

> 認証付きリクエストでワークスペースのWhatsApp接続を設定し、検証済みのメッセージWebhookを受信します。

認証付きAPIでワークスペースに一つのWhatsApp接続を設定し、検証付きWebhookでメッセージを受信します。受信したメッセージと通知は、接続先のワークスペースに保存します。テキストの会話は既存のAttention処理に入り、必要に応じてCognoがTaskを作成・更新します。ブラウザでの接続手順は[WhatsAppをCognoに接続する](https://cogno.studio/docs/ja/whatsapp-integration.md)をご覧ください。

## アクセス要件

`Authorization`にCognoのBearerトークンを送信します。すべての操作に、有効なワークスペースメンバーであることと`integrations.manage`権限が必要です。member・admin・ownerの各ロールがこの権限を持ちます。ワークスペースのMFAポリシーも適用します。ワークスペースはURLから決まり、接続手続きは開始したユーザーに紐づきます。

デプロイ環境にWhatsAppの認証情報、別々のstate用・トークン用暗号化キー、固定の登録PIN用キー、明示したGraph APIバージョン、公開HTTPSのWebhookコールバックURLを設定してください。APIと連携workerには同じ設定が必要です。`DATABASE_LISTENER_URL`は、直接接続またはセッションを維持するPostgreSQL接続先を使います。設定が不足すると、`setup_not_configured`コードで`503`を返します。

ブラウザの接続画面には、フロントエンドのビルド時に`NEXT_PUBLIC_WHATSAPP_META_APP_ID`、`NEXT_PUBLIC_WHATSAPP_CONFIGURATION_ID`、`NEXT_PUBLIC_WHATSAPP_GRAPH_API_VERSION`も必要です。App IDとGraphバージョンはCoreの設定に合わせ、MetaアプリのFacebook Login設定でフロントエンドのHTTPSドメインを許可してください。これらは公開値です。App Secretやアクセストークンはフロントエンドに設定しないでください。

## stgのテスト設定

`ENVIRONMENT=stg`のサーバー側でのみ、次の4つの環境変数を設定します。

* `WHATSAPP_TEST_WORKSPACE_ID`：テストに使うCognoのワークスペース。
* `WHATSAPP_TEST_MESSAGING_ACCOUNT_ID`：Metaのテスト用WhatsApp BusinessアカウントID。
* `WHATSAPP_TEST_PHONE_NUMBER_ID`：テスト電話番号のID。電話番号そのものではありません。
* `WHATSAPP_TEST_ACCESS_TOKEN`：Metaの一時アクセストークン。秘密情報として扱い、`NEXT_PUBLIC_`変数には設定しないでください。

このリポジトリで管理する環境では、stgのTerraform入力で`whatsapp.test_connection`を設定します。トークンをSecret Managerに保存し、`access_token_secret_name`にシークレットIDを指定してください。`access_token_secret_version`には有効な数値バージョンまたは`latest`を指定でき、stgでは`latest`を使います。Core APIと連携workerに同じWorkspace・MetaアセットIDと、同じシークレット参照を渡します。Terraformはトークン値を保存しません。一時トークンが失効したら、新しい有効なシークレットバージョンを保存し、通常のリリース手順で両方を再デプロイしてください。各インスタンスは起動時に`latest`を読み取り、稼働中のインスタンスは現在のトークンを使い続けます。既存接続へ新しいトークンを保存するには接続開始の再実行も必要です。シークレットの更新だけでは既存接続は更新されません。

既存の接続開始リクエストが、設定したワークスペースに限ってこのトークンを使い、Embedded Signupを省略して接続の進捗を返します。他のワークスペースでは通常のMetaサインインを使います。追加エンドポイントやブラウザのトークン入力欄はありません。アプリ・権限・有効期限・電話番号の確認、認証情報の暗号化保存、接続設定ワーカーは通常どおり適用します。一時トークンの期限が切れたら、再接続する前にサーバー側の設定を更新してください。

通常のサインアップを使う場合は4つとも未設定にします。一部だけの設定、またはstg以外でのテスト認証情報の設定は`503 setup_not_configured`になります。既存のバックエンドとフロントエンドのサインアップ設定も引き続き必要です。

## エンドポイント

ベースパスは`/api/v1/whatsapp/workspaces/{workspace_id}/connection-flows`です。

| メソッド | ベースパス以降 | 結果 |
| - | - | - |
| `POST` | ベースパス | `201`：接続手続きを作成し、`progress`と`state`を返します。 |
| `POST` | `/authorization` | `200`：Metaの認可コードを交換し、認可を保存して設定をキューに登録します。 |
| `GET` | `/{flow_id}` | `200`：開始したユーザーの現在の進捗を返します。 |
| `POST` | `/{flow_id}/resume` | `200`：有効な保存済み認可を使い、設定を再びキューに登録します。 |
| `POST` | `/{flow_id}/cancel` | `200`：未完了の設定をキャンセルします。既存の有効な接続は維持します。 |

認可リクエストは次のフィールドだけを受け付けます。

| フィールド | 意味 |
| - | - |
| `state` | 接続手続きの開始時に返された不透明な値。 |
| `code` | Metaから返された認可コード。 |
| `messaging_account_id` | 選択したWhatsApp Business AccountのID。正の整数を表す文字列。 |
| `phone_number_id` | 選択した電話番号のID。正の整数を表す文字列。 |

APIはトークンと、選択した番号がそのアカウントに所属することを確認してから認可を保存します。コードは認可リクエストの処理中に交換します。トークンは暗号化して保存し、進捗応答やジョブ引数には含めません。

## リクエストの順序

**1. 接続手続きを開始する**

ベースパスに`POST`します。返された`state`と`progress.flow_id`を保持してください。認可用stateは開始から10分、接続手続きは開始から1日で期限切れになります。

**2. Metaの認可結果を送信する**

Metaの認可を完了し、返されたコードと選択したアカウント・電話番号のIDを、保持した`state`と一緒に`/authorization`へ送信します。受付が成功すると`configuring`を返し、バックグラウンドで設定を続けます。

**3. 進捗を確認する**

設定が完了するか操作が必要になるまで、`GET /{flow_id}`で確認します。同じ受付済みの認可を再送すると、コードを再交換せずに保存済みの進捗を返します。

## 進捗と復旧

進捗には`flow_id`・`status`・`expires_at`・`connection_id`・`phone_number_id`・`last_error_code`を含みます。すべての接続設定の応答に`Cache-Control: no-store`を付けます。

| 状態 | 意味 | 次の操作 |
| - | - | - |
| `awaiting_authorization` | Metaの認可を待っています。 | stateの期限内に認可結果を送信します。 |
| `configuring` | バックグラウンドの設定が待機中または実行中です。 | 進捗を再確認します。 |
| `completed` | 認可と接続が有効です。 | 接続設定は完了しています。 |
| `action_required` | 表示された理由を人が解消する必要があります。 | 解消して再開するか、再認可が必要なら新しい手続きを開始します。 |
| `cancelled` | 開始したユーザーが設定をキャンセルしました。 | 再試行するには新しい手続きを開始します。 |
| `expired` | 接続設定の期限を過ぎました。 | 新しい手続きを開始します。 |
| `failed` | 理由を記録して手続きが失敗終了しました。 | 理由を確認し、新しい手続きを開始します。 |

workerは、明示的に一時的と判定した設定失敗を最大6回まで試行します。試行回数を使い切ると、接続手続きは`action_required`になります。保存済みの認可が有効なら、問題を解消してから再開できます。コード交換の中断、無効な認可、権限不足、アカウント不一致では、新しい認可が必要です。

## エラー

想定される失敗は`application/problem+json`で返し、`type`・`title`・`status`・固定の`code`を含みます。不正なリクエストには、送信されたコードやstateを含まない汎用エラーを返します。

| HTTPステータス | 主なコード | 意味 |
| - | - | - |
| `400` | `invalid_state`、`authorization_required` | stateを使えないか、新しい認可が必要です。 |
| `401` | `authentication_required` | Cognoの認証情報が必要です。 |
| `402` | `integration_limit_reached` | ワークスペースの連携数の上限に達しています。 |
| `403` | `workspace_access_denied`、`mfa_required` | ワークスペースへのアクセス、権限、またはMFAが必要です。 |
| `404` | `flow_not_found` | このワークスペースと操作ユーザーでは、その手続きを参照できません。 |
| `409` | `authorization_conflict`、`connection_transition_conflict` | 保存済みの状態とリクエストが矛盾しています。 |
| `422` | `invalid_request` | リクエストが受け付ける形式と一致しません。 |
| `503` | `setup_not_configured` | デプロイ設定が不足しているか不正です。 |

## Webhookを受信する

MetaアプリのコールバックURLと`WHATSAPP_WEBHOOK_CALLBACK_URL`を`https://[your-api-host]/api/v1/whatsapp/webhook`に設定します。`WHATSAPP_WEBHOOK_VERIFY_TOKEN`に専用の検証文字列を設定し、MetaのWebhook設定にも同じ文字列を入力します。POSTの検証には、デプロイ設定の`WHATSAPP_META_APP_SECRET`と`WHATSAPP_META_APP_ID`を使います。WebhookリクエストにはCognoのBearerトークンを使いません。

メッセージと配信・既読状態を受け取るには`messages`を購読します。グループ情報の通知も受け取る場合は、`group_lifecycle_update`・`group_participants_update`・`group_settings_update`・`group_status_update`も購読してください。[MetaのWebhook設定手順](https://developers.facebook.com/documentation/business-messaging/whatsapp/webhooks/create-webhook-endpoint/)と[グループWebhookリファレンス](https://developers.facebook.com/documentation/business-messaging/whatsapp/groups/webhooks/)も参照できます。

| メソッド | パス | 動作 |
| - | - | - |
| `GET` | `/api/v1/whatsapp/webhook` | `hub.mode=subscribe`と`hub.verify_token`を検証し、`hub.challenge`をプレーンテキストで返します。 |
| `POST` | `/api/v1/whatsapp/webhook` | 元の本文に対する`X-Hub-Signature-256`とバッチ全体を検証し、受け付けたレコードをコミットしてから`200`を返します。 |

受信できる本文は1リクエストあたり最大3 MiBです。アプリ・WhatsApp Business Account・現在の主電話番号を、ワークスペースの有効かつ期限内の認可と照合します。未知または切断済みの接続先と、対象外の購読フィールドは、保存せずに受付済みとして応答します。接続設定中の場合は、設定完了後にMetaが再送できるよう`503`を返します。

受け付けたレコードはまとめてコミットし、同じ通知の再送は重複保存しません。本文・送信者・返信参照・取得済みのメディア情報を保存します。添付ファイルのダウンロードは行いません。配信状態とグループ変更は、会話メッセージではなく通知として保存します。これらはワークスペースの知識として扱い、外部インデックスには送信しません。

送信者の識別には、Metaのビジネス単位のユーザーIDであるBSUIDを使います。1対1の会話には相手のBSUID、グループの会話には`group_id`を使うため、参加者が違っても同じグループの会話として保存します。連絡先の名前は`contacts[].user_id`で照合します。送信者の電話番号（`from`と`wa_id`）は任意の付加情報で、識別には使いません。受信側のビジネス電話番号を示す`metadata.phone_number_id`は、接続を特定するため引き続き必須です。ID変更のシステムメッセージで`from_user_id`がない場合は、`system.user_id`のBSUIDを使います。変更前のIDはメッセージの詳細に保持しますが、会話履歴の統合は行いません。[MetaのBSUIDリファレンス](https://developers.facebook.com/documentation/business-messaging/whatsapp/business-scoped-user-ids/)も参照できます。

メッセージのバックグラウンド処理は、既定で有効です（`WHATSAPP_SEMANTIC_REDUCTION_ENABLED=true`）。保存後の処理を予約せずにメッセージを保持する場合は、APIでこの設定を`false`にします。新しく受け付けた通常メッセージと処理ジョブをまとめてコミットします。workerはMetaやLLMを呼び出さず、保存済みメッセージを構造化した会話イベントと読みやすい表現に変換します。同じメッセージを再処理しても、イベントは重複しません。共通のSemantic Event変換ジョブは、初回の失敗後に最大5回まで再試行します。配信・既読状態、グループ通知、システムメッセージでは、この処理を予約しません。Metaから再送された場合も含め、保存済みメッセージの自動再処理は行いません。

本文のあるイベントは既存のAttentionの判断処理に入り、今対応するか、後で対応するか、見送るかと、関係する有効なProjectを判断します。WhatsAppはワークスペースの接続済みアカウントを使い、Projectごとのソースフィルターはありません。会話の識別には接続と受信側のビジネス電話番号も含むため、別接続で同じBSUIDやグループIDが現れても混ざりません。判断処理と、その後の実行は、引用先が保存されていればそのメッセージも含め、件数を制限した会話履歴を読み取れます。外部の送信者名だけでワークスペースのメンバーを特定することはありません。この処理から作成するTaskには、参照元の種類`whatsapp_thread`と元イベントのIDを保持します。Taskの実行には既存のEnvironmentとエージェントの設定を使い、受信したメッセージすべてが新しいTaskになるわけではありません。

| HTTPステータス | 意味 |
| - | - |
| `200` | 保存済み、重複受信、または意図的に対象外とした通知です。 |
| `400` | challenge・JSON・対応するイベントの形式が不正です。 |
| `403` | 検証トークンまたは署名が不正です。 |
| `413` | 本文が3 MiBを超えています。 |
| `503` | Webhook設定不足、接続設定中、またはワークスペースのイベント受信上限に達しています。原因を解消してから再送します。 |
| `500` | 保存に失敗し、バッチをロールバックしました。Metaが再送できます。 |

## 関連ドキュメント

* [連携](https://cogno.studio/docs/ja/integrations.md)
* [料金](https://cogno.studio/docs/ja/billing.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.