Gemini Live
Gemini Live models (the live family with provider google-ai-studio, such as gemini-3.8-live)
speak Google's own Live API — the BidiGenerateContent WebSocket protocol. The gateway serves
that protocol on Google's own path, so the official Google GenAI SDKs work unchanged: point
their base URL at the gateway and use your LLM API key.
The gateway is a byte-faithful relay. It authenticates the connection, picks the upstream
credential, rewrites only the model in your first setup message, and passes every other message
through untouched in both directions — tools, transcription, voice settings, session resumption
and anything Google adds later keep working.
INFO
OpenAI's gpt-live-1 uses a different protocol on a different endpoint — see Live Voice
Sessions. A Gemini model sent there, or an OpenAI model sent here, is
refused.
Use the Google GenAI SDK
Python (google-genai):
from google import genai
from google.genai import types
client = genai.Client(
api_key=LLM_API_KEY,
http_options={"base_url": "https://api.llmapi.ai"},
)
config = types.LiveConnectConfig(response_modalities=["AUDIO"], output_audio_transcription={})
async with client.aio.live.connect(model="gemini-3.8-live", config=config) as session:
await session.send_client_content(
turns={"role": "user", "parts": [{"text": "Hello!"}]}, turn_complete=True
)
async for message in session.receive():
if message.data:
play(message.data) # 24 kHz PCM16
if message.server_content and message.server_content.turn_complete:
break
JavaScript / TypeScript (@google/genai):
import { GoogleGenAI, Modality } from "@google/genai";
const ai = new GoogleGenAI({
apiKey: LLM_API_KEY,
httpOptions: { baseUrl: "https://api.llmapi.ai" },
});
const session = await ai.live.connect({
model: "gemini-3.8-live",
config: { responseModalities: [Modality.AUDIO] },
callbacks: {
onmessage: (message) => {
if (message.data) play(message.data); // base64 24 kHz PCM16
},
onerror: (e) => console.error(e),
},
});
session.sendClientContent({ turns: [{ role: "user", parts: [{ text: "Hello!" }] }] });
Connect without an SDK
wss://api.llmapi.ai/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent
wss://api.llmapi.ai/ws/google.ai.generativelanguage.v1alpha.GenerativeService.BidiGenerateContent
The API version you dial is forwarded to Google unchanged. Authenticate with your LLM API key in
any of these forms:
| Form |
Used by |
x-goog-api-key: $LLM_API_KEY |
Python SDK, server-side clients |
?key=$LLM_API_KEY |
JavaScript SDK and browsers |
Authorization: Bearer $KEY |
Any client that sets headers |
WARNING
A key in a query string is visible to anything that logs URLs. Use it only where a header is
impossible, and prefer a short-lived key.
Session lifecycle
1. Client opens the WebSocket
2. Client sends: {"setup":{"model":"models/gemini-3.8-live","generationConfig":{"responseModalities":["AUDIO"]}}}
3. Server sends: {"setupComplete":{}}
4. Client sends: {"realtimeInput":{"audio":{"data":"<base64 PCM16>","mimeType":"audio/pcm;rate=16000"}}} ← repeatedly
or {"clientContent":{"turns":[...],"turnComplete":true}}
5. Server sends: {"serverContent":{"modelTurn":{"parts":[{"inlineData":{"data":"<base64 PCM16>"}}]}}} ← repeatedly
Server sends: {"toolCall":{...}} → client answers with {"toolResponse":{...}}
6. Server sends: {"serverContent":{"turnComplete":true},"usageMetadata":{...}} ← once per turn
The setup message must be first and must arrive within 60 seconds of the upgrade. setup.model
takes models/<id> or a bare id. The gateway replaces it with the provider's model name; every
other setup field reaches Google verbatim. Server messages are relayed exactly as Google sends
them, including their binary WebSocket frames.
Audio format
- Input: PCM16 little-endian, mono, 16 kHz (
mimeType: "audio/pcm;rate=16000")
- Output: PCM16 little-endian, mono, 24 kHz
- Audio travels base64-encoded inside JSON messages
Models and tools
List the available models with GET /v1/models (family live). Notes:
gemini-3.8-live-extended-thinking requires generationConfig.thinkingConfig.thinkingLevel in
setup; without it Google closes the session with 1007.
- Grounding with Google Search or Google Maps (
googleSearch, googleSearchRetrieval,
googleMaps) is billed by Google per request, so it is available where that cost is accounted
for:
- With your own Google API key (a project in API-keys mode): always — Google bills the
searches to your Google account.
- On LLM API credit: Google Search on models that report the queries they run, billed per
query at the model's web-search price. Gemini 3.x Live models do not report their searches, so
on them grounding needs your own key; a
setup asking for it is refused with 1008.
- Function calling, code execution and URL context bill as ordinary tokens and work everywhere.
setup can be sent only once per connection; a second one closes the session.
- Ephemeral tokens (
auth_tokens/…) are not supported — authenticate with an LLM API key.
Billing
Gemini Live bills per token, per turn, from the usageMetadata Google reports with each
turnComplete:
- Each turn bills its whole context — the conversation so far, including earlier audio — not just
the new input, so a long session costs more per turn than a short one. Google's
context window compression caps this.
- Input is priced per modality (text, audio, image/video) and output per modality (text, audio);
thinking tokens are billed at the output rate. The model page in the dashboard lists every rate.
- Google Search grounding on credit bills per distinct query the model reports in a turn, shown as
the request's web-search cost.
- If you hang up while the model is still answering, that answer is still billed — Google bills
it — and the gateway keeps the upstream open just long enough to record it.
Each connection appears in your logs and analytics as one streamed request with its token counts
and cost.
Limits
| Limit |
Value |
| Idle timeout |
60 s without a client message |
| Maximum duration |
2 hours, or the model's own maximum if it is shorter |
| Google connection |
About 10 minutes; Google sends goAway first — reconnect with session resumption |
| Concurrent sessions |
Capped per organization when your plan sets a cap |
| Credit guard |
The session is closed before it can spend more than the remaining balance |
Sessions on your own provider key (BYOK) are not gated on gateway credit.
Errors
As with Google's API, errors arrive as WebSocket close frames — the SDKs raise them as API
errors carrying the close code and reason. Close codes Google sends are passed through unchanged;
the gateway's own use the same codes:
| Code |
Meaning |
1007 |
Invalid setup: not the first message, no model, or a second setup |
1008 |
Not allowed: unknown model, model not served here, access denied, unsupported tool, credit exhausted |
1011 |
Internal: no provider credential, provider unreachable, model not priced |
1013 |
Try again later: concurrent session cap reached, or the gateway is restarting |
Authentication and balance problems are refused before the WebSocket opens, with HTTP 401
(missing or invalid key), 402 (no credit) or 429 (rate limited).
API operation: GET /ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent