Skip to main content
API チャネルは、顧客との会話経路をすでに持っているチーム向けです。自社アプリ、自社で運用する Zalo OA、コンタクトセンター、CRM など。顧客のメッセージは Webhook でプラットフォームに転送し、Agent の回答はコールバックで自社の Webhook に返ります。
双方向で 1 つの秘密鍵と 1 つの署名方式を共有するので、署名の関数は一度書けば送信にも受信にも使えます。

連携方式を選ぶ

2 つは排他ではありません。1 つの Agent が、ウェブサイトのウィジェットと自社システムの API チャネルに同時に応答できます。それぞれ別の接続で、別のキーを持ちます。

環境とドメイン

すべて 1 つのアプリケーションドメインの下にあり、パスで区別します。API チャネルの受信 Webhook は https://console-agents.fpt.ai/webhooks/api、履歴 API は https://console-agents.fpt.ai/direct-bff/… です。Webhook のアドレスは組み立てずに、必ず Console からそのままコピーしてください。

API チャネルをつなぎ、キーを受け取る

1

FPT AI Agent Platform にサインインする

Console を開き、アカウントでサインインします。
2

設定する Agent を選ぶ

自社システムが転送するメッセージに応答する Agent です。
3

チャネルタブを開く

チャネル は Agent のナビゲーションバーにあります。
4

API のタイルをクリックする

API チャネルの設定パネルが開きます。
5

チャネルの設定を入力する

項目は 2 つです。下の表を参照してください。
6

設定を保存をクリックしてチャネルを作る

チャネルタブの API タイルが 設定済み に変わります。
7

新しいキーを生成をクリックする

ダイアログを閉じる前に、ルーティングキー と 署名キー をコピーしてください。
API チャネルの設定パネル
署名キーは、作られた瞬間に一度だけ表示されます。システムはハッシュしか保存しないので、あとから見る方法はありません。ダイアログを閉じる前に、秘密情報の保管先にコピーしてください。

受け取るもの

コールバック URL をテストする

入力欄の横の コールバックをテスト ボタンは、署名付きのリクエストをあなたのアドレスに送り、正しい応答を期待します。実装の仕方は下の「Webhook エンドポイントを検証する」を参照してください。このボタンは組織あたり毎分 10 回までです。

秘密鍵を入れ替える

1

新しいキーを生成をクリックする

この時点から、古いキーと新しいキーの両方が受け付けられます。
2

新しいキーをすべてのサーバーに配る

送信側と受信側の両方を確認してください。
3

入れ替えを完了をクリックする

古いキーが無効になります。以後は新しいキーだけが通ります。
最後の手順を飛ばさないでください。入れ替えを完了するまで古いキーは有効なままなので、忘れると実質的に何も入れ替わっていません。

イベントの署名を検証する

双方向のすべてのパケットは、チャネルの秘密鍵を使った HMAC-SHA256 で署名されます。署名は X-Hub-Signature-256 ヘッダーに sha256= の接頭辞付きで入り、送信時刻を載せた X-Hub-Timestamp ヘッダーが並びます。 署名の対象は、timestamp、ドット、生の本文をつないだ文字列です。
  • 送るバイト列そのものに署名してください。JSON をオブジェクトに解析してから再度文字列化すると、キーの順番が変わるだけでも署名が変わります。
  • タイムスタンプは署名の中に入っているので、パケットを捕まえた攻撃者が書き換えることはできません。現在の Unix 時刻を秒で送ってください。
  • サーバー時刻から前後 5 分を超えてずれたタイムスタンプは拒否されます。NTP で同期しておいてください。
  • 例外はありません。署名を省くモードはなく、キーを生成していない接続にも免除はありません。

Go での署名

Node.js での署名

プラットフォームから届く署名を検証する

同じ関数を再利用し、タイミングから情報が漏れないよう定数時間の比較を使います。
署名が合わない原因のほとんどは、Web フレームワークが本文をオブジェクトに解析してしまい、生のバイト列を読めなくなっていることです。生のまま保持する設定(express.raw、bodyParser.raw、または入力ストリームを直接読む)にして、検証が済んでから JSON を解析してください。

顧客のメッセージを受け取る

顧客が自社システムに送ったメッセージは、Webhook でプラットフォームに転送します。イベントは 2 つの部分、すなわちペイロードと、それを認証する署名からなります。

テキストメッセージ

ボタンやクイックリプライからのメッセージ

添付付きのメッセージ

パラメータ

text は常に必須です。postback だけのメッセージでも必要です。顧客のターンは保存され、担当者が会話を引き継ぐときに表示されるので、文字のない postback は受信箱に空の吹き出しを残します。ボタンのラベルを text として送ってください。
postback は別の文脈として Agent に届き、顧客の発言として扱われることはありません。人が打った言葉と、画面が運んできた値を区別できるようにするためです。ボタンもクイックリプライも、このフィールド 1 つで扱います。

cURL の例

レスポンスコード

200 は 受理 であって、回答済みではありません。Agent は非同期で動き、回答はそのあと Webhook に届きます。

重複排除

messageId は端から端までの重複排除キーです。同じ (integrationKey, messageId) の組み合わせを 5 分以内に再送しても認識して読み飛ばすので、タイムアウト後の再送で顧客に 2 回答えてしまうことはありません。
自社の安定したメッセージ ID を使ってください。再送のたびに新しい ID を作ると、重複排除がまったく効かなくなります。

受信の添付

attachments の各要素には、プラットフォームが取得できる url が必要です。ファイルの中身は組織のストレージにコピーされて Agent に渡されるので、渡した URL をそのあと長く生かしておく必要はありません。
添付のアップロードは、管理者が有効にするまでオフです。オフのとき、また上限を超えたファイルや取得に失敗したファイルは読み飛ばされますが、text は Agent に届きます。つまり添付付きのメッセージがエラーになることはなく、ファイルが取り込まれたかどうかはレスポンスコードからは分かりません。

追加データ

metadata のオブジェクトは、client_metadata の下に入れ子になって Agent に届きます。トップレベルに統合されることはありません。そこにあるキー、とくに宛先の識別子が、回答の届け先を決めるからです。 本文のトップレベルにある未知のフィールドは無視されるので、独自の項目を足しても拒否されません。

Agent からのコールバック

Agent の回答は、署名付きの POST で自社の Webhook に送られます。受信方向と同じく、イベントはペイロードとその署名からなります。

Webhook エンドポイントを検証する

最初の本番メッセージの前に、あなたのエンドポイントが想定どおりのものか、プラットフォームに確かめさせられます。Console の コールバックをテスト ボタンが、署名付きのリクエストを送ります。
通すには、受け取った challenge をそのまま返す JSON 本文とともに 2xx を返します。
  • 検証のリクエストもほかのパケットとまったく同じように署名されるので、すでに書いた関数がそのまま使えます。
  • type は検証のリクエストにだけ現れ、実際のメッセージには付きません。
  • challenge を返すことは必須です。素の 200 では足りません。放置されたドメイン、CDN のエラーページ、ロードバランサーのどれもが 200 を返しうるからです。
  • 検証ごとに challenge は変わります。
  • プラットフォームはリダイレクトをたどりません。301、302、303 は本文を失うので、正しく返しようがありません。
  • 何も保存されません。合格は、その時点でエンドポイントが正しく答えたという意味です。

コールバックイベントの構造

命名について: 外側のフィールドは lowerCamelCase (eventId、integrationKey、conversationId、occurredAt)、内容ブロックとその中のフィールドは snake_case (quick_replies、sub_title、image_url、file_name) です。これは手落ちではなく意図的で、内容ブロックはチャットウィジェットや会話履歴と語彙を共有しているためです。

Button

QuickReply

ボタン付きの画像は、要素 1 つのカルーセルとして送られます。

Reference

Attachment

いまのところ API チャネルの回答ターンにファイルを添付する機能はないので、attachments がコールバックに現れたことはありません。将来の互換性のために予約されています。受信方向の添付は通常どおり動きます。

ペイロードの例

ボタンのないテキストメッセージ
ボタン付きのメッセージ
クイックリプライ
カルーセル
出典付きの回答

コールバックの扱い方

  • text は buttons や carousels がある場合も必ず入っています。表示できないときの代わりになるので、テキストしか扱えないシステムでも会話は成立します。
  • 空のリストは [] ではなく、項目ごと省かれます。buttons、quick_replies、carousels、references は、そのターンに無ければ現れません。
  • conversationId と from は、古いバージョンのプラットフォームからのコールバックでは無いことがあります。無い場合は未確定として扱ってください。
  • 重複排除は runId ではなく eventId で行います。
  • 自社データとの突き合わせも runId ではなく conversationId で行ってください。runId は回答 1 ターンにすぎません。
  • すぐ 200 を返し、処理は非同期にしてください。1 回あたり 10 秒しかなく、処理が遅いと失敗とみなされて再送されます。

エンドポイントが失敗したとき

エンドポイントが長く落ちている間、配信は 最大 1 回 です。これは意図的な割り切りで、無制限に再送すると共有の配信基盤が詰まるためです。復旧の手段は下の履歴 API です。エラーキューはプラットフォーム側にあり、自動では再配信されません。

コールバック URL の要件

  • https であること(http は社内開発でのみ使えます)。
  • URL に認証情報を埋め込まないこと。プラットフォームの認証は署名で行い、パスに隠した秘密では行いません。
  • 公開インターネットのアドレスに解決されること。ループバック、プライベート、リンクローカル、ユニークローカル、マルチキャスト、キャリア NAT の各範囲は拒否されます。
  • 判定は接続時に行われるので、内部アドレスに解決されるドメインも拒否されます。
  • 2048 文字まで。

会話履歴を読み直す

これは、受け取れなかった回答ターンを回収する手段です。コールバックは最大 1 回の配信なので、3 回失敗したターンはエラーキューに残ります。この API がなければ、そのメッセージはあなたにとって失われたままです。
200 のレスポンス:
  • チャネルの秘密鍵ではなく、組織の API キーを使います。秘密鍵は「自社サーバーがメッセージを転送している」ことの証明で、こちらは「自分のデータを自分で読む」操作だからです。visitorToken は自分のセッションしか読めず、ほかを読むと 403 SESSION_FORBIDDEN になります。
  • カーソル方式のページングで、古い順に並びます。after に手元の最後のメッセージ ID を渡し、hasMore で次のページの有無を見ます。
  • メッセージ ID は JavaScript の安全な整数の範囲を超えるため文字列ですが、数値として並び替えられます。
  • role ではなく from を読んでください。人の担当者のターンは Agent と同じ role で保存されます。from の値は customer、bot、operator の 3 つです。
  • operator はまだ現れません。このチャネルで担当者が Agent の代わりに応答する機能はないためです。将来の互換性のために予約されています。
  • 返る行はすべて実際のターンです。text、ボタン、クイックリプライ、カルーセル、出典、添付のいずれかを持つ行だけが現れるので、空の吹き出しを除く処理は要りません。
  • 不正な after は黙って無視されず、400 が返ります。
  • 1 つの 404 が 3 つの場合をまとめています。会話が存在しない、別の組織のもの、社内の会話。意図的に区別できないようにしています。
  • 添付には名前、種類、サイズだけが入り、オブジェクトキーは入りません。
  • 履歴の読み出しは実行回数の枠を消費しません。既定で API キーあたり毎分 120 回という独自の枠を持ちます。
  • 履歴の枠を超えると、429 に Retry-After ヘッダーだけが付いて返ります。
これは復旧の手段であって、アーカイブではありません。データ保持ポリシーに従って顧客が削除されると、そのメッセージもすべて消えます。残しておきたいものは自社のシステムに同期してください。

API キーと利用枠

API キーを作る

組織の API キーは、履歴 API とファイルのダウンロードリンク API で使います。Console の API キー のページで作成します。
  • キーは sk- に続く 32 文字のランダムな文字列です。たとえば sk-9Kd2xQ…。
  • キーは作成時に一度だけ表示されます。システムはハッシュしか保存しないので、あとから見る方法はありません。
  • 一覧には先頭 12 文字が出るので、見分けられます。
  • キーは作った人の権限で動くため、新しい権限が増えることはありません。

キーの失効と入れ替え

失効は削除ではなくフラグです。失効したキーの ID もあとから解決できるので、監査証跡が読める状態を保てます。一覧には失効したキーも並びます。
キーはキャッシュされるため、失効が効くまで最大 30 秒かかります。レスポンスの revocationDelaySeconds フィールドがその秒数を伝えます。キーが漏れたときは直ちに失効させ、この遅延を見込んでください。
API キーの入れ替えは、この順番の 2 手順です。先に新しいキーを作り、次に古いキーを失効させる。その間は両方が有効です。

利用状況を確認する

  • runs は組織の 1 日あたりの枠(UTC)で、すべての会話とチャネルで共有します。resetsAt、つまり UTC の 00:00 に戻ります。
  • rate.limit は呼び出し元ごとの毎分の上限です。
  • 利用状況の確認は枠を消費しないので、何度でも呼べます。
  • API キー専用です。visitorToken は 403 USAGE_FORBIDDEN で拒否されます。
枠を消費する API は、成功時も 429 時も次の 3 つのヘッダーを返します。

次に読むもの

Live Chat チャネル

自前で作らず、用意されたチャット画面を使う場合に。

モバイル SDK

Android と iOS のアプリにチャット画面を組み込みます。

技術付録

エラーコード、システムの上限、本番前チェックリスト。