Realtime (WebSocket)
POST https://api.mafdet.ai/v1/realtime/sessions ← mint a ticket
wss://api.mafdet.ai/v1/realtime ← open the session
A realtime session is a persistent WebSocket carrying audio both ways: you push microphone audio as it is captured, and the model answers while you are still speaking. Use it for live captions and spoken conversation — anything where waiting for the recording to finish defeats the point.
Transcribing a file? Do not use this. A recording you already have goes to
/v1/chat/completionsas an audio part withgemini-3.5-transcribe. It is one ordinary HTTPS request, about 30% cheaper, and there is no session to manage. Realtime earns its complexity only when the audio does not exist yet.
Models
| Model | What it does | Input | Output |
|---|---|---|---|
gemini-3.5-transcribe-live | Speech to text as it is spoken | $4.20 / 1M | $25.20 / 1M |
gemini-live-native-audio | Spoken conversation, audio in and out | $0.60 / 1M | $2.40 / 1M |
Both are PAID tier. Both are pre-GA — see the release stage in their display names on the models page.
Two steps, and why
The WebSocket does not accept your API key. You exchange the key for a one-time ticket over HTTPS, then open the socket with the ticket.
This is deliberate. A WebSocket's credentials travel in the handshake URL and
headers, which reach proxy logs, browser history and ps output in a way an
HTTPS request body does not. A ticket is single-use, expires in 30 seconds, and
is worthless once the session starts.
1. Mint a ticket
Your API key needs the realtime:call scope. Scopes are fixed when a key is
created, so an existing key cannot be upgraded — create a new one and select
Realtime. A key without the scope gets 403 INSUFFICIENT_SCOPE; this is why a key you use
for account reads cannot quietly start opening billable audio sessions.
curl https://api.mafdet.ai/v1/realtime/sessions \
-H "Authorization: Bearer $MAFDET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gemini-3.5-transcribe-live"}'
{
"realtimeSessionId": "…",
"ticket": "S3vQ…",
"wsUrl": "wss://api.mafdet.ai/v1/realtime",
"subprotocol": "mafdet-realtime.v1",
"expiresInSeconds": 30,
"model": "gemini-3.5-transcribe-live",
"billing": {
"dimensions": [{ "dimension": "AUDIO_INPUT", "sellMicroUsd": "…" }],
"maxSessionSpendMicroUsd": "…",
"maxSessionSeconds": 600
}
}
The billing block is the session's own price list and spend cap, returned
before you connect so a session is never open-ended.
2. Connect within 30 seconds
The ticket goes in the WebSocket subprotocol header, not the URL:
Sec-WebSocket-Protocol: mafdet-realtime.v1, mafdet-ticket.<ticket>
Mint the ticket immediately before connecting. Thirty seconds is enough to
open a socket and nothing else — if you prepare audio, prompt for a microphone,
or wait on a user after minting, the ticket will have expired and the socket
closes 4401.
Sending and receiving
Frames are JSON. Audio is base64 PCM, 16-bit little-endian mono at 16 kHz going up and 24 kHz coming down.
{
"realtimeInput": {
"mediaChunks": [
{ "mimeType": "audio/pcm;rate=16000", "data": "<base64 pcm16le>" }
]
}
}
The server streams back transcription or audio as it is produced, and marks the end of each reply with a turn-complete frame. Usage arrives per turn, not as a running total — add the turns up if you want a session figure.
Limits
| Limit | Default |
|---|---|
| Concurrent sessions per API key | 2 |
| Concurrent sessions per organization | 3 |
| Session duration | 10 minutes |
| Turns per session | 100 |
| Frame size | 128 KB |
Sessions also end when the spend cap is reached or the wallet runs short. Every
limit closes the socket with a distinct code and a stated reason — never a silent
disconnect. A key at its cap gets 4429, as does an org at its own.
Billing
Billed on tokens split by modality: text and audio are priced separately in each direction, and audio is the expensive half. Credit is reserved as the session runs and settled on the turns actually used when it ends.
A session that dies badly — your process is killed, the network drops, the gateway restarts — is settled from the durable record of what it consumed. You are not billed for a session that vanished, and one is never silently free.
Privacy
Audio streams for the length of the turn and is not recorded. Mafdet does not store your microphone audio or the model's, and neither is written into conversation history or logs.