Choisissez l’API utilisée par votre application. Chaque API possède ses propres mécanismes d’authentification et de création de sessions, ainsi que son propre contrat d’événements.
Choisissez une connexion téléphonique
Un appel téléphonique peut atteindre GPT-Live via un trunk SIP ou une application qui relaie l’audio. Choisissez le mode de connexion adapté à votre système téléphonique existant et à l’endroit où votre application doit traiter l’audio.
| Connexion | Audio et responsabilités de l’application |
|---|---|
| SIP direct | Le fournisseur échange l’audio de l’appel avec OpenAI. Votre application gère les webhooks, la configuration des sessions, les décisions concernant les appels et la logique métier. |
| Pont audio côté serveur | Votre application relaie l’audio du fournisseur ou du salon vers GPT-Live via WebSocket. Elle gère les deux connexions, la conversion des événements, la lecture audio et le cycle de vie de l’appel. |
La connexion du fournisseur à votre application et celle de votre application à OpenAI sont distinctes. Par exemple, un appelant peut rejoindre un salon via SIP tandis qu’un agent présent dans ce salon se connecte à GPT-Live via WebSocket.
Vous utilisez Twilio, Telnyx, LiveKit ou Daily/Pipecat ? Consultez les intégrations partenaires de GPT-Live pour accéder aux guides propres à chaque fournisseur.
SIP direct
Avec SIP direct, l’audio de l’appel reste sur le chemin média reliant le fournisseur à OpenAI. La signalisation SIP utilise TLS, et GPT-Live exige SRTP pour l’audio des appels. Votre backend reste responsable de la décision concernant l’appel entrant, de la configuration de la session, de l’autorisation et de la logique métier.
Utilisez une connexion auxiliaire lorsque votre backend doit recevoir des événements de session ou envoyer des commandes. Elle se rattache à la conversation existante pendant que SIP transporte l’audio. Attribuez un seul gestionnaire à chaque action afin que les livraisons de webhooks en double ou les événements observés sur plusieurs connexions ne déclenchent pas deux fois l’exécution des outils.
Conservez le routage SIP et la configuration du fournisseur avec l’intégration qui les utilise. Les événements webhook, les identifiants d’appel et les charges utiles d’acceptation de Realtime relèvent de la Realtime API ; utilisez le contrat GPT-Live pour une session Live.
Gérez le cycle de vie de l’appel
Vérifiez que la prise en charge de SIP dans GPT-Live est activée pour votre projet et que le trunk SIP de votre fournisseur est routé vers ce projet avant d’utiliser cette procédure. Les charges utiles des webhooks et d’acceptation de Realtime présentées dans l’autre onglet relèvent d’un autre contrat d’API.
Recevez l’appel entrant
Configurez le point de terminaison webhook de votre projet pour live.transport.incoming. Vérifiez la signature du webhook et dédupliquez les livraisons avant de prendre une décision concernant l’appel. Un accusé de réception du webhook ne vaut pas acceptation de l’appel.
Le webhook identifie un appel SIP par data.type: "sip" et fournit data.session_id. Utilisez cet identifiant de session sans le modifier pour chaque action sur l’appel Live. Traitez data.sip_headers comme des métadonnées non fiables provenant de l’appelant, et non comme une autorisation.
Les intégrations existantes peuvent encore recevoir l’événement obsolète live.call.incoming, qui ne comporte pas de champ data.type. Pendant la migration, gérez les deux noms et conservez l’ancien abonnement jusqu’à ce que toutes les livraisons et tentatives de renvoi de l’ancien événement soient terminées. Un même appel en attente peut aussi émettre un webhook Realtime ; confiez la décision d’accepter ou de rejeter l’appel à un seul gestionnaire plutôt que de l’accepter via les deux API.
Acceptez ou rejetez l’appel
Appliquez les règles d’autorisation et de routage de votre application. Pour accepter l’appel, envoyez une requête POST /v1/live/sessions/{session_id}/accept authentifiée avec un objet session à la racine :
{
"session": {
"type": "live",
"model": "gpt-live-1",
"instructions": "You are answering an inbound support call.",
"audio": { "output": { "voice": "marin" } },
"delegation": { "type": "client" }
}
}Utilisez Authorization: Bearer $OPENAI_API_KEY depuis votre backend de confiance pour les requêtes de contrôle des appels. Choisissez la voix et le mode de délégation au moment de l’acceptation. SIP négocie le format audio : omettez donc audio.format. L’exemple sélectionne la délégation au client ; votre backend doit prendre en charge le travail délégué. Consultez Délégation et outils pour les configurations client et Responses.
Une acceptation réussie renvoie 200 OK avec un corps vide après l’initialisation de la session. Gérez les erreurs HTTP avant de considérer l’appel comme accepté.
Pour rejeter l’appel, envoyez POST /v1/live/sessions/{session_id}/reject avec un code d’état SIP, par exemple { "status_code": 486 } pour indiquer que la ligne est occupée. Ce code doit être un entier compris entre 300 et 699 inclus. La première décision d’acceptation ou de rejet est retenue ; toute décision concurrente ultérieure renvoie decision_already_made.
Rattachez votre backend
Après l’acceptation, ouvrez une connexion WebSocket auxiliaire à l’adresse wss://api.openai.com/v1/live/sessions/{session_id}/attach. Utilisez l’identifiant de la session acceptée, ainsi que les mêmes informations d’authentification du projet et les mêmes en-têtes de connexion. N’envoyez pas de nouveau session.start.
SIP transporte l’audio de l’appel. Utilisez la connexion auxiliaire pour les transcriptions, la délégation, les outils, les commandes et l’audio retransmis. Désignez un seul responsable pour chaque effet de bord, même si plusieurs connexions observent un événement.
Observez les événements du clavier téléphonique
La connexion auxiliaire reçoit transport.dtmf.received lorsque l’appelant appuie sur une touche et transport.dtmf.send après qu’un outil hébergé a envoyé une tonalité avec succès. Le champ event de l’événement contient une valeur parmi 0–9, *, # ou A–D.
Il s’agit de notifications d’observation, et non de commandes client. N’envoyez pas transport.dtmf.send pour demander une tonalité et ne supposez pas que le canal de données du navigateur reçoit les événements du clavier téléphonique.
Transférez l’appel ou mettez-y fin
Pour transférer l’appel, envoyez POST /v1/live/sessions/{session_id}/refer avec { "target_uri": "sip:agent@example.com" } pour indiquer la destination. Pour raccrocher, envoyez POST /v1/live/sessions/{session_id}/hangup sans corps de requête. Les deux opérations renvoient 200 OK avec un corps vide en cas de réussite.
Gardez votre connexion auxiliaire ouverte pour recevoir les derniers événements et les données d’utilisation avant de libérer les ressources de l’application. Une requête de raccrochage réussie ou une déconnexion inattendue ne remplace pas session.closed. Consultez Utilisation et fermeture en douceur pour en savoir plus sur la finalisation et les motifs de fermeture.
Cette procédure permet d’accepter les appels entrants. La création d’un appel SIP sortant via POST /v1/live/sessions n’est pas prise en charge ; utilisez l’intégration partenaire appropriée pour les appels sortants gérés par le fournisseur.
Ponts audio côté serveur
Utilisez la connexion WebSocket de GPT-Live lorsque votre application reçoit un flux audio d’un fournisseur de téléphonie ou d’un framework d’agents. L’application authentifie les deux connexions, convertit leurs enveloppes d’événements et relaie l’audio dans les deux sens.
GPT-Live prend en charge l’audio brut G.711 μ-law et A-law à 8 kHz via WebSocket. Lorsque le flux du fournisseur utilise le même codec, la même fréquence d’échantillonnage et le même nombre de canaux, votre application peut transmettre les octets audio bruts sans les convertir en PCM. Préservez l’ordre des données audio et utilisez le format de message requis par chaque connexion. Des formats audio identiques ne rendent pas les deux protocoles d’événements interchangeables.
Le pont est également responsable de l’audio qu’il met en file d’attente pour la lecture. Tenez compte de la mise en mémoire tampon chez le fournisseur, des interruptions et de la fin de l’appel dans la conception de votre application. Consultez Gestion des sessions pour le cycle de vie des sessions Live et Migrez vers GPT-Live pour les changements concernant les tours de parole et le contrôle de la lecture.
Conservez l’identifiant d’appel ou de salon du fournisseur avec l’identifiant de session OpenAI afin de pouvoir suivre une conversation dans les deux systèmes.
Prochaines étapes avec GPT-Live
- WebSockets : connectez un flux audio côté serveur à GPT-Live.
- Webhooks et contrôles côté serveur : gérez une session depuis votre backend.
- Délégation et outils : reliez la parole à votre backend de raisonnement et d’outils.
- Gestion des sessions : gérez les transcriptions, l’état des sessions et leur fermeture.
SIP est un protocole permettant de passer des appels téléphoniques sur Internet. Avec SIP et la Realtime API, vous pouvez diriger les appels téléphoniques entrants vers l’API.
Vue d’ensemble
Pour connecter un numéro de téléphone à la Realtime API, utilisez un fournisseur de trunks SIP (par exemple, Twilio). Ce service convertit votre appel téléphonique en trafic IP. Après avoir acheté un numéro de téléphone auprès de votre fournisseur de trunks SIP, suivez les instructions ci-dessous.
Commencez par créer un webhook pour les appels entrants dans Paramètres > Projet > Webhooks sur platform.openai.com.
Ensuite, faites pointer votre trunk SIP vers le point de terminaison SIP d’OpenAI en utilisant l’identifiant du projet
pour lequel vous avez configuré le webhook, par exemple sip:$PROJECT_ID@sip.api.openai.com;transport=tls.
Pour la résidence des données en Europe, utilisez plutôt sip:$PROJECT_ID@sip-eu.api.openai.com;transport=tls.
Pour trouver votre $PROJECT_ID, accédez à Paramètres > Projet > Général. Cette page affiche l’identifiant du projet, qui
commence par le préfixe proj_.
Lorsqu’OpenAI reçoit du trafic SIP associé à votre projet,
votre webhook est déclenché. L’événement émis est de type
realtime.call.incoming,
comme dans l’exemple ci-dessous :
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"}
]
}
}À partir de ce webhook, vous pouvez accepter ou rejeter l’appel en utilisant la valeur call_id qu’il contient.
Lors de l’acceptation de l’appel, vous fournissez la configuration nécessaire
(instructions, voix, etc.) à la session Realtime API.
Une fois la session établie, vous pouvez ouvrir une connexion WebSocket et surveiller la session comme d’habitude. Les API permettant
d’accepter, de rejeter, de surveiller, de transférer l’appel et de raccrocher sont décrites ci-dessous.
Acceptez l’appel
Utilisez le point de terminaison d’acceptation des appels pour
approuver l’appel entrant et configurer la session temps réel qui y répondra.
Envoyez les mêmes paramètres que pour une requête
create client secret
: assurez-vous que le modèle temps réel, la voix, les outils ou les instructions sont configurés avant de relier
l’appel au modèle.
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."
}'Le chemin de la requête doit inclure la valeur call_id du webhook
realtime.call.incoming,
et chaque requête doit comporter l’en-tête Authorization présenté ci-dessus. Le
point de terminaison renvoie 200 OK dès que la branche SIP est en phase de sonnerie et que la session temps réel
est en cours d’établissement.
Rejetez l’appel
Utilisez le point de terminaison de rejet d’appel pour
refuser une invitation lorsque vous ne souhaitez pas traiter l’appel entrant (par exemple, s’il provient
d’un indicatif de pays non pris en charge). Fournissez le paramètre de chemin call_id
et, éventuellement, un code SIP status_code (par exemple, 486 pour indiquer « occupé ») dans le corps JSON
afin de définir la réponse renvoyée à l’opérateur.
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}'Si aucun code d’état n’est fourni, l’API utilise 603 Decline par défaut.
Une requête réussie renvoie 200 OK après qu’OpenAI a transmis la réponse
SIP.
Suivez les événements de l’appel
Après avoir accepté un appel, ouvrez une connexion WebSocket à la même session pour
recevoir les événements en continu et envoyer des commandes en temps réel. Lorsque vous vous connectez à un appel existant
à l’aide du paramètre call_id, l’argument model n’est pas utilisé, car le modèle a déjà été configuré
via le point de terminaison accept.
Requête WebSocket
GET wss://api.openai.com/v1/realtime?call_id={call_id}
Paramètres de requête
| Paramètre | Type | Description |
|---|---|---|
call_id | string | Identifiant fourni par le webhook realtime.call.incoming. |
En-têtes
Authorization: Bearer YOUR_API_KEY
La connexion WebSocket fonctionne exactement comme toute autre connexion à la Realtime API. Envoyez
response.create
et d’autres événements client pour contrôler l’appel, et écoutez les événements serveur pour
suivre sa progression. Consultez Webhooks et contrôles côté serveur
pour en savoir plus.
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",
})
);
});Redirigez l’appel
Transférez un appel en cours à l’aide du
point de terminaison de transfert d’appel. Fournissez
call_id ainsi que la valeur target_uri à placer dans l’en-tête SIP Refer-To
(par exemple, tel:+14155550123 ou 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 renvoie 200 OK une fois la requête REFER transmise à votre fournisseur SIP.
Le système en aval prend en charge la suite de l’appel pour l’appelant.
Raccrochez
Mettez fin à la session à l’aide du point de terminaison de raccrochage lorsque votre application doit déconnecter l’appelant. Ce point de terminaison permet de mettre fin aux sessions en temps réel aussi bien SIP que WebRTC.
curl -X POST "https://api.openai.com/v1/realtime/calls/$CALL_ID/hangup" \
-H "Authorization: Bearer $OPENAI_API_KEY"L’API renvoie 200 OK lorsqu’elle commence à mettre fin à l’appel.
Plages d’adresses IP pour la signalisation SIP et les médias
Les appels SIP Realtime utilisent des chemins réseau distincts pour la signalisation et les médias. Pour garantir leur bon fonctionnement, configurez votre réseau afin d’autoriser le trafic de signalisation et de médias comme indiqué ci-dessous.
Signalisation SIP
sip.api.openai.com et sip-eu.api.openai.com sont des points de terminaison dont le routage repose sur GeoIP. Votre réseau doit autoriser
le trafic TCP/TLS sortant vers les adresses renvoyées par le DNS sur le port 5061.
Médias SRTP
L’API spécifie une adresse IP et un port UDP distincts pour les médias dans le SDP négocié. Votre réseau doit autoriser le trafic SRTP bidirectionnel sur UDP à destination et en provenance des plages CIDR suivantes :
13.79.45.80/2823.98.140.64/2840.67.149.176/2840.83.204.240/28
Exemples côté serveur
Voici un exemple de gestionnaire pour realtime.call.incoming. Il accepte l’appel, puis consigne tous les événements de
la Realtime API.
Pour l’exemple Ruby, définissez les variables d’environnement OPENAI_API_KEY et OPENAI_WEBHOOK_SECRET,
puis installez les dépendances requises avec
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)Étapes suivantes
Maintenant que vous avez établi une connexion SIP, utilisez le menu de navigation à gauche ou consultez les pages suivantes pour commencer à développer votre application en temps réel.
- Guide de conception de prompts pour Realtime
- Gestion des conversations
- Webhooks et contrôles côté serveur
- Gestion des coûts
- Transcription en temps réel