Wähle die API, die deine Anwendung verwendet. Jede API hat eigene Vorgaben für Authentifizierung, Sitzungserstellung und Ereignisse.
Telefonieverbindung auswählen
Ein Telefonanruf kann GPT-Live über einen SIP-Trunk oder eine Anwendung erreichen, die Audio weiterleitet. Wähle den Weg, der zu deinem bestehenden Telefonsystem passt. Berücksichtige dabei, wo deine Anwendung Audio verarbeiten muss.
| Verbindung | Zuständigkeiten für Audio und Anwendungslogik |
|---|---|
| Direkte SIP-Verbindung | Der Anbieter tauscht das Anrufaudio mit OpenAI aus. Deine Anwendung kümmert sich um Webhooks, Sitzungskonfiguration, Entscheidungen über Anrufe und Geschäftslogik. |
| Serverseitige Audiobrücke | Deine Anwendung leitet Audio vom Anbieter oder aus einem Raum über WebSocket an GPT-Live weiter. Sie verwaltet beide Verbindungen, die Umwandlung der Ereignisse, die Wiedergabe und den Anruflebenszyklus. |
Die Verbindung eines Anbieters zu deiner Anwendung und die Verbindung deiner Anwendung zu OpenAI sind voneinander getrennt. Beispielsweise kann eine anrufende Person einem Raum über SIP beitreten, während sich ein Agent in diesem Raum über WebSocket mit GPT-Live verbindet.
Verwendest du Twilio, Telnyx, LiveKit oder Daily/Pipecat? Unter GPT-Live-Partnerintegrationen findest du anbieterspezifische Anleitungen.
Direkte SIP-Verbindung
Bei einer direkten SIP-Verbindung bleibt das Anrufaudio auf dem Medienpfad zwischen Anbieter und OpenAI. Die SIP-Signalisierung verwendet TLS, und GPT-Live setzt für das Anrufaudio SRTP voraus. Dein Backend ist weiterhin für die Entscheidung über eingehende Anrufe, die Sitzungskonfiguration, die Autorisierung und die Geschäftslogik zuständig.
Verwende eine Sideband-Verbindung, wenn dein Backend Sitzungsereignisse empfangen oder Befehle senden muss. Sie verbindet sich mit dem bestehenden Gespräch, während SIP das Audio überträgt. Weise jeder Aktion genau einen Handler zu, damit mehrfach zugestellte Webhooks oder auf mehreren Verbindungen beobachtete Ereignisse Werkzeuge nicht doppelt ausführen.
Verwalte SIP-Routing und Anbieterkonfiguration zusammen mit der Integration, die sie verwendet. Realtime-Webhook-Ereignisse, Anrufkennungen und Nutzdaten zur Anrufannahme gehören zur Realtime API. Verwende für eine Live-Sitzung die Vorgaben von GPT-Live.
Anruflebenszyklus verwalten
Vergewissere dich vor der Nutzung dieses Ablaufs, dass die SIP-Unterstützung von GPT-Live für dein Projekt aktiviert ist und der SIP-Trunk deines Anbieters an dieses Projekt weitergeleitet wird. Die Realtime-Webhook-Nutzdaten und die Nutzdaten zur Anrufannahme im anderen Tab folgen anderen API-Vorgaben.
Eingehenden Anruf empfangen
Konfiguriere den Webhook-Endpunkt deines Projekts für live.transport.incoming. Überprüfe die Webhook-Signatur und entferne doppelte Zustellungen, bevor du über den Anruf entscheidest. Eine Zustellungsbestätigung nimmt den Anruf nicht an.
Der Webhook kennzeichnet einen SIP-Anruf mit data.type: "sip" und liefert data.session_id. Verwende diese Sitzungs-ID unverändert für jede Live-Anrufaktion. Behandle data.sip_headers als nicht vertrauenswürdige Metadaten der anrufenden Person, nicht als Autorisierung.
Bestehende Integrationen können weiterhin das veraltete Ereignis live.call.incoming empfangen, das kein data.type enthält. Verarbeite während der Migration beide Ereignisnamen und behalte das alte Abonnement bei, bis alle ausstehenden Zustellungen und Wiederholungsversuche für das alte Ereignis abgeschlossen sind. Derselbe ausstehende Anruf kann auch einen Realtime-Webhook auslösen. Weise die Entscheidung über Annahme oder Ablehnung genau einem Handler zu, statt den Anruf über beide APIs anzunehmen.
Anruf annehmen oder ablehnen
Wende die Autorisierungs- und Routingregeln deiner Anwendung an. Um den Anruf anzunehmen, sende eine authentifizierte Anfrage an POST /v1/live/sessions/{session_id}/accept mit einem session-Objekt auf oberster Ebene:
{
"session": {
"type": "live",
"model": "gpt-live-1",
"instructions": "You are answering an inbound support call.",
"audio": { "output": { "voice": "marin" } },
"delegation": { "type": "client" }
}
}Verwende für Anfragen zur Anrufsteuerung aus deinem vertrauenswürdigen Backend Authorization: Bearer $OPENAI_API_KEY. Wähle bei der Annahme die Stimme und den Delegationsmodus aus. SIP handelt das Audioformat aus, lass daher audio.format weg. Das Beispiel wählt die Delegation an den Client. Dein Backend muss die delegierten Aufgaben bearbeiten. Konfigurationen für den Client und Responses findest du unter Delegation und Werkzeuge.
Bei erfolgreicher Annahme wird nach der Initialisierung der Sitzung 200 OK mit einem leeren Antworttext zurückgegeben. Behandle HTTP-Fehler, bevor du den Anruf als angenommen betrachtest.
Um den Anruf abzulehnen, sende eine Anfrage an POST /v1/live/sessions/{session_id}/reject mit einem SIP-Status, beispielsweise { "status_code": 486 } für „besetzt“. Der Status muss eine ganze Zahl von 300 bis einschließlich 699 sein. Die erste Entscheidung über Annahme oder Ablehnung gilt. Eine spätere konkurrierende Entscheidung gibt decision_already_made zurück.
Backend verbinden
Stelle nach der Annahme eine Sideband-WebSocket-Verbindung zu wss://api.openai.com/v1/live/sessions/{session_id}/attach her. Verwende die ID der angenommenen Sitzung sowie dieselbe Projektauthentifizierung und dieselben Verbindungsheader. Sende session.start nicht erneut.
SIP überträgt das Anrufaudio. Verwende die Sideband-Verbindung für Transkripte, Delegation, Werkzeuge, Befehle und gespiegeltes Audio. Lege für jeden Seiteneffekt genau eine zuständige Instanz fest, auch wenn mehrere Verbindungen ein Ereignis beobachten.
Tastenereignisse beobachten
Die Sideband-Verbindung empfängt transport.dtmf.received, wenn die anrufende Person eine Taste drückt, und transport.dtmf.send, nachdem ein gehostetes Werkzeug erfolgreich einen Ton gesendet hat. Das Feld event des Ereignisses enthält einen der folgenden Werte: 0–9, *, # oder A–D.
Dies sind Benachrichtigungen für Beobachter, keine Client-Befehle. Sende transport.dtmf.send nicht, um einen Ton anzufordern, und gehe nicht davon aus, dass der Datenkanal des Browsers Tastenereignisse empfängt.
Anruf weiterleiten oder beenden
Um den Anruf weiterzuleiten, sende eine Anfrage an POST /v1/live/sessions/{session_id}/refer mit { "target_uri": "sip:agent@example.com" } für dein Ziel. Um aufzulegen, sende eine Anfrage an POST /v1/live/sessions/{session_id}/hangup ohne Anfragetext. Beide geben bei Erfolg 200 OK mit einem leeren Antworttext zurück.
Halte deine Sideband-Verbindung für abschließende Ereignisse und Nutzungsdaten offen, bevor du Anwendungsressourcen freigibst. Eine erfolgreiche Anfrage zum Auflegen oder ein unerwarteter Verbindungsabbruch ersetzt session.closed nicht. Informationen zum Abschluss und zu den Gründen für das Schließen findest du unter Nutzung und geordnetes Schließen.
Dieser Ablauf nimmt eingehende Anrufe an. Das Erstellen eines ausgehenden SIP-Anrufs über POST /v1/live/sessions wird nicht unterstützt. Verwende für ausgehende Anrufe, die der Anbieter steuert, die entsprechende Partnerintegration.
Serverseitige Audiobrücken
Verwende die WebSocket-Verbindung zu GPT-Live, wenn deine Anwendung einen Audiostream von einem Telefonieanbieter oder einem Agenten-Framework empfängt. Die Anwendung authentifiziert beide Verbindungen, wandelt die Hüllstrukturen ihrer Ereignisse um und leitet Audio in beide Richtungen weiter.
GPT-Live unterstützt rohe G.711-μ-law- und A-law-Audiodaten mit 8 kHz über WebSocket. Wenn der Stream des Anbieters denselben Codec, dieselbe Abtastrate und dieselbe Kanalanzahl verwendet, kann deine Anwendung die rohen Audiobytes weiterleiten, ohne sie in PCM umzuwandeln. Behalte die Reihenfolge der Audiodaten bei und verwende das von der jeweiligen Verbindung geforderte Nachrichtenformat. Übereinstimmende Audioformate machen die beiden Ereignisprotokolle nicht austauschbar.
Die Audiobrücke ist auch für alle Audiodaten verantwortlich, die sie zur Wiedergabe in eine Warteschlange stellt. Berücksichtige beim Entwurf deiner Anwendung die Pufferung durch den Anbieter, Unterbrechungen und das Beenden des Anrufs. Informationen zum Lebenszyklus einer Live-Sitzung findest du unter Sitzungen verwalten. Änderungen am Sprecherwechsel und an der Wiedergabesteuerung werden unter Zu GPT-Live migrieren beschrieben.
Speichere die Anruf- oder Raumkennung des Anbieters zusammen mit der OpenAI-Sitzungs-ID, damit du ein Gespräch über beide Systeme hinweg nachverfolgen kannst.
Nächste Schritte mit GPT-Live
- WebSockets: Verbinde einen serverseitigen Audiostream mit GPT-Live.
- Webhooks und serverseitige Steuerung: Verwalte eine Sitzung über dein Backend.
- Delegation und Werkzeuge: Verbinde Sprache mit deinem Backend für Reasoning und Werkzeuge.
- Sitzungen verwalten: Verarbeite Transkripte und den Sitzungsstatus und kümmere dich um das Schließen der Sitzung.
SIP ist ein Protokoll für Telefonanrufe über das Internet. Mit SIP und der Realtime API kannst du eingehende Telefonanrufe an die API weiterleiten.
Übersicht
Wenn du eine Telefonnummer mit der Realtime API verbinden möchtest, verwende einen SIP-Trunking-Anbieter (z. B. Twilio). Dieser Dienst wandelt deinen Telefonanruf in IP-Datenverkehr um. Nachdem du eine Telefonnummer bei deinem SIP-Trunking-Anbieter gekauft hast, folge der Anleitung unten.
Erstelle zunächst auf platform.openai.com unter Einstellungen > Projekt > Webhooks einen Webhook für eingehende Anrufe.
Richte anschließend deinen SIP-Trunk auf den OpenAI-SIP-Endpunkt aus. Verwende dabei die Projekt-ID
des Projekts, für das du den Webhook konfiguriert hast, z. B. sip:$PROJECT_ID@sip.api.openai.com;transport=tls.
Für europäische Datenresidenz verwende stattdessen sip:$PROJECT_ID@sip-eu.api.openai.com;transport=tls.
Deine $PROJECT_ID findest du unter Einstellungen > Projekt > Allgemein. Dort wird die Projekt-ID angezeigt,
die mit dem Präfix proj_ beginnt.
Wenn OpenAI SIP-Datenverkehr empfängt, der deinem Projekt zugeordnet ist,
wird dein Webhook ausgelöst. Dabei wird ein Ereignis vom Typ
realtime.call.incoming gesendet,
wie im folgenden Beispiel:
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"}
]
}
}Auf Grundlage dieses Webhooks kannst du den Anruf mit dem darin enthaltenen Wert call_id annehmen oder ablehnen.
Bei der Annahme gibst du die erforderliche Konfiguration
(Anweisungen, Stimme usw.) für die Realtime-API-Sitzung an.
Sobald die Sitzung hergestellt ist, kannst du eine WebSocket-Verbindung einrichten und die Sitzung wie gewohnt überwachen. Die APIs zum
Annehmen, Ablehnen, Überwachen, Weiterleiten und Beenden des Anrufs sind unten dokumentiert.
Anruf annehmen
Verwende den Endpunkt zum Annehmen von Anrufen, um
den eingehenden Anruf zu genehmigen und die Echtzeitsitzung zu konfigurieren, die ihn entgegennimmt.
Sende dieselben Parameter wie bei einer Anfrage an
create client secret.
Stelle also sicher, dass Echtzeitmodell, Stimme, Werkzeuge oder Anweisungen festgelegt sind, bevor du
den Anruf mit dem Modell verbindest.
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."
}'Der Anfragepfad muss die call_id aus dem Webhook
realtime.call.incoming
enthalten. Jede Anfrage benötigt außerdem den oben gezeigten Authorization-Header. Der
Endpunkt gibt 200 OK zurück, sobald der SIP-Verbindungsabschnitt klingelt und die Echtzeitsitzung
aufgebaut wird.
Anruf ablehnen
Verwende den Endpunkt zum Ablehnen von Anrufen, um
eine Einladung abzulehnen, wenn du den eingehenden Anruf nicht bearbeiten möchtest (z. B. bei
einer nicht unterstützten Landesvorwahl). Gib den Pfadparameter call_id
und optional einen SIP-Statuscode status_code (z. B. 486 für „besetzt“) im JSON-Body an,
um die Antwort an den Telefonieanbieter festzulegen.
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}'Wenn kein Statuscode angegeben wird, verwendet die API standardmäßig 603 Decline.
Bei einer erfolgreichen Anfrage lautet die Antwort 200 OK, nachdem OpenAI
die SIP-Antwort übermittelt hat.
Anrufereignisse überwachen
Nachdem du einen Anruf angenommen hast, öffne eine WebSocket-Verbindung zur selben Sitzung, um
Ereignisse zu streamen und Echtzeitbefehle zu senden. Beachte: Wenn du dich über den Parameter call_id
mit einem bestehenden Anruf verbindest, wird das Argument model nicht verwendet, da das Modell bereits
über den Endpunkt accept konfiguriert wurde.
WebSocket-Anfrage
GET wss://api.openai.com/v1/realtime?call_id={call_id}
Abfrageparameter
| Parameter | Typ | Beschreibung |
|---|---|---|
call_id | string | Kennung aus dem Webhook realtime.call.incoming. |
Header
Authorization: Bearer YOUR_API_KEY
Die WebSocket-Verbindung verhält sich genauso wie jede andere Verbindung zur Realtime API. Sende
response.create
und andere Client-Ereignisse, um den Anruf zu steuern, und empfange Server-Ereignisse, um
den Verlauf zu verfolgen. Weitere Informationen findest du unter
Webhooks und serverseitige Steuerung.
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",
})
);
});Anruf weiterleiten
Leite einen aktiven Anruf über den
Endpunkt zum Weiterleiten von Anrufen weiter. Gib
call_id sowie target_uri an. Letzterer Wert wird in den SIP-Header Refer-To
eingetragen (zum Beispiel tel:+14155550123 oder 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"}'OpenAI gibt 200 OK zurück, sobald die REFER-Anfrage an deinen SIP-Anbieter weitergeleitet wurde.
Das nachgelagerte System übernimmt den weiteren Anrufablauf für die anrufende Person.
Anruf beenden
Beende die Sitzung mit dem Endpunkt zum Auflegen, wenn deine Anwendung die Verbindung zur anrufenden Person trennen soll. Mit diesem Endpunkt kannst du Echtzeitsitzungen sowohl über SIP als auch über WebRTC beenden.
curl -X POST "https://api.openai.com/v1/realtime/calls/$CALL_ID/hangup" \
-H "Authorization: Bearer $OPENAI_API_KEY"Die API antwortet mit 200 OK, sobald sie beginnt, die Anrufverbindung abzubauen.
IP-Bereiche für SIP-Signalisierung und Medien
SIP-Anrufe über die Realtime API nutzen getrennte Netzwerkpfade für Signalisierung und Medien. Damit sie ordnungsgemäß funktionieren, konfiguriere dein Netzwerk so, dass es den Signalisierungs- und Medienverkehr wie unten beschrieben zulässt.
SIP-Signalisierung
sip.api.openai.com und sip-eu.api.openai.com sind Endpunkte mit GeoIP-Routing. Dein Netzwerk muss
ausgehenden TCP/TLS-Verkehr zu den per DNS zurückgegebenen Adressen auf Port 5061 zulassen.
SRTP-Medien
Die API gibt im ausgehandelten SDP eine separate IP-Adresse für Medien und einen UDP-Port an. Dein Netzwerk muss SRTP-Verkehr über UDP in beide Richtungen zu und von den folgenden CIDR-Bereichen zulassen:
13.79.45.80/2823.98.140.64/2840.67.149.176/2840.83.204.240/28
Serverbeispiele
Das folgende Beispiel zeigt einen Handler für realtime.call.incoming. Er nimmt den Anruf an und protokolliert anschließend
alle Ereignisse der Realtime API.
Lege für das Ruby-Beispiel die Umgebungsvariablen OPENAI_API_KEY und OPENAI_WEBHOOK_SECRET fest.
Installiere anschließend die erforderlichen Abhängigkeiten mit
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)Nächste Schritte
Nachdem du die Verbindung über SIP hergestellt hast, nutze die Navigation links oder öffne die folgenden Seiten, um mit der Entwicklung deiner Echtzeitanwendung zu beginnen.
- Leitfaden für Echtzeit-Prompts
- Unterhaltungen verwalten
- Webhooks und serverseitige Steuerung
- Kosten verwalten
- Echtzeittranskription