Realtime voice: secure customer integration
Customers select a TronXVI voice tier in their own server-side configuration. They never provide an OpenAI key or raw provider model ID.
# Customer backend only. Never place these values in browser code.
TRONXVI_API_BASE_URL=http://127.0.0.1:8010
TRONXVI_API_KEY=trx_live_xxxxxxxxx
TRONXVI_VOICE_MODEL=atlas_voice
TRONXVI_VOICE_NAME=adrian| TronXVI tier | API mode | Provider model | Text input / output | Audio input / output |
|---|---|---|---|---|
| Scout Voice | scout_voice | gpt-realtime-2.1-mini | $0.60 / $2.40 | $10 / $20 |
| Atlas Voice | atlas_voice | gpt-realtime-1.5 | $4 / $16 | $32 / $64 |
| Sentinel Voice | sentinel_voice | gpt-realtime-2.1 | $4 / $24 | $32 / $64 |
Prices are USD per million input / output tokens before any TronXVI markup or customer-credit pricing. Provider model selection is made by TronXVI on the server; raw provider model IDs are deliberately rejected.
Customer flow
Browser -> customer backend -> TronXVI authenticated session route
<- short-lived provider client secret <-
Browser -> OpenAI Realtime WebRTC using only that short-lived secret- The customer backend reads
TRONXVI_API_KEY,TRONXVI_VOICE_MODEL, andTRONXVI_VOICE_NAMEfrom its server environment. - It calls
POST /api/platform/v1/realtime/sessionswith the TronXVI key in theAuthorizationheader. - TronXVI verifies the active key and its allowed voice modes, maps the selected tier to the exact provider model, and creates a 10-minute client secret.
- The customer backend returns that secret to its browser/app.
- The browser uses the short-lived secret with OpenAI Realtime WebRTC. It must never receive a TronXVI key or provider API key.
The client secret is not stored in Platform state, browser storage, logs, or usage records.
Create a realtime voice session
POST /api/platform/v1/realtime/sessions
Authorization: Bearer trx_live_xxxxxxxxx
Content-Type: application/json{
"mode": "atlas_voice",
"voice": "adrian",
"instructions": "You are a concise, helpful product assistant."
}mode is required to be one of scout_voice, atlas_voice, or sentinel_voice. voice defaults to cedar and accepts the provider names alloy, ash, ballad, coral, echo, sage, shimmer, verse, marin, and cedar; Platform aliases such as adrian are also accepted.
Successful response:
{
"status": "ok",
"client_secret": "rt_xxxxx",
"client_secret_expires_at": 1789999999,
"mode": "atlas_voice",
"model": "gpt-realtime-1.5",
"voice": "cedar",
"session": {}
}The client_secret is a sensitive, short-lived credential. Return it only to the intended signed-in browser/app session, then send its SDP offer to OpenAI's Realtime WebRTC endpoint as documented by OpenAI. Do not log it or cache it for future sessions.
Customer backend example
This code belongs in the customer's backend, not in their React/Next client bundle.
const response = await fetch(
`${process.env.TRONXVI_API_BASE_URL}/api/platform/v1/realtime/sessions`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.TRONXVI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
mode: process.env.TRONXVI_VOICE_MODEL ?? "atlas_voice",
voice: process.env.TRONXVI_VOICE_NAME ?? "adrian",
}),
},
);
if (!response.ok) throw new Error("Unable to start a realtime voice session");
const session = await response.json();
// Return session.client_secret to this customer's signed-in browser only.Text chat
{
"message": "Give me a concise onboarding checklist.",
"mode": "atlas"
}Text modes are scout, atlas, and sentinel. They are separate from voice modes; a voice mode cannot be passed to the text endpoint.
Key permission and failure behaviour
- A missing, malformed, revoked, expired, disabled-account, or mismatched key receives
401 auth_errorbefore a provider call. - An active key that does not allow the requested voice tier receives
403 permission_errorbefore a provider call. - Raw provider model IDs and unexpected JSON fields are rejected with
422. - Provider capacity responses become
429 rate_limited; unavailable selected models become503 model_unavailablewith no fallback to a different tier. - Realtime client-secret issuance records an event with selected tier, mapped provider model, status, and latency. Final stream audio/token consumption is provider-billed after issuance and is not yet collected into Platform's usage totals.
Keys created without explicit mode restrictions receive all six TronXVI text and voice modes. Restrict keys per environment or product when that is the desired customer entitlement.
Retired unauthenticated realtime routes
The following old routes are intentionally retired and return 410 realtime_route_retired through the application surface:
/api/assistant/realtime/call/api/assistant/realtime/token/api/assistant/realtime/session-trace/api/assistant/realtime/instructions/api/assistant/realtime/session-restore/{sessionControlId}
They used the backend provider credential without a TronXVI customer key. Use /api/platform/v1/realtime/sessions instead.
Operations and production boundary
Platform's server must have OPENAI_API_KEY configured. The customer does not receive or configure that credential. Session secrets last 600 seconds.
This authenticated API route is ready for customer-backend integration. Before opening the Platform console to real external users, add user/organization authentication and ownership checks to the separate developer/project/key-management console routes, replace the JSON state store with transactional storage, and implement provider usage reconciliation plus spend limits.
