The WebSocket endpoint and real-time connection
On this page
Updated November 3, 2026, based on the xAI Speech to Speech, Pricing, and Rate limits pages: $0.08 per minute, concurrent sessions by tier, and
grok-voice-3.0as the current model. Sources: Speech to Speech · Pricing · Rate limits.
The real-time Voice Agent API
The Grok Voice Agent API lets you build conversational voice agents that talk with your users in real time. Unlike classic REST APIs, which work request by request, this API uses the WebSocket protocol to keep a persistent two-way connection open between your app and xAI’s servers.

There’s a single endpoint:
wss://api.x.ai/v1/realtime
You pick the model with the model URL parameter, for example wss://api.x.ai/v1/realtime?model=grok-voice-latest. grok-voice-latest points to grok-voice-3.0, the current model, and it’s also the default. In production, xAI recommends pinning a named version.
This one endpoint handles the entire life cycle of a voice conversation: receiving audio, detecting speech, generating the response, and sending back the synthesized audio.
Open the WebSocket connection
To connect, put your xAI API key in the authorization header. Here’s an example in JavaScript:
const ws = new WebSocket("wss://api.x.ai/v1/realtime", {
headers: {
"Authorization": "Bearer " + process.env.XAI_API_KEY
}
});
ws.on("open", () => {
console.log("WebSocket connection established");
});
ws.on("message", (data) => {
const event = JSON.parse(data);
console.log("Event received:", event.type);
});
ws.on("close", (code, reason) => {
console.log("Connection closed:", code, reason);
});
ws.on("error", (err) => {
console.error("WebSocket error:", err);
});
In Python, you can use the websockets library:
import asyncio
import websockets
import json
import os
async def connect():
uri = "wss://api.x.ai/v1/realtime"
headers = {
"Authorization": f"Bearer {os.environ['XAI_API_KEY']}"
}
async with websockets.connect(uri, additional_headers=headers) as ws:
async for message in ws:
event = json.loads(message)
print(f"Event: {event['type']}")
asyncio.run(connect())
Session life cycle
As soon as the WebSocket connection opens, the server sends a session.created event confirming the session is active. You then send a session.update event to configure the conversation (voice, instructions, tools, turn detection).
The typical cycle looks like this:
- Connection: open the WebSocket with authentication
- Configuration: send
session.updatewith your settings - Confirmation: receive
session.updatedfrom the server - Conversation: exchange audio and text events
- Closing: disconnect the WebSocket cleanly
Handle connection errors
The server can close or refuse the connection for several reasons: an authentication error, exceeding your tier’s concurrent session limit (10 on the entry tier, up to 200 on the highest), or an incident. The current documentation sets no maximum session length, and session resumption (lesson 4) lets you pick a conversation back up after a drop. Your app should include reconnection logic with exponential backoff.
Prices checked November 3, 2026. Prices change often: before you budget anything, check the current rates on the official xAI pricing page.
Key takeaways
- The WebSocket endpoint
wss://api.x.ai/v1/realtimeis the single entry point for all voice conversations - You authenticate with the
Authorization: Bearer {API key}header - The number of concurrent sessions depends on your tier: 10 on the entry tier, up to 200
- The server sends
session.createdon connection, then waits for yoursession.updateto configure the conversation - Pricing is $0.08 per minute, or $4.80 per hour, plus $0.004 per text input