Elige la API que usa tu aplicación. Cada API tiene sus propios mecanismos de autenticación y creación de sesiones, y su propio contrato de eventos.
Elige una conexión de telefonía
Una llamada telefónica puede llegar a GPT-Live a través de una troncal SIP o de una aplicación que retransmite audio. Elige la opción que se adapte a tu sistema telefónico actual y al lugar donde tu aplicación necesite procesar el audio.
| Conexión | Audio y responsabilidades de la aplicación |
|---|---|
| SIP directo | El proveedor intercambia el audio de la llamada con OpenAI. Tu aplicación se encarga de los webhooks, la configuración de la sesión, las decisiones sobre la llamada y la lógica de negocio. |
| Puente de audio del servidor | Tu aplicación retransmite el audio del proveedor o de la sala a GPT-Live a través de WebSocket. Administra ambas conexiones, la traducción de eventos, la reproducción y el ciclo de vida de la llamada. |
La conexión del proveedor con tu aplicación y la conexión de tu aplicación con OpenAI son independientes. Por ejemplo, una persona que llama puede unirse a una sala a través de SIP mientras un agente de esa sala se conecta a GPT-Live mediante WebSocket.
¿Usas Twilio, Telnyx, LiveKit o Daily/Pipecat? Consulta Integraciones con socios de GPT-Live para ver las guías específicas de cada proveedor.
SIP directo
SIP directo mantiene el audio de la llamada en la ruta de medios entre el proveedor y OpenAI. La señalización SIP usa TLS, y GPT-Live requiere SRTP para el audio de la llamada. Tu backend sigue siendo responsable de la decisión sobre la llamada entrante, la configuración de la sesión, la autorización y la lógica de negocio.
Usa una conexión de banda lateral cuando tu backend necesite recibir eventos de la sesión o enviar comandos. Esta se conecta a la conversación existente mientras SIP transporta el audio. Asigna un controlador a cada acción para que las entregas duplicadas de webhooks o los eventos observados en varias conexiones no ejecuten las herramientas dos veces.
Mantén el enrutamiento SIP y la configuración del proveedor junto con la integración que los usa. Los eventos de webhook, los identificadores de llamada y las cargas útiles de aceptación de Realtime pertenecen a la Realtime API; usa el contrato de GPT-Live para una sesión de Live.
Gestiona el ciclo de vida de la llamada
Antes de usar este flujo, confirma que la compatibilidad con SIP de GPT-Live esté habilitada para tu proyecto y que la troncal SIP de tu proveedor esté enrutada a ese proyecto. Las cargas útiles de webhook y de aceptación de Realtime que aparecen en la otra pestaña corresponden a un contrato de API diferente.
Recibe la llamada entrante
Configura el punto de acceso de webhook de tu proyecto para live.transport.incoming. Verifica la firma del webhook y elimina las entregas duplicadas antes de tomar una decisión sobre la llamada. Confirmar la recepción de una entrega no implica aceptar la llamada.
El webhook identifica una llamada SIP con data.type: "sip" y proporciona data.session_id. Usa ese ID de sesión sin modificarlo en cada acción de llamada de Live. Trata data.sip_headers como metadatos no confiables de quien llama, no como autorización.
Es posible que las integraciones existentes aún reciban el evento obsoleto live.call.incoming, que no tiene data.type. Durante la migración, maneja ambos nombres y conserva la suscripción anterior hasta que se hayan procesado todas las entregas y los reintentos del sistema anterior. La misma llamada pendiente también puede emitir un webhook de Realtime; asigna un solo controlador a la decisión de aceptar o rechazar, en lugar de aceptar a través de ambas API.
Acepta o rechaza la llamada
Aplica las reglas de autorización y enrutamiento de tu aplicación. Para aceptar la llamada, envía una solicitud POST /v1/live/sessions/{session_id}/accept autenticada con un objeto session de nivel superior:
{
"session": {
"type": "live",
"model": "gpt-live-1",
"instructions": "You are answering an inbound support call.",
"audio": { "output": { "voice": "marin" } },
"delegation": { "type": "client" }
}
}Usa Authorization: Bearer $OPENAI_API_KEY desde tu backend de confianza para las solicitudes de control de llamadas. Elige la voz y el modo de delegación al aceptar la llamada. SIP negocia el formato de audio, así que omite audio.format. El ejemplo selecciona la delegación al cliente; tu backend debe encargarse del trabajo delegado. Consulta Delegación y herramientas para ver las configuraciones de cliente y Responses.
Si la aceptación se completa correctamente, se devuelve 200 OK con un cuerpo vacío después de inicializar la sesión. Maneja los errores HTTP antes de considerar que la llamada se ha aceptado.
Para rechazar la llamada, envía POST /v1/live/sessions/{session_id}/reject con un código de estado SIP, como { "status_code": 486 } para indicar que está ocupado. El estado debe ser un número entero entre 300 y 699, inclusive. Prevalece la primera decisión de aceptar o rechazar; cualquier decisión posterior que compita con ella devuelve decision_already_made.
Conecta tu backend
Después de aceptar la llamada, conecta un WebSocket de banda lateral en wss://api.openai.com/v1/live/sessions/{session_id}/attach. Usa el ID de la sesión aceptada y la misma autenticación del proyecto y los mismos encabezados de conexión. No vuelvas a enviar session.start.
SIP transporta el audio de la llamada. Usa la conexión de banda lateral para las transcripciones, la delegación, las herramientas, los comandos y el audio reflejado. Elige un único responsable de cada efecto secundario, incluso si varias conexiones observan un evento.
Observa los eventos del teclado telefónico
La conexión de banda lateral recibe transport.dtmf.received cuando quien llama presiona una tecla y transport.dtmf.send después de que una herramienta alojada envía un tono correctamente. El campo event del evento contiene uno de los siguientes valores: 0–9, *, # o A–D.
Estas son notificaciones para observadores, no comandos del cliente. No envíes transport.dtmf.send para solicitar un tono ni supongas que el canal de datos del navegador recibe eventos del teclado telefónico.
Transfiere o finaliza la llamada
Para transferir la llamada, envía POST /v1/live/sessions/{session_id}/refer con { "target_uri": "sip:agent@example.com" } para indicar el destino. Para colgar, envía POST /v1/live/sessions/{session_id}/hangup sin cuerpo de solicitud. Ambas operaciones devuelven 200 OK con un cuerpo vacío si se completan correctamente.
Mantén abierta la conexión de banda lateral para recibir los eventos finales y los datos de uso antes de liberar los recursos de la aplicación. Una solicitud de colgar completada correctamente o una desconexión inesperada no sustituyen a session.closed. Consulta Uso y cierre ordenado para obtener información sobre la finalización y los motivos de cierre.
Este flujo acepta llamadas entrantes. No se admite la creación de llamadas SIP salientes mediante POST /v1/live/sessions; usa la integración con socios correspondiente para las llamadas salientes gestionadas por el proveedor.
Puentes de audio del servidor
Usa la conexión WebSocket de GPT-Live cuando tu aplicación reciba un flujo de audio de un proveedor de telefonía o de un framework de agentes. La aplicación autentica ambas conexiones, traduce sus envoltorios de eventos y retransmite el audio en ambas direcciones.
GPT-Live admite audio sin procesar G.711 μ-law y A-law a 8 kHz a través de WebSocket. Cuando el flujo del proveedor usa el mismo códec, frecuencia de muestreo y número de canales, tu aplicación puede reenviar los bytes de audio sin procesar sin convertirlos a PCM. Conserva el orden del audio y usa el formato de mensaje requerido por cada conexión. Que los formatos de audio coincidan no hace que los dos protocolos de eventos sean intercambiables.
El puente también es responsable de todo el audio que pone en cola para reproducirlo. Incluye en el diseño de tu aplicación el almacenamiento en búfer del proveedor, las interrupciones y la finalización de la llamada. Consulta Administración de sesiones para conocer el ciclo de vida de las sesiones de Live y Migrar a GPT-Live para conocer los cambios en la gestión de turnos y el control de reproducción.
Conserva el identificador de llamada o de sala del proveedor junto con el ID de sesión de OpenAI para poder rastrear una conversación en ambos sistemas.
Próximos pasos con GPT-Live
- WebSockets: conecta un flujo de audio del servidor a GPT-Live.
- Webhooks y controles del lado del servidor: administra una sesión desde tu backend.
- Delegación y herramientas: conecta el habla con tu backend de razonamiento y herramientas.
- Administración de sesiones: gestiona las transcripciones, el estado de la sesión y el cierre.
SIP es un protocolo que se usa para hacer llamadas telefónicas a través de internet. Con SIP y la Realtime API, puedes dirigir las llamadas telefónicas entrantes a la API.
Descripción general
Si quieres conectar un número de teléfono a la Realtime API, usa un proveedor de troncales SIP (por ejemplo, Twilio). Este servicio convierte tu llamada telefónica en tráfico IP. Después de comprar un número de teléfono a tu proveedor de troncales SIP, sigue las instrucciones que aparecen a continuación.
Comienza por crear un webhook para las llamadas entrantes en Configuración > Proyecto > Webhooks de platform.openai.com.
Luego, dirige tu troncal SIP al punto de acceso SIP de OpenAI con el ID del proyecto
para el que configuraste el webhook, por ejemplo, sip:$PROJECT_ID@sip.api.openai.com;transport=tls.
Para la residencia de datos en Europa, usa sip:$PROJECT_ID@sip-eu.api.openai.com;transport=tls en su lugar.
Para encontrar tu $PROJECT_ID, ve a Configuración > Proyecto > General. Esa página mostrará el ID del proyecto, que
tendrá el prefijo proj_.
Cuando OpenAI reciba tráfico SIP asociado con tu proyecto,
se activará tu webhook. Se emitirá un evento
realtime.call.incoming,
como en el siguiente ejemplo:
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"}
]
}
}A partir de este webhook, puedes aceptar o rechazar la llamada usando el valor call_id del webhook.
Al aceptar la llamada, proporcionarás la configuración necesaria
(instrucciones, voz, etc.) para la sesión de la Realtime API.
Una vez establecida la sesión, puedes configurar un WebSocket y monitorearla como de costumbre. A continuación se documentan las API para
aceptar, rechazar, monitorear, transferir y colgar la llamada.
Acepta la llamada
Usa el punto de acceso para aceptar llamadas para
aprobar la llamada entrante y configurar la sesión en tiempo real que la responderá.
Envía los mismos parámetros que enviarías en una solicitud
create client secret;
es decir, asegúrate de configurar el modelo en tiempo real, la voz, las herramientas o las instrucciones antes de conectar la
llamada al modelo.
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."
}'La ruta de la solicitud debe incluir el call_id del webhook
realtime.call.incoming,
y cada solicitud requiere el encabezado Authorization que se muestra arriba. El
punto de acceso devuelve 200 OK una vez que el tramo SIP está timbrando y la sesión en tiempo real
se está estableciendo.
Rechaza la llamada
Usa el punto de acceso para rechazar llamadas para
rechazar una invitación cuando no quieras atender la llamada entrante (por ejemplo, si proviene de
un código de país no admitido). Proporciona el parámetro de ruta call_id
y, opcionalmente, un status_code de SIP (por ejemplo, 486 para indicar “ocupado”) en el cuerpo JSON
para controlar la respuesta que se envía al operador.
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 no se proporciona un código de estado, la API usa 603 Decline de forma predeterminada. Una
solicitud exitosa recibe 200 OK como respuesta después de que OpenAI entrega la respuesta
SIP.
Monitorear los eventos de la llamada
Después de aceptar una llamada, abre una conexión WebSocket a la misma sesión para
recibir eventos en streaming y enviar comandos en tiempo real. Ten en cuenta que, al conectarte a una llamada existente
con el parámetro call_id, no se usa el argumento model (ya que el modelo se configuró
a través del punto de acceso accept).
Solicitud WebSocket
GET wss://api.openai.com/v1/realtime?call_id={call_id}
Parámetros de consulta
| Parámetro | Tipo | Descripción |
|---|---|---|
call_id | string | Identificador del webhook realtime.call.incoming. |
Encabezados
Authorization: Bearer YOUR_API_KEY
La conexión WebSocket se comporta exactamente igual que cualquier otra conexión a Realtime API. Envía
response.create
y otros eventos del cliente para controlar la llamada, y escucha los eventos del servidor para
seguir su progreso. Consulta Webhooks y controles del lado del servidor
para obtener más información.
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",
})
);
});Redirigir la llamada
Transfiere una llamada activa con el
punto de acceso para transferir llamadas. Proporciona
call_id y el valor de target_uri que debe incluirse en el encabezado SIP Refer-To
(por ejemplo, tel:+14155550123 o 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 devuelve 200 OK una vez que se reenvía REFER a tu proveedor SIP. El
sistema receptor gestiona el resto del flujo de la llamada para la persona que llama.
Colgar la llamada
Finaliza la sesión con el punto de acceso para colgar llamadas cuando tu aplicación deba desconectar a la persona que llama. Este punto de acceso permite finalizar sesiones en tiempo real tanto de SIP como de WebRTC.
curl -X POST "https://api.openai.com/v1/realtime/calls/$CALL_ID/hangup" \
-H "Authorization: Bearer $OPENAI_API_KEY"La API responde con 200 OK cuando comienza a finalizar la llamada.
Rangos de IP para señalización SIP y contenido multimedia
Las llamadas SIP de Realtime usan rutas de red separadas para la señalización y el contenido multimedia. Para garantizar un funcionamiento correcto, configura tu red para permitir el tráfico de señalización y contenido multimedia como se describe a continuación.
Señalización SIP
sip.api.openai.com y sip-eu.api.openai.com son puntos de acceso enrutados mediante GeoIP. Tu red debe permitir
el tráfico TCP/TLS saliente hacia las direcciones que devuelve DNS en el puerto 5061.
Contenido multimedia por SRTP
La API especifica una dirección IP y un puerto UDP separados para el contenido multimedia en el SDP negociado. Tu red debe permitir el tráfico SRTP bidireccional sobre UDP hacia y desde los siguientes bloques CIDR:
13.79.45.80/2823.98.140.64/2840.67.149.176/2840.83.204.240/28
Ejemplos de servidor
A continuación se muestra un ejemplo de un controlador de realtime.call.incoming. Acepta la llamada y luego registra todos los eventos de
Realtime API.
Para el ejemplo en Ruby, configura las variables de entorno OPENAI_API_KEY y OPENAI_WEBHOOK_SECRET
y luego instala las dependencias necesarias con
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)Próximos pasos
Ahora que te conectaste mediante SIP, usa la navegación de la izquierda o abre estas páginas para comenzar a crear tu aplicación en tiempo real.
- Guía de diseño de prompts para tiempo real
- Gestión de conversaciones
- Webhooks y controles del lado del servidor
- Gestión de costos
- Transcripción en tiempo real