本文說明當 CRM 端點傳回 HTTP
200 "Success." 以外的回應時,CCAI Platform 自訂 CRM (一般 API) 功能的行為,可做為整合人員設定 API 帳戶和 API 記錄端點時的行為參考。
高階執行順序和關係
當互動觸發自訂 CRM 整合時,平台會依下列順序呼叫端點:
帳戶層級作業 (API 帳戶) - 聯絡人
範例:
尋找聯絡人。
建立聯絡人。
更新聯絡人。
記錄層級作業 (API 記錄) - 票證或案件
範例:
尋找票券。
建立支援單。
更新票證。
工作階段後動作 (如有設定)
範例:
新增留言或附註。
上傳附件或轉錄稿。
套用收尾更新。
先前步驟產生的 ID,通常會用於後續步驟。舉例來說,如果端點酬載範本包含 contact_id,則可在建立票證時傳遞;在一般 API 設定中,ticket_id 則是工作階段後動作的必要項目。請注意,並非所有端點都設定為擷取 ID,詳情請參閱「重要細微差異:2xx + 擷取 ID 的端點缺少 ID」一節。
重要細微差異:2xx + 擷取 ID 的端點缺少 ID
並非所有自訂 CRM 端點都會從收到的回應中擷取 ID。這項行為僅適用於設定 response_data_location 和 custom_id_location (用於建立端點) 的端點,通常是查詢端點 (擷取現有記錄的 ID) 和建立端點 (擷取新建立記錄的 ID)。註解、附件和更新等端點不會從回應中擷取 ID。
缺少 ID 對 ID 擷取端點的影響
查詢端點:如果
200 OK回應沒有相符記錄 (因此沒有可擷取的 ID),則屬於正常的「找不到」行為。如果執行個體已啟用skip_account_creation或skip_record_creation,平台會刻意繼續下游作業,並使用空值contact_id或ticket_id,而不是嘗試建立。這是這些設定的預期行為,並非設定錯誤。建立端點:如果
200 OK回應在設定的位置未包含新建立的 ID,則屬於設定或回應合約問題。HTTP 要求成功,因此不會觸發重試,但下游步驟可能會在資料遺失的情況下繼續執行。在這兩種情況下,失敗 (如果是失敗) 會顯示為資料遺失,而非端點錯誤,這可能會在偵錯期間造成混淆。
整合商指南
對於建立作業,請在設定的位置傳回預期的 ID,做為成功合約的一部分,而不只是傳回
2xx。如果缺少 ID,請視為設定或回應合約問題,並進行調查。如果是查詢作業,傳回
200 OK且沒有相符項目是可接受的。如果您的執行個體刻意依賴「查詢而不建立」模式 (例如skip_account_creation = true),請記錄這項決策,讓下游端點知道如何妥善處理缺少的 ID。在測試中,請確認:
如果是建立端點,ID 會可靠地出現在回應中,且位於自訂 CRM 中設定的確切位置。
對於查詢端點,平台的下游行為會與執行個體的略過旗標設定相符。
錯誤處理:總覽
如果端點傳回非成功回應 (非 2xx) 或未回應:
平台可能會重試要求:
部分狀態會立即傳送一次。
如果失敗可以重試,則會延長時間。
平台持續重試上游步驟時,下游步驟可能會延遲。
部分失敗會視為不可重試 (例如設定或驗證失敗)。
如要瞭解詳細的重試規則,請參閱「重試和輪詢行為」。失敗與下游呼叫之間的關係,請參閱「鏈結和依附元件規則」。
鏈結和依附關係規則
自訂 CRM 行為是由執行個體的 CRM 設定控管,具體來說,就是「略過 CRM 帳戶和記錄建立」中記錄的設定。本文會以這些設定的後端設定名稱 (skip_account_creation、skip_account_lookup、skip_record_creation) 稱呼,因為這些設定在下列 JSON 設定範例中就是以這種方式呈現。
在這些設定中,平台會盡可能繼續執行鏈結,例如在查詢失敗且啟用帳戶建立功能時建立匿名聯絡人,而不是一律「硬性停止」。
帳戶失敗對記錄作業的影響
即使帳戶步驟未產生聯絡人,記錄步驟 (票證/案件) 仍可能執行,但確切行為取決於執行個體的設定。
視設定而定,平台可以:
建立匿名聯絡人做為備用,並繼續建立票證。
如果帳戶查詢或帳戶建立作業設為略過,請繼續錄製步驟,不需使用
contact_id。
對端點的影響
建立票證時缺少
contact_id,通常表示執行個體設定停用了帳戶查詢或帳戶建立功能。如果執行個體需要帳戶,請將缺少的
contact_id視為值得調查的信號,而不是在沒有聯絡人的情況下默默插入票證。如果您的設定刻意允許在沒有聯絡人的情況下建立票證,請務必確保票證端點能明確且可預測地處理這種情況。
記錄失敗對工作階段後動作的影響
如果一般 API 設定已設定票券查詢,平台就不會調度工作階段後呼叫,例如 call_finished、chat_finished、email_finished、save_call_recording、save_chat_history、update_ticket 和 done_ticket,直到 ticket_id 存在為止。
如果叫用工作階段後端點時未提供 ticket_id,通常表示發生下列其中一種情況:
執行個體設定已停用票券查詢功能,這在一般通用 API 設定中並不常見。
酬載範本省略了
ticket_id變數,這是值得調查的設定問題。
對端點的影響
如果工作階段後呼叫缺少
ticket_id,請將其視為值得調查的設定信號,而非預期行為而默默接受。如果設定刻意不要求查詢票證,請設定工作階段後端點,妥善處理缺少的
ticket_id。舉例來說,記錄問題和無作業,或傳回清楚、結構良好的錯誤訊息,而不是當機。
重試和輪詢行為
重試作業會在三個層級進行:
HTTP 層級立即重試 (快速嘗試第二次)。
轉接程式層級重試 (快速復原網路故障和特定暫時性回應)。
指令層級重試 (數天內長尾重試)。
HTTP 層級立即重試 (快速重試)
對於某些暫時性狀態,平台最多會嘗試 2 次 (1 次初始嘗試 + 1 次立即重試)。這通常適用於下列錯誤狀態:
408、413、429、500、502、503、504、521、522和524。
轉接器層級重試 (快速復原網路)
在 HTTP 呼叫和指令層級排程之間,CRM 轉接器 (command_runner.js) 中的中繼重試層會處理完全不會產生 HTTP 回應,或與特定暫時訊息相符的失敗:
立即重新排入佇列:由 TCP/通訊端層級錯誤觸發 -
ECONNRESET、ENOTFOUND、ESOCKETTIMEDOUT、ETIMEDOUT、ECONNREFUSED、EHOSTUNREACH、EPIPE、EAI_AGAIN。這類網路失敗發生在收到 HTTP 回應之前。延遲 30 秒重試:錯誤訊息為
"Too Early"(HTTP 425)、"Service Unavailable"或"Unordered Collection"時觸發。此層級無法重試:所有其他項目都會落入指令層級重試排程 (第 3 層)。
對整合商的重要性
如果平台無法建立或維持與端點的 TCP 連線,就會發生這類錯誤,這通常表示伺服器發生問題 (伺服器故障、拒絕連線,或在要求中途斷線),而不只是內部基礎架構的問題。實際效果是,部分網路故障的復原速度比 7 天指令層級排程快得多,通常在幾秒內就能完成。
指令層級重試 (約 7 天,14 次嘗試)
如果作業失敗且可以重試,平台最多可能會在約 7 天內重試 14 次,時間表如下:
10s → 1m → 5m → 30m → 1h → 6h → 6h → 12h → 1d → 1d → 1d → 1d → 1d → 1d
這種長尾重試行為適用於:
帳戶作業。
記錄作業。
工作階段後作業。
無法重試的失敗
部分失敗會視為無法重試,例如:
設定或驗證失敗 (例如未設定或誤設必要端點)。
平台偵測到的特定內部錯誤類別。
如要確保失敗視為永久失敗 (不重試),請與支援團隊或導入團隊聯絡,確認在特定設定中,指出不可重試失敗的正確方式。
逾時和網路故障
平台會處理兩種不同的路徑:
應用程式層級逾時:超過設定的 HTTP 逾時時間 (要求已傳送,但未收到回應) 時,平台會引發內部錯誤,可在指令層級 (第 3 層) 重試。這表示要求會遵循標準輪詢排程 (在約 7 天內最多重試 14 次)。
TCP/通訊端層級錯誤:在收到 HTTP 回應之前,如果連線在網路層級失敗 (例如
ETIMEDOUT、ESOCKETTIMEDOUT和ECONNREFUSED),轉接器層 (第 2 層) 會擷取這些錯誤,並立即重新排入指令。這類故障的復原速度通常快得多,往往只要幾秒鐘,而不是按照 7 天的排程。
區分兩者的重要性
應用程式逾時 (伺服器接受連線,但未及時回應) 的重試速度較慢。
如果是網路層級失敗 (完全無法連上伺服器),重試速度會快得多。
在這兩種情況下,系統可能已處理部分要求,因此端點應具備冪等性,詳情請參閱「建構彈性端點 (冪等性和設計提示)」。
狀態碼和逾時行為矩陣 (含範例)
下表和範例說明 CCAI Platform 如何處理不同的 HTTP 狀態碼、逾時和網路故障。
結果摘要表
下表中的 ID 相關資料列僅適用於設定為從回應中擷取 ID 的端點,例如查詢或建立端點。大多數其他端點不會擷取回應 ID。
| 結果 | 範例 | 立即重試 HTTP? | 長尾重試 (約 7 天)? | 後續影響 |
|---|---|---|---|---|
| 成功擷取 ID 的端點 | 2xx + 預期 ID 存在於設定的回應位置。 |
否 | 否 | 下游會繼續處理擷取的 ID。 |
| 查無相符項目 | 2xx,但在設定的位置找不到記錄。 |
否 | 否 | 正常的「找不到」行為。啟用 skip_account_creation 或 skip_record_creation 後,下游會刻意繼續使用空值 ID。 |
建立不含 ID 的回訪2xx |
2xx 來自建立端點,但新記錄的 ID 在設定的位置遺失。 |
否 | 否 | 下游可能會繼續處理遺漏的資料。視為設定或回應合約問題。 |
| 非 ID 擷取端點成功 | 2xx 來自不擷取 ID 的端點,例如附註、更新或附件動作。 |
否 | 否 | 下游會根據指令鏈和執行個體設定繼續執行。 |
| 暫時性錯誤 | 408、413、429、500、502、503、504、521、522和 524。 |
是 (共兩次機會) | 通常可以 | 重試期間,下游步驟可能會延遲。 |
| 其他錯誤 | 400、401、403、404和其他 4xx/5xx。 |
否 | 通常可以 | 重試期間,下游步驟可能會延遲。 |
| 設定/驗證失敗 | 設定錯誤、缺少端點。 | 不適用 | 否 | 鏈結可能會停止或部分完成,具體取決於設定。 |
| 網路層級失敗 (TCP/通訊端) | ECONNRESET、ENOTFOUND、ESOCKETTIMEDOUT、ETIMEDOUT、ECONNREFUSED、EHOSTUNREACH、EPIPE和EAI_AGAIN。 |
不適用 | 否 (由轉接器第 2 層處理) | 轉接器會立即重新排入佇列,通常很快就會復原 (幾秒內)。下游步驟可能會短暫延遲。 |
| 應用程式層級逾時 | HTTP timeout exceeded (未收到任何回應)。 |
不適用 | 通常可以 (第 3 層) | 在指令層級重試期間,下游步驟可能會延遲。 |
範例:使用最基本的通用 API 設定
基準自訂 CRM 一般 API 設定,包含鏈結執行的三個端點:尋找或建立聯絡人、尋找或建立票證,以及工作階段後留言。請以這份範本為基礎,並根據客戶關係管理系統的具體情況進行調整。
執行個體層級設定
{
"lookup_method": "genericApi",
"auth_method": "basic",
"basic_auth_username": "ccai-integration",
"basic_auth_password": "<secret>",
"api_request_timeout": 10,
"case_lookup_url": "https://crm.example.com/api/cases/{RECORD_ID}",
"contact_lookup_url": "https://crm.example.com/api/contacts/{ACCOUNT_ID}",
"skip_account_lookup": false,
"skip_account_creation": false,
"skip_record_creation": false
}
回應形狀
客戶關係管理系統的回應格式因客戶而異。response_data_location 是 lodash 樣式的路徑,可連至剖析後回應主體中的相關物件。不一定要將回應包裝在頂層 data 欄位中,以下範例預設顯示實際的平面形狀。
舉例來說,如果客戶關係管理系統將資源嵌套在 data.contact 下,則會設定 response_data_location: "data.contact",並將回應主體設為 { "contact": { "id": "c_99812" } };其餘設定則維持不變。
端點 1 - contact_find_endpoint
依電話號碼或電子郵件地址查詢聯絡人。
{
"request_url": "https://crm.example.com/api/contacts/search?phone={PHONE_NUMBER}&email={EMAIL}",
"request_method": "GET",
"request_parameters": {},
"response_data_location": "data"
}
成功:找到聯絡人
200 OK
Content-Type: application/json
{ "id": "c_42018", "first_name": "Jane", "last_name": "Doe" }
找不到聯絡人
404 Not Found
平台會將 404 視為「找不到」(而非錯誤)。如果 skip_account_creation 為 false,流程會繼續執行 contact_create_endpoint。
找不到替代模式:也有效
200 OK
{}
如果沒有相符的記錄,部分 CRM 會傳回含有空白資料的 200 OK,而非 404。平台會以相同方式處理這兩種情況,兩者都會觸發下一個步驟 (建立,如果已啟用)。
暫時性失敗
503 Service Unavailable
}
觸發第 1 層立即 HTTP 重試 (共 2 次嘗試)。如果仍失敗,則會進入第 3 層指令層級重試。
端點 2 - contact_create_endpoint
建立聯絡人。custom_id_location 欄位會告知平台,在回應中何處可找到新聯絡人的 ID。
{
"request_url": "https://crm.example.com/api/contacts",
"request_method": "POST",
"request_parameters": {
"first_name": "{FIRST_NAME}",
"last_name": "{LAST_NAME}",
"email": "{EMAIL}",
"phone": "{PHONE_NUMBER}",
"external_session_id": "{SESSION_TYPE}-{SESSION_ID}"
},
"response_data_location": "data",
"custom_id_location": "id"
}
成功建立
201 Created
{ "id": "c_99812", "first_name": "John", "last_name": "Doe" }
2xx,但設定的位置缺少 ID
200 OK
{}
端點傳回 200 OK,但設定的位置沒有 id。平台會記錄警告,並將空值 contact_id 轉送至下游 (不會擲回例外狀況,也不會重試)。請將此視為設定問題:response_data_location 和 custom_id_location 應能可靠地為端點從此路徑傳回的任何 2xx 產生 ID。
端點 3 - case_create_endpoint
建立支援單。上一個步驟中的 contact_id 可做為 {ACCOUNT_ID} 使用。
{
"request_url": "https://crm.example.com/api/cases",
"request_method": "POST",
"request_parameters": {
"subject": "{TICKET_SUBJECT}",
"description": "{TICKET_DESCRIPTION}",
"contact_id": "{ACCOUNT_ID}",
"channel": "{CHANNEL}",
"external_session_id": "{SESSION_TYPE}-{SESSION_ID}"
},
"response_data_location": "data",
"custom_id_location": "id"
}
成功建立
201 Created
{ "id": "case_77103", "status": "new" }
使用 response_data_location: "data" 時,平台會將路徑解析為剖析後的回應主體。接著,系統會讀取 custom_id_location: "id" → ticket_id = "case_77103" 的欄位,並將其傳送至工作階段後。
端點 4 - case_comment_endpoint
這個端點會在通話或即時通訊結束後,在票證中新增工作階段摘要註解。RECORD_ID 變數會帶有步驟 3 產生的 ticket_id。
{
"request_url": "https://crm.example.com/api/cases/{RECORD_ID}/comments",
"request_method": "POST",
"request_parameters": {
"body": "{COMMENT_BODY}",
"agent_email": "{AGENT_EMAIL}",
"channel": "{CHANNEL}",
"duration": "{CALL_DURATION}",
"external_session_id": "{SESSION_TYPE}-{SESSION_ID}"
}
}
如果一般 API 執行個體已設定 case_lookup_url,平台會等到票證建立步驟成功完成後,才調度這個端點。因此,如果這裡缺少 RECORD_ID,代表設定有問題,而非暫時狀態。
變化版本:停用帳戶建立功能
這個範例與前一個範例非常相似,都是最小的一般 API 設定,但這裡的執行個體不允許在 CRM 中建立聯絡人。系統會執行帳戶查詢,但不會建立帳戶。
執行個體設定變更
{
"skip_account_creation": true,
"skip_account_lookup": false
}
執行個體設定變更包括下列行為:
帳戶步驟只會呼叫
contact_find_endpoint。如果找不到聯絡人,就不會呼叫contact_create_endpoint。記錄步驟會收到空值
contact_id。平台會繼續建立票證,但不會有contact_id,因為{ACCOUNT_ID}會解析為空白,且contact_id欄位會從case_create_endpoint酬載中完全捨棄。也就是說,您的票券建立端點必須能在這項設定中建立不含
contact_id的票券。如果 CRM 要求每張票證都必須有關聯的聯絡人,則這項設定不相容。
case_create_endpoint的防禦模式
如果沒有 contact_id,客戶關係管理系統對來電者的瞭解會比平常少。您可以使用 =DEFAULT_VALUE 輔助程式,擷取要求中可用的任何識別資訊,並做為備用信號傳遞:
"request_parameters": {
"subject": "{TICKET_SUBJECT}",
"contact_id": "{ACCOUNT_ID}",
"contact_origin": "=DEFAULT_VALUE(\"{EMAIL}\", \"{PHONE_NUMBER}\", \"anonymous\")"
}
=DEFAULT_VALUE 輔助程式會挑選第一個非空白值,因此 CRM 會在有電子郵件或電話號碼時收到,而只有在兩者都沒有時,才會收到文字字串 "anonymous",這有助於標記未附加識別聯絡資訊的票證。
變化版本:僅限查詢的票證流程 (不建立記錄)
帳戶作業會正常執行,但無法建立票證。這項整合功能只會將留言附加至查詢到的「現有」票證。
執行個體設定變更
{
"skip_record_creation": true,
"case_lookup_url": "https://crm.example.com/api/cases/{RECORD_ID}"
}
變更包括下列行為:
記錄步驟會呼叫
case_find_endpoint,並使用傳回的票證。如果找不到票證,鏈結會在記錄步驟停止,不會叫用case_create_endpoint。只有在成功查詢票券時,系統才會調度工作階段後端點 (
case_comment_endpoint、case_update_endpoint等)。如果沒有任何ticket_id具體化,Rails 端的ready?防護機制會確保這些指令保持在佇列中 (並最終過期)。實際影響:在這種設定下,工作階段後端點只會接收與已知票證相關聯的工作階段。您不需要處理
"missing ticket_id"分支。
建議的冪等鍵實務做法
平台會將 SESSION_TYPE 和 SESSION_ID 都公開為範本變數。套用複合索引鍵模式最乾淨俐落的方法,是直接將其嵌入每個相關要求主體,這樣端點就會有標準索引鍵可供使用,您不必額外編寫邏輯:
"request_parameters": {
"...your fields...": "...",
"ccai_session_key": "{SESSION_TYPE}-{SESSION_ID}"
}
對於同一個呼叫,鏈結中每個端點 (帳戶 > 記錄 > 工作階段後) 的每次重試都會產生相同的 ccai_session_key。在客戶關係管理系統的建立或 upsert 邏輯中,將其做為簡化錨點,例如對 (ccai_session_key、endpoint_kind) 執行 upsert,即可安全地吸收重試,而不會產生重複記錄。
建構具韌性的端點 (冪等性和設計提示)
由於要求可能會重複 (立即重試 + 數天內重試),端點應具備冪等性:
使用穩定的複合互動 ID 做為冪等鍵:
將工作階段類型與工作階段 ID 結合,例如
call-12345或chat-12345。請勿單獨依賴
call_id或chat_id。語音和即時通訊 ID 可能會重疊,因為每個序列都可以從 1 開始。
如果收到疑似重複的要求:
請檢查酬載,判斷是否確實重複。部分共用端點 (例如留言或附註端點) 可供多種指令類型使用。
在正常情況下,建立作業不應出現重複要求,但如果 CRM 處理要求後傳回錯誤,或在平台收到成功回應前逾時,就可能發生這種情況。
確認建立要求重複時,傳回先前建立的記錄 ID,而非其他記錄。
明確處理缺少的 ID:
建立票證時缺少
contact_id,通常表示帳戶查詢或帳戶建立功能已停用。如果執行個體需要帳戶,請進行調查,不要在沒有聯絡人的情況下默默建立票證。在已設定票券查詢的一般 API 設定中,工作階段後呼叫不應缺少
ticket_id。請先檢查票證查詢設定和酬載範本,再將要求視為一般無作業。
如要更新,建議將欄位設為特定值,而非遞增計數器,這樣重複呼叫才安全。
疑難排解和觀測能力
偵錯自訂 CRM 整合時,請注意下列模式:
重複呼叫同一個端點:
請根據指令層級重試 (~7 天,14 次嘗試) 中的重試排程,比較時間戳記。
使用複合工作階段 ID (例如工作階段類型 + 通話或即時通訊工作階段 ID) 建立事件關聯。
CCAI Platform 匯出的記錄可顯示通話或即時通訊工作階段 ID,以及 API 事件,方便追蹤。
檢查端點是否持續傳回可重試的錯誤 (例如
500),而非無法重試的設定失敗。
「不會停止」的重試:
檢查端點傳回的錯誤回應。
如果您希望永久失敗,請與支援團隊聯絡,瞭解如何為設定指出不可重試的錯誤。
從未呼叫端點:
請確認:
上游步驟 (帳戶/記錄) 已成功完成,並產生必要的 ID。
端點已正確設定,並在自訂客戶關係管理設定中啟用。
如果端點設定錯誤或停用,或鏈結中較早的步驟失敗,可能會導致某些步驟無法執行。
關聯記錄:
在您端記錄完整的請求和回應,包括互動 ID (
call_id/chat_id)。使用該 ID 將 CRM 記錄與平台行為建立關聯 (特別是在重試期間)。