このガイドでは、Apps API を使用してサーバーサイドのチャット インテグレーションを構築する方法について説明します。このガイドを読み終えると、インテグレーションで次のことができるようになります。
Apps API に対する認証。
エンドユーザーの作成または更新。
エンドユーザーのチャットを開始する。
コンタクト センター AI プラットフォームからの Webhook イベントを受信して検証する。
チャットにテキスト メッセージを送信する。
事前チャットの文字起こしインポート、キュー選択の仮想エージェント ルーティング、エスカレーションの回避、メディア添付ファイルなどのオプションのブランチを処理する。
会話が完了したらチャットを終了する。
このガイドは、お客様所有のチャット エクスペリエンスを CCAI Platform に接続するバックエンド サービスを構築するデベロッパーを対象としています。CCAI Platform で API 認証情報を作成し、HTTPS Webhook エンドポイントをホストし、シークレットを安全に保存し、サーバーから HTTP リクエストを行うことができることを前提としています。
このガイドは、Apps API のチャット エンドポイントを補完するものです。リクエストとレスポンスのスキーマの詳細については API リファレンスを参照し、エンドツーエンドの実装フローについてはこのガイドを参照してください。
用語
このドキュメントで適用される用語の定義は次のとおりです。
お客様: 独自のソフトウェアにチャット インテグレーションを実装する CCAI Platform のお客様。
コンシューマー: Apps API にリクエストを送信し、CCAI Platform Webhook イベントを受信する、お客様所有のサーバーサイド アプリケーション。
エンドユーザー: お客様のソフトウェアを使用して、エージェントまたは仮想エージェントとのチャットを開始または継続するユーザー。
チャット: Apps API が作成する CCAI Platform 会話リソース。
Webhook エンドポイント: CCAI Platform からチャット イベントを 受信するコンシューマー アプリケーションの HTTPS エンドポイント。
始める前に
Firebase を追加する前に、次の準備をしてください。
Apps API 認証情報
CCAI Platform で [設定] > [デベロッパー設定] > [API 認証情報] から API 認証情報を作成します。
認証情報のシークレットは安全に保存してください。ブラウザやモバイル クライアント コードで公開しないでください。
テナント URL の詳細
CCAI Platform のサブドメインとドメインを特定します。
Apps API のベース URL は
https://YOUR_SUBDOMAIN.YOUR_DOMAIN/apps/api/v1です。
Webhook エンドポイント
CCAI Platform からの POST リクエストを受信できる公開 HTTPS エンドポイントをホストします。
CCAI Platform のデベロッパー設定でエンドポイントを構成します。
Webhook のプライマリ シークレットとセカンダリ シークレットを生成して保存します。
キューまたはメニューの構成
新しいチャットが入力されるキューまたはメニューを特定します。
キュー選択の仮想エージェントを使用する場合は、API を介してチャットを作成する前に、その仮想エージェントを構成してエントリ キューに割り当てます。
エンドユーザー ID
システムで各エンドユーザーに使用する安定した識別子を決定します。
Apps API から返された CCAI Platform エンドユーザー ID を保存します。
レート制限の処理
- CCAI Platform は Apps API のレートを制限します。インテグレーションに再試行とバックオフを組み込み、単一のテナントに対してリクエストをバーストで送信しないようにしてください。
認証と Webhook のセキュリティ
インテグレーションでは、次の 2 つの認証パスを使用します。
サーバーから CCAI Platform へのリクエストに対する Apps API 認証。
CCAI Platform からサーバーへのリクエストに対する Webhook 署名検証。
Apps API リクエストを認証する
リクエストでは HTTP 基本認証を使用します。CCAI Platform で [設定] > [デベロッパー設定] > [API 認証情報] で API トークンを作成し、 [password] フィールドに渡します(推奨)。テナントが従来の認証パスを使用している場合は、代わりに会社の鍵をユーザー名として、会社のシークレットをパスワードとして渡すことができます。認証の設定の詳細については、Apps API リファレンスをご覧ください。次の例は、基本認証を使用して Apps API リクエストを認証する方法を示しています。
curl -X GET \
https://YOUR_SUBDOMAIN.YOUR_DOMAIN/apps/api/v1/chats/{chat_id} \
-u "YOUR_SUBDOMAIN:YOUR_API_TOKEN" \
-H "Accept: application/json"
認証情報はサーバーサイドのシークレット ストアに保存し、セキュリティ ポリシーに従ってローテーションします。ブラウザやモバイルアプリで送信しないでください。
Webhook リクエストを検証する
CCAI Platform は、Webhook エンドポイントにチャット イベントを送信します。各 Webhook リクエストには次のものが含まれます。
X-SignatureX-Signature-Timestamp
X-Signature ヘッダーには、プライマリ署名、セカンダリ署名、またはその両方を含めることができます。
primary=<primary_signature> secondary=<secondary_signature>
各署名は、Base64 でエンコードされた HMAC-SHA256 ダイジェストです。署名付きの値は、タイムスタンプ ヘッダーと未加工の JSON リクエスト本文を連結したものです。
X-Signature-Timestamp + raw_request_body
Webhook ハンドラで次の操作を行います。
X-SignatureとX-Signature-Timestampを読み取ります。いずれかのヘッダーがない場合は、リクエストを拒否します。
古いタイムスタンプを拒否して、リプレイのリスクを軽減します。
JSON を解析する前に、未加工のリクエスト本文を読み取ります。
アクティブな Webhook シークレットごとに、想定される署名を計算します。
一定時間比較を使用して、受信した署名と想定される署名を比較します。
アクティブなシークレットが一致する場合は、リクエストを受け入れます。
次の Ruby 実装例は、UJET Webhook 署名を検証する方法を示しています。
require "base64"
require "openssl"
require "active_support/security_utils"
def parse_ujet_signature(header)
header.to_s.split(/\s+/).each_with_object({}) do |part, result|
key, value = part.split("=", 2)
result[key] = value if key && value
end
end
def expected_signature(secret, timestamp, raw_body)
Base64.strict_encode64(
OpenSSL::HMAC.digest(
OpenSSL::Digest.new("sha256"),
secret,
"#{timestamp}#{raw_body}"
)
)
end
def secure_match?(received, expected)
return false if received.nil? || expected.nil?
return false unless received.bytesize == expected.bytesize
ActiveSupport::SecurityUtils.secure_compare(received, expected)
end
def verify_ujet_webhook!(request, primary_secret:, secondary_secret:)
signature_header = request.headers["X-Signature"]
timestamp = request.headers["X-Signature-Timestamp"]
return false if signature_header.nil? || timestamp.nil?
# Optional but recommended: reject stale requests.
return false if (Time.now.utc - Time.at(timestamp.to_i).utc).abs > 5.minutes
raw_body = request.body.read
signatures = parse_ujet_signature(signature_header)
expected = [
expected_signature(primary_secret, timestamp, raw_body),
expected_signature(secondary_secret, timestamp, raw_body)
].compact
received = [
signatures["primary"],
signatures["secondary"]
].compact
received.any? do |received_signature|
expected.any? do |expected_signature_value|
secure_match?(received_signature, expected_signature_value)
end
end
end
検証に成功したら、成功レスポンスを迅速に返し、イベントをべき等に処理します。Webhook の配信と API レスポンスは異なる順序で到着する可能性があるため、重複するレコードを作成せずに同じ状態変更を複数回受信できるようにインテグレーションを構築してください。
インテグレーションのフロー
次のフローでは、エンドユーザーの作成、チャットの開始、CCAI Platform イベントの受信、メッセージの交換、チャットの終了を行います。
エンドユーザーを作成または更新する
目標: チャットを作成する前に、CCAI Platform にエンドユーザー レコードがあることを確認します。
エンドポイント
次のエンドポイントを使用して、エンドユーザーを作成または更新します。
POST /apps/api/v1/end_users
リクエストの例
次の例は、エンドユーザーの作成または更新のリクエスト本文を示しています。
{
"identifier": "customer-user-12345",
"email": "customer.user@example.com",
"name": "Customer User",
"phone": "+15551234567"
}
保存するデータ
レスポンスから CCAI Platform エンドユーザー ID をシステムに保存します。チャットを作成するときにその ID を使用します。
どのようなことを行えるか
エンドユーザーが存在しない場合、CCAI Platform は新しいレコードを作成します。
同じ識別子を持つエンドユーザーがすでに存在する場合、CCAI Platform はレコードを更新し、既存のエンドユーザーの情報を返します。
チャットを作成する
目標: エンドユーザーの新しい CCAI Platform チャットを開始します。
エンドポイント
次のエンドポイントを使用して、新しいチャットを開始します。
POST /apps/api/v1/chats
リクエストの例
次の例は、チャットを作成するためのリクエスト本文を示しています。
{
"chat": {
"menu_id": 123,
"end_user_id": 456,
"lang": "en"
}
}
仮想エージェント ルーティングのオプションのコンテキスト
キュー選択の仮想エージェントがアプリケーションのコンテキストを必要とする場合は、次の例に示すように、チャットの作成時にコンテキスト ペイロードを含めます。
{
"chat": {
"menu_id": 123,
"end_user_id": 456,
"lang": "en",
"context": {
"value": {
"customer_tier": "gold",
"issue_type": "billing"
}
}
}
}
仮想エージェントは、そのコンテキストの値を使用して、チャットを受信するキューを決定できます。
どのようなことを行えるか
Apps API はチャット リソースを返します。
CCAI Platform は、構成済みの Webhook エンドポイントに
chat_createdWebhook イベントを送信します。API レスポンスと Webhook イベントは、どちらの順序で到着する可能性があります。どちらも、チャット ID をキーとする同じチャット レコードの更新として扱います。
チャット Webhook イベントを処理する
目標: コンシューマー アプリケーションを CCAI Platform のチャット状態と同期させます。
Webhook エンドポイントは、CCAI Platform からのチャット ライフサイクル イベントとメッセージ イベントを処理します。少なくとも次のものを保存します。
チャット ID。
イベントタイプ。
イベント タイムスタンプ。
イベントにメッセージが含まれている場合は、メッセージの送信者、メッセージ タイプ、メッセージ コンテンツ。
イベントがルーティング動作を表す場合は、エスカレーションまたは回避データ。
推奨される動作
イベントを処理する前に、すべての Webhook 署名を検証します。
処理済みのイベント ID または決定的なイベントキーを保存して、再試行で重複が作成されないようにします。
イベントを受け入れたら、2xx レスポンスを返します。
可能な場合は、ダウンストリームの副作用を非同期で処理します。
どのようなことを行えるか
CCAI Platform がチャットの作成、受信メッセージ、エージェント メッセージ、エスカレーションの変更、チャットの完了などのイベントを送信すると、アプリケーションはチャットの状態を更新します。
テキスト メッセージを送信する
目標: コンシューマー アプリケーションから CCAI Platform チャットにエンドユーザー メッセージを送信します。
エンドポイント
次のエンドポイントを使用して、チャットにテキスト メッセージを送信します。
POST /apps/api/v1/chats/{chat_id}/message
リクエストの例
次の例は、テキスト メッセージを送信するためのリクエスト本文を示しています。
{
"from_user_id": 456,
"message": {
"type": "text",
"content": "Hello, I need help with my order."
}
}
どのようなことを行えるか
CCAI Platform はメッセージを受け入れます。
メッセージは、エージェントまたは仮想エージェントの会話に表示されます。
Webhook エンドポイントは、Apps API を介して独自のアプリケーションが送信したメッセージなど、メッセージのメッセージ イベントを受信します。
CCAI Platform からメッセージを受信して表示する
目標: お客様所有のチャット エクスペリエンスでエージェントまたは仮想エージェントのメッセージを表示します。
Webhook エンドポイントがメッセージ イベントを受信したら、次の操作を行います。
Webhook 署名を検証します。
イベントが新しいかどうかを確認します。
チャット ID でチャットを特定します。
送信者とメッセージ タイプを特定します。
お客様所有のチャット UI でメッセージをレンダリングします。
更新や再試行で会話履歴が失われないように、イベントを永続化します。
どのようなことを行えるか
お客様所有のチャット UI に、エージェント、仮想エージェント、エンドユーザーが送信したメッセージが正しい順序で表示されます。イベントが順不同で到着した場合は、イベント タイムスタンプと独自の永続レイヤを使用して表示順序を調整します。
仮想エージェントから人間のエージェントにエスカレーションする
目標: エンドユーザーがエージェントのサポートを必要とする場合、チャットを仮想エージェントの処理から人間のキューに移動します。
インテグレーションでキュー選択の仮想エージェントを使用する場合は、チャットをターゲット キューにルーティングするように仮想エージェントを構成します。サーバーがエスカレーションを直接開始する場合は、Apps API エスカレーション エンドポイントを使用します。
エンドポイント
次のエンドポイントを使用して、チャットを仮想エージェントから人間のエージェントにエスカレーションします。
POST /apps/api/v1/chats/{chat_id}/escalations
リクエストの例
次の例は、チャットをエスカレーションするためのリクエスト本文を示しています。
{
"reason": "by_end_user_ask",
"force_escalate": false
}
どのようなことを行えるか
ターゲット キューが使用可能な場合、チャットはエージェントの処理に進みます。
営業時間外または容量超過のためキューが使用できない場合、CCAI Platform はチャットフローを介して回避オプションを返したり送信したりできます。
インテグレーションは、利用可能な回避オプションをエンドユーザーにレンダリングします。
エスカレーション回避の選択を記録する
目標: エンドユーザーが選択した回避オプションを CCAI Platform に通知します。
CCAI Platform がエスカレーション回避オプションを提供したら、エスカレーション更新エンドポイントを使用してエンドユーザーの選択を記録します。
エンドポイント
次のエンドポイントを使用して、回避選択でエスカレーション レコードを更新します。
PATCH /apps/api/v1/chats/{chat_id}/escalations/{escalation_id}
サポートされている deflection_channel の値:
email- エンドユーザーがメール回避オプションを選択します。virtual_agent- エンドユーザーが仮想エージェントとの継続を選択します。human_agent- エンドユーザーが人間のエージェントを待機し続けることを選択します。この値は、容量超過の回避にのみ適用されます。
リクエストの例
次の例は、回避選択を記録するためのリクエスト本文を示しています。
{
"deflection_channel": "email"
}
このエンドポイントには、サポートされている deflection_channel 値のみを送信してください。
external_link はエスカレーション更新エンドポイントの有効な値ではありません。エンドユーザーが外部回避リンクをクリックすると、チャットは終了します。
どのようなことを行えるか
CCAI Platform はエスカレーション レコードを更新し、選択したオプションに従ってチャットを移行します。
チャットを終了する
目標: 会話が完了したらチャットを閉じます。
エンドポイント
次のエンドポイントを使用して、アクティブなチャットを終了します。
PATCH /apps/api/v1/chats/{chat_id}/end
リクエストの例
次の例は、チャットを終了するためのリクエスト本文を示しています。
{
"ended_by_user_id": 456
}
どのようなことを行えるか
CCAI Platform はチャットを終了します。
Webhook エンドポイントは、最後のチャット状態イベントを受信します。
アプリケーションはチャットを完了としてマークし、そのチャットの新しいエンドユーザー メッセージの受け入れを停止します。
高度なフロー
次のブランチは省略可能です。インテグレーションに適用されるフローのみを実装してください。
事前チャットの文字起こしをインポートする
CCAI Platform チャットを作成する前に、エンドユーザーがシステムで会話(chatbot の会話など)を行っていた場合は、このフローを使用します。
チャットの作成時に文字起こしペイロードを追加します。文字起こしにより、エージェントはコンテキストを把握できるため、エンドユーザーは情報を繰り返す必要がありません。
Apps API リファレンスには、正確な文字起こしスキーマが記載されています。
キュー選択の仮想エージェントでチャットをルーティングする
アプリケーションがすべての新しいチャットをエントリ キューに送信し、仮想エージェントが最終的なターゲット キューを決定する場合は、このフローを使用します。
キュー選択用の仮想エージェントを作成します。
仮想エージェントをエントリ キューに割り当てます。
チャットの作成時にコンテキストを含めます。
コンテキストを検査してチャットを正しいキューにエスカレーションするように仮想エージェントを構成します。
ターゲット キューが使用できない場合は、回避オプションを処理します。
写真や動画の添付ファイルを送信する
エンドユーザーがお客様所有のチャット UI からメディアを送信する場合は、このフローを使用します。
メディアフローには 4 つのステージがあります。
ステージ 1 - 署名付きアップロード URL をリクエストする
写真や動画をアップロードするための署名付き URL をリクエストするには、次のエンドポイントを使用します。
POST /apps/api/v1/chats/{chat_id}/photos/upload
POST /apps/api/v1/chats/{chat_id}/videos/upload
ステージ 2 - 返されたストレージ URL にファイルをアップロードする
ファイルと、CCAI Platform が署名付きアップロード レスポンスで返すフィールドを含めます。
ステージ 3 - アップロードしたファイルをチャットに追加する
アップロードした写真や動画をチャットに追加するには、次のエンドポイントを使用します。
POST /apps/api/v1/chats/{chat_id}/photos
POST /apps/api/v1/chats/{chat_id}/videos
CCAI Platform が返す media_id を保存します。チャット メッセージ ペイロードは、メディア ID でメディアを参照します。
ステージ 4 - メディアをメッセージとして送信する
次のエンドポイントを使用して、チャットにメディア メッセージを送信します。
POST /apps/api/v1/chats/{chat_id}/message
リクエストの例
次の例は、写真の添付ファイルを送信するためのリクエスト本文を示しています。
{
"from_user_id": 456,
"message": {
"type": "photo",
"content": {
"media_id": 789
}
}
}
動画メッセージには、video メッセージ タイプと動画 media_id を使用します。
チャット中にカスタムデータを送信する
インテグレーションで、お客様定義のコンテキストをアクティブなチャットに添付する必要がある場合は、次のエンドポイントを使用します。
POST /apps/api/v1/chats/{chat_id}/custom_data
Apps API リファレンスでは、正確なペイロードの形状と予約済みキーの動作が定義されています。
チャット中にエンドユーザー ID を更新する
チャットの開始後にエンドユーザーの ID が変更された場合や判明した場合は、次のエンドポイントを使用します。
POST /apps/api/v1/chats/{chat_id}/end_user
たとえば、匿名のエンドユーザーがアクティブなチャット中にログインし、インテグレーションで CCAI Platform がチャットを更新されたエンドユーザー ID に関連付ける必要がある場合は、このエンドポイントを使用します。
CSAT データまたは評価データを収集する
インテグレーションでチャット後の評価エクスペリエンスを所有している場合は、次のチャット CSAT エンドポイントと評価エンドポイントを使用します。
GET /apps/api/v1/chats/{chat_id}/csat
GET /apps/api/v1/chats/{chat_id}/rating
PATCH /apps/api/v1/chats/{chat_id}/rating
正確な適格性ルールと評価ペイロードについては、Apps API リファレンスをご覧ください。