選擇應用程式使用的 API。每個 API 都有各自的身分驗證、工作階段建立與事件規範。
選擇電話通訊連線方式
電話通話可以透過 SIP 中繼線,或透過轉送音訊的應用程式連接至 GPT-Live。請根據現有電話系統,以及應用程式需要在哪個環節處理音訊,選擇合適的方式。
| 連線 | 音訊處理與應用程式職責 |
|---|---|
| SIP 直連 | 供應商與 OpenAI 交換通話音訊。應用程式則負責處理 webhook、工作階段組態、通話決策與業務邏輯。 |
| 伺服器音訊橋接 | 應用程式透過 WebSocket 將供應商或房間的音訊轉送至 GPT-Live,並負責管理兩端的連線、事件轉換、播放與通話生命週期。 |
供應商與應用程式之間的連線,以及應用程式與 OpenAI 之間的連線,彼此獨立。例如,來電者可以透過 SIP 加入房間,而房間內的智慧體則透過 WebSocket 連接至 GPT-Live。
使用 Twilio、Telnyx、LiveKit 或 Daily/Pipecat?請參閱 GPT-Live 合作夥伴整合,查看各供應商的專屬指南。
SIP 直連
SIP 直連讓通話音訊沿著供應商與 OpenAI 之間的媒體路徑傳輸。SIP 信令使用 TLS,而 GPT-Live 要求通話音訊使用 SRTP。後端仍負責來電決策、工作階段組態、授權與業務邏輯。
當後端需要接收工作階段事件或傳送指令時,請使用側頻連線。它會附接至現有對話,而音訊仍由 SIP 傳輸。請為每個動作指定一個處理常式,以免 webhook 重複送達,或多個連線觀察到同一事件時,導致工具重複執行。
請將 SIP 路由與供應商組態,和使用這些設定的整合一併管理。Realtime webhook 事件、通話識別碼與接受來電的酬載屬於 Realtime API;Live 工作階段應使用 GPT-Live 規範。
處理通話生命週期
使用此流程前,請確認專案已啟用 GPT-Live SIP 支援,且供應商的 SIP 中繼線已路由至該專案。另一個分頁中的 Realtime webhook 與接受來電酬載遵循的是不同的 API 規範。
接收來電
為專案的webhook 端點設定 live.transport.incoming 事件。做出通話決策前,請驗證 webhook 簽章,並排除重複送達的事件。確認收到 webhook 並不代表接受來電。
Webhook 透過 data.type: "sip" 識別 SIP 通話,並提供 data.session_id。所有 Live 通話動作都必須原樣使用該工作階段 ID。請將 data.sip_headers 視為不受信任的來電者中繼資料,不可作為授權依據。
現有整合可能仍會收到已棄用的 live.call.incoming 事件,此事件不含 data.type。遷移期間,請同時處理兩個事件名稱,並保留舊訂閱,直到舊版事件的傳送與重試全部完成。同一通待處理來電也可能觸發 Realtime webhook;請指定單一處理常式負責接受或拒絕來電的決策,不要透過兩個 API 同時接受來電。
接受或拒絕來電
套用應用程式的授權與路由規則。若要接受來電,請傳送已通過身分驗證的 POST /v1/live/sessions/{session_id}/accept 請求,並包含最上層 session 物件:
{
"session": {
"type": "live",
"model": "gpt-live-1",
"instructions": "You are answering an inbound support call.",
"audio": { "output": { "voice": "marin" } },
"delegation": { "type": "client" }
}
}請從受信任的後端使用 Authorization: Bearer $OPENAI_API_KEY 傳送通話控制請求。接受來電時,請選擇語音與委派模式。音訊格式由 SIP 協商,因此請省略 audio.format。此範例選用用戶端委派,因此後端必須處理受委派的工作。如需用戶端與 Responses 組態,請參閱委派與工具。
成功接受來電後,會在工作階段初始化完成時回傳 200 OK,回應本文為空。請先處理 HTTP 錯誤,再將來電視為已接受。
若要拒絕來電,請傳送 POST /v1/live/sessions/{session_id}/reject 並附上 SIP 狀態,例如以 { "status_code": 486 } 表示忙線。狀態必須是 300 至 699 之間的整數。最先做出的接受或拒絕決策會生效;之後競爭同一來電的決策會回傳 decision_already_made。
附接後端
接受來電後,請透過 wss://api.openai.com/v1/live/sessions/{session_id}/attach 建立側頻 WebSocket 連線。使用已接受來電的工作階段 ID,以及相同的專案身分驗證與連線標頭。請勿再次傳送 session.start。
SIP 負責傳輸通話音訊。側頻則用於逐字稿、委派、工具、指令與鏡射音訊。即使多個連線都觀察到同一事件,也請為每項副作用指定單一負責方。
觀察鍵盤事件
來電者按下按鍵時,側頻會收到 transport.dtmf.received;託管工具成功傳送按鍵音後,則會收到 transport.dtmf.send。事件的 event 欄位包含 0–9、*、# 或 A–D 其中一個值。
這些是提供給觀察端的通知,不是用戶端指令。請勿傳送 transport.dtmf.send 來要求傳送按鍵音,也不要假設瀏覽器資料通道會收到鍵盤事件。
轉接或結束通話
若要轉接通話,請傳送 POST /v1/live/sessions/{session_id}/refer,並以 { "target_uri": "sip:agent@example.com" } 指定目的地。若要掛斷通話,請傳送不含請求本文的 POST /v1/live/sessions/{session_id}/hangup。兩者成功時都會回傳 200 OK,回應本文為空。
釋放應用程式資源前,請保持側頻連線開啟,以接收最後的事件與用量資料。掛斷請求成功或連線意外中斷,都不能取代 session.closed。如需瞭解收尾處理與關閉原因,請參閱用量與正常關閉。
此流程用於接受來電。不支援透過 POST /v1/live/sessions 建立撥出的 SIP 通話;若要由供應商負責撥出通話,請使用相關的合作夥伴整合。
伺服器音訊橋接
當應用程式從電話服務供應商或智慧體框架接收音訊串流時,請使用 GPT-Live WebSocket 連線。應用程式負責兩端連線的身分驗證、轉換各自的事件封裝格式,並雙向轉送音訊。
GPT-Live 支援透過 WebSocket 傳輸 8 kHz 的原始 G.711 μ-law 與 A-law 音訊。當供應商串流使用相同的編解碼器、取樣率與聲道數時,應用程式可以直接轉送原始音訊位元組,無須轉換成 PCM。請維持音訊順序,並使用各連線要求的訊息格式。音訊格式相同並不代表兩種事件通訊協定可以互換。
橋接程式也負責管理其排入播放佇列的所有音訊。設計應用程式時,請納入供應商端的緩衝、插話中斷與結束通話的處理。如需瞭解 Live 工作階段生命週期,請參閱管理工作階段;如需瞭解發言輪替與播放控制的變更,請參閱遷移至 GPT-Live。
請將供應商的通話或房間識別碼與 OpenAI 工作階段 ID 一併保留,以便跨兩個系統追蹤同一段對話。
GPT-Live 後續步驟
- WebSockets:將伺服器音訊串流連接至 GPT-Live。
- Webhook 與伺服器端控制:從後端管理工作階段。
- 委派與工具:將語音連接至推理與工具後端。
- 管理工作階段:處理逐字稿、工作階段狀態與關閉流程。
SIP 是一種 用於透過網際網路撥打電話的通訊協定。搭配 SIP 與 Realtime API,即可將來電導向 API。
概覽
若要將電話號碼連接至 Realtime API,請使用 SIP 中繼服務供應商(例如 Twilio)。這類服務會將電話通話轉換成 IP 流量。向 SIP 中繼服務供應商購買電話號碼後,請按照下列指示操作。
首先,前往 platform.openai.com 的設定 > 專案 > Webhooks,為來電建立 webhook。
接著,使用已設定 webhook 的專案 ID,
將 SIP 中繼線指向 OpenAI SIP 端點,例如 sip:$PROJECT_ID@sip.api.openai.com;transport=tls。
若需要歐洲資料駐留,請改用 sip:$PROJECT_ID@sip-eu.api.openai.com;transport=tls。
若要尋找 $PROJECT_ID,請前往設定 > 專案 > 一般。該頁面會顯示專案 ID,
其前綴為 proj_。
當 OpenAI 收到與專案相關聯的 SIP 流量時,
就會觸發 webhook。觸發的事件為
realtime.call.incoming,
如下列範例所示:
POST https://my_website.com/webhook_endpoint
user-agent: OpenAI/1.0 (+https://platform.openai.com/docs/webhooks)
content-type: application/json
webhook-id: wh_685342e6c53c8190a1be43f081506c52 # unique id for idempotency
webhook-timestamp: 1750287078 # timestamp of delivery attempt
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4= # signature to verify authenticity from OpenAI
{
"object": "event",
"id": "evt_685343a1381c819085d44c354e1b330e",
"type": "realtime.call.incoming",
"created_at": 1750287018, // Unix timestamp
"data": {
"call_id": "some_unique_id",
"sip_headers": [
{ "name": "From", "value": "sip:+142555512112@sip.example.com" },
{ "name": "To", "value": "sip:+18005551212@sip.example.com" },
{ "name": "Call-ID", "value": "03782086-4ce9-44bf-8b0d-4e303d2cc590"}
]
}
}收到此 webhook 後,即可使用其中的 call_id 值來接受或拒絕來電。
接受來電時,需為 Realtime API 工作階段提供必要的組態
(指示、語音等)。
工作階段建立後,即可設定 WebSocket,並照常監控工作階段。以下說明用於
接受、拒絕、監控、轉接及掛斷通話的 API。
接受來電
使用接受來電端點,
核准來電並設定負責接聽的即時工作階段。
請傳送與
create client secret
請求相同的參數,也就是在將通話橋接至模型之前,
確保已設定即時模型、語音、工具或指示。
curl -X POST "https://api.openai.com/v1/realtime/calls/$CALL_ID/accept" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "realtime",
"model": "gpt-realtime-2.1",
"instructions": "You are Alex, a friendly concierge for Example Corp."
}'請求路徑必須包含來自
realtime.call.incoming
webhook 的 call_id,且每個請求都必須包含上方所示的 Authorization 標頭。
當 SIP 通話區段開始響鈴,且即時工作階段
正在建立時,端點就會回傳 200 OK。
拒絕來電
當您不想處理來電時(例如來自
不支援的國碼),可使用拒接通話端點
拒絕通話邀請。請提供 call_id 路徑參數,
並在 JSON 本文中選擇性地提供 SIP status_code(例如以 486 表示「忙線」),
以控制傳回電信業者的回應。
curl -X POST "https://api.openai.com/v1/realtime/calls/$CALL_ID/reject" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status_code": 486}'若未提供狀態碼,API 預設會使用 603 Decline。
請求成功時,會在 OpenAI 傳送 SIP 回應後
傳回 200 OK。
監控通話事件
接受通話後,請開啟連至同一工作階段的 WebSocket 連線,
以串流接收事件並發出即時指令。請注意,使用 call_id 參數連接至現有通話時,
不會使用 model 引數,因為模型已透過
accept 端點設定。
WebSocket 請求
GET wss://api.openai.com/v1/realtime?call_id={call_id}
查詢參數
| 參數 | 型別 | 說明 |
|---|---|---|
call_id | 字串 | 來自 realtime.call.incoming webhook 的識別碼。 |
標頭
Authorization: Bearer YOUR_API_KEY
此 WebSocket 的運作方式與其他 Realtime API 連線完全相同。傳送
response.create
及其他用戶端事件來控制通話,並監聽伺服器事件以
追蹤進度。詳情請參閱Webhook 與伺服器端控制
。
import WebSocket from "ws";
const callId = "rtc_u1_9c6574da8b8a41a18da9308f4ad974ce";
const ws = new WebSocket(`wss://api.openai.com/v1/realtime?call_id=${callId}`, {
headers: {
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
},
});
ws.on("open", () => {
ws.send(
JSON.stringify({
type: "response.create",
})
);
});轉接通話
使用
轉接通話端點轉接進行中的通話。請提供
call_id,以及要放入 SIP Refer-To 標頭的 target_uri
(例如 tel:+14155550123 或 sip:agent@example.com)。
curl -X POST "https://api.openai.com/v1/realtime/calls/$CALL_ID/refer" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"target_uri": "tel:+14155550123"}'REFER 轉送至您的 SIP 供應商後,OpenAI 便會傳回 200 OK。
後續通話流程由下游系統為來電者處理。
掛斷通話
當您的應用程式需要中斷來電者的連線時,請使用掛斷端點 結束工作階段。此端點可用於 終止 SIP 和 WebRTC 即時工作階段。
curl -X POST "https://api.openai.com/v1/realtime/calls/$CALL_ID/hangup" \
-H "Authorization: Bearer $OPENAI_API_KEY"API 開始拆除通話連線時,會回應 200 OK。
SIP 信令與媒體 IP 範圍
Realtime SIP 通話的信令與媒體使用不同的網路路徑。為確保正常運作, 請依照以下說明設定網路,允許信令與媒體流量通過。
SIP 信令
sip.api.openai.com 和 sip-eu.api.openai.com 是透過 GeoIP 路由的端點。您的網路必須允許
輸出 TCP/TLS 流量連至 DNS 傳回的位址,並使用連接埠 5061。
SRTP 媒體
API 會在協商的 SDP 中指定獨立的媒體 IP 位址與 UDP 連接埠。您的網路必須 允許透過 UDP 傳輸的 SRTP 雙向流量往返下列 CIDR 範圍:
13.79.45.80/2823.98.140.64/2840.67.149.176/2840.83.204.240/28
伺服器範例
以下是 realtime.call.incoming 處理常式的範例。它會接受通話,然後記錄
Realtime API 的所有事件。
若要使用 Ruby 範例,請設定 OPENAI_API_KEY 和 OPENAI_WEBHOOK_SECRET
環境變數,再使用下列指令安裝必要的相依套件:
gem install openai webrick async-websocket。
from flask import Flask, request, Response, jsonify, make_response
from openai import OpenAI, InvalidWebhookSignatureError
import asyncio
import json
import os
import requests
import time
import threading
import websockets
app = Flask(__name__)
client = OpenAI(webhook_secret=os.environ["OPENAI_WEBHOOK_SECRET"])
AUTH_HEADER = {"Authorization": "Bearer " + os.environ["OPENAI_API_KEY"]}
call_accept = {
"type": "realtime",
"instructions": "You are a support agent.",
"model": "gpt-realtime-2.1",
}
response_create = {
"type": "response.create",
"response": {
"instructions": ("Say to the user 'Thank you for calling, how can I help you'")
},
}
async def websocket_task(call_id):
try:
async with websockets.connect(
"wss://api.openai.com/v1/realtime?call_id=" + call_id,
additional_headers=AUTH_HEADER,
) as websocket:
await websocket.send(json.dumps(response_create))
while True:
response = await websocket.recv()
print(f"Received from WebSocket: {response}")
except Exception as e:
print(f"WebSocket error: {e}")
@app.route("/", methods=["POST"])
def webhook():
try:
event = client.webhooks.unwrap(request.data, request.headers)
if event.type == "realtime.call.incoming":
requests.post(
"https://api.openai.com/v1/realtime/calls/"
+ event.data.call_id
+ "/accept",
headers={**AUTH_HEADER, "Content-Type": "application/json"},
json=call_accept,
)
threading.Thread(
target=lambda: asyncio.run(websocket_task(event.data.call_id)),
daemon=True,
).start()
return Response(status=200)
except InvalidWebhookSignatureError as e:
print("Invalid signature", e)
return Response("Invalid signature", status=400)
if __name__ == "__main__":
app.run(port=8000)後續步驟
現在您已透過 SIP 建立連線,可以使用左側導覽列或點選下列頁面,開始建立即時應用程式。