Platform
Docs

Build on TronXVI Platform

TronXVI Platform exposes text, image-generation, Web Search, and realtime voice flows. This guide covers project setup, API keys, environment variables, model selection, and the core routes developers will integrate.

  1. Confirm that your signed-in administrator account is authorised for the workspace.
  2. Create a local project in Platform.
  3. Issue a TronXVI API key.
  4. Configure the required environment variables.
  5. Send text, image, and Web Search requests through the authenticated Platform routes.
  6. Create authenticated short-lived realtime sessions for voice.

Current platform status

Read this before creating a project, key, or customer integration.

Platform v1 data-plane routes for chat, image generation, Web Search, and realtime sessions authenticate a TronXVI developer API key.
The developer, project, key, and console-management routes require a signed-in administrator, but the backend does not yet enforce per-user or per-organisation ownership. Confirm the account and workspace boundary before using production data.
Keep control-plane access behind the Platform sign-in and use the authenticated data-plane routes for customer integrations. Do not place a long-lived developer API key in browser storage.
Billing screens show operational estimates and unavailable states. They are not an invoice, payment ledger, credit balance, or enforced auto-recharge system.

Start here

Complete these steps before wiring the application or client integration.

1

Read the current Platform status before using the console; confirm that your signed-in administrator account is authorised for the workspace.

2

Create a project in Platform so API keys and usage are scoped correctly.

3

Generate a TronXVI API key and store it in server-side configuration only.

4

Enable Web Search only when the API key's tool allowance is appropriate for the application.

5

Select a TronXVI voice name such as Maya or Adrian for the assistant experience.

6

Use the authenticated Platform routes for image generation, Web Search, and live voice sessions.

7

For General Chat rendering, install @tronxvi/brain-renderer, add the server proxy, consume the SSE stream, and render the terminal response.

Use the console

These are the current sidebar workflows and their limits.

Home

Use the activity-window buttons to view request, success-rate, active-key, estimated-spend, and telemetry summaries.

The figures are workspace telemetry, not invoice-grade billing data.

Dashboard

Filter the usage chart by day, week, or month and by API key.

Switch between key inventory and recent traffic. Refresh reloads the current workspace from the backend.

Projects and API keys

Create, search, inspect, and export projects as CSV. Project key details show current, revoked, and expired credentials.

Create a key for a selected project, set an optional expiry and spend limit, then copy the full value immediately. Deleting a key in the UI revokes it; it does not erase its historical usage record.

Playground and voice

The text Playground sends a real chat request only after you paste a developer key. The key remains in page memory only and is cleared on refresh; it is never written to browser storage.

The voice view is an integration guide, not a browser-side realtime caller. Image generation and direct Web Search are API integrations rather than Playground actions.

Billing, support, and aliases

Treat Billing tabs and cards as informational until authoritative payment and credit telemetry is connected.

Use the sidebar profile menu for Support or Report a bug. /support and /chats currently show the Playground; /analytics shows Dashboard; /users shows Projects.

API keys, limits, and rotation

Use the current key controls carefully; they are development-console controls, not a multi-user production control plane.

A newly issued full API key is shown only once. Copy it before closing the save dialog, store it in a server-side secret manager, and rotate it by issuing a replacement before revoking the old key.
New keys default to all six selectable text and voice modes, Web Search enabled, a 20-request-per-minute Web Search limit, a 1,000-request monthly Web Search allowance, no expiry, and no per-key spend limit.
The Scout, Atlas, and Sentinel text-mode entitlements also gate the matching image tier. For example, an Atlas image request requires the atlas mode to be allowed for that key.
A spend_limit_usd is a per-key estimate guard, not an account balance. Once completed successful usage reaches the recorded limit, later chat, image, Web Search, and realtime-session requests return 429 usage_limit_exceeded without a provider call.
The guard is evaluated from completed estimated usage, so a request may take the recorded total above its limit before a later request is blocked. There is no prepaid balance, payment-required response, auto-recharge, or account-wide hard cap today.
Expiry dates are interpreted as the end of the selected UTC day. Revocation is immediate for future authentication. The current key-update route can rename, move, expire, and revoke a key; it cannot change an existing spend limit.

Env setup

Most integrations only need one API key, one text mode, one image tier, an optional Web Search tool, one voice tier, and one public voice name.

TRONXVI_API_URL=https://api.tronxvi.com
TRONXVI_API_KEY=<set-in-Railway-or-Vercel>
TRONXVI_IMAGE_MODEL=atlas
TRONXVI_VOICE_MODEL=atlas_voice
TRONXVI_VOICE_NAME=adrian
TRONXVI_ENABLED_TOOLS=web_search
Store TRONXVI_API_KEY on the server. Do not expose it in browser code or client bundles.
TRONXVI_IMAGE_MODEL selects the image tier: scout, atlas, or sentinel. Platform always maps it to the server-owned gpt-image-2 model.
TRONXVI_VOICE_MODEL selects the TronXVI realtime voice model tier: scout_voice, atlas_voice, or sentinel_voice.
TRONXVI_VOICE_NAME accepts public TronXVI voice names, but send the value in lowercase such as mason, maya, or adrian.
TRONXVI_ENABLED_TOOLS is your application policy. Set it to web_search only when your project key has Web Search enabled; never set or ship a Brave API key.

General Chat rendering integration

Use one TronXVI API key, the canonical structured response, and the official renderer package to render tables, files, spreadsheets, diagrams, images, code, and other General Chat capabilities inside your own application.

What TronXVI owns: authentication, the request and response contract, structured capability blocks, and the official renderer.
What your app owns: its page layout, colors, typography, navigation, user authentication, and the place where the answer appears.
Important: the API key authenticates the server request; it does not belong in browser code. The renderer package displays the structured response.

1. Install the renderer

npm install @tronxvi/brain-renderer

2. Add a server proxy

import { NextRequest } from "next/server";

export async function POST(request: NextRequest) {
  const body = await request.text();
  const upstream = await fetch(
    process.env.TRONXVI_API_URL + "/api/platform/v1/chat/stream",
    {
      method: "POST",
      headers: {
        Authorization: "Bearer " + process.env.TRONXVI_API_KEY,
        "Content-Type": "application/json",
        Accept: "text/event-stream",
      },
      body,
      cache: "no-store",
    },
  );

  return new Response(upstream.body, {
    status: upstream.status,
    headers: {
      "Content-Type": upstream.headers.get("Content-Type") || "text/event-stream",
      "Cache-Control": "no-cache, no-transform",
    },
  });
}

3. Consume the SSE stream

export async function consumeTronXVIStream(
  body: ReadableStream<Uint8Array>,
  onEvent: (event: Record<string, unknown>) => void,
) {
  const reader = body.getReader();
  const decoder = new TextDecoder();
  let buffer = "";

  while (true) {
    const { value, done } = await reader.read();
    buffer += decoder.decode(value || new Uint8Array(), { stream: !done });
    const frames = buffer.split(/\r?\n\r?\n/);
    buffer = frames.pop() || "";

    for (const frame of frames) {
      const data = frame
        .split(/\r?\n/)
        .filter((line) => line.startsWith("data:"))
        .map((line) => line.slice(5).trimStart())
        .join("\n");
      if (data) onEvent(JSON.parse(data));
    }

    if (done) break;
  }
}

4. Render the terminal response

import {
  GeneralChatAnswerRenderer,
  type GeneralChatResponse,
} from "@tronxvi/brain-renderer";
import "@tronxvi/brain-renderer/styles.css";

export function TronXVIAnswer({ response }: { response: GeneralChatResponse | null }) {
  if (!response) return null;
  return <GeneralChatAnswerRenderer response={response} />;
}

General Chat contract and capability output

Send a message to /api/platform/v1/chat/stream. The stream uses general_chat.event.v2; the terminal response uses general_chat.response.v2.

{
  "contract": "general_chat.response.v2",
  "requestId": "req_123",
  "answer": {
    "blocks": [
      {
        "id": "table_001",
        "kind": "answer_table",
        "caption": "Comparison",
        "columns": ["Option", "Price"],
        "rows": [["Atlas", "$10"]]
      }
    ],
    "artifacts": []
  },
  "outcome": { "status": "complete" }
}
The API key authenticates the server request. It does not belong in browser JavaScript, NEXT_PUBLIC_* variables, HTML, mobile bundles, or logs.
The server forwards the request to /api/platform/v1/chat/stream and forwards the SSE body without buffering, rewriting, or converting it to plain text.
The terminal complete, failed, or rejected event contains the authoritative general_chat.response.v2 response. Pass that response to GeneralChatAnswerRenderer.
The renderer controls TronXVI answer content only. The customer owns the surrounding page layout, colors, navigation, typography, and placement.
Tables, files, spreadsheets, diagrams, images, code, and other capability results arrive as typed answer blocks. Do not recreate them by parsing prose or Markdown.
Generated artifacts must be downloaded through the customer server with the same API key; never put the key in a browser download link.

Choose your models

Text, image, and voice are configured separately. Atlas is the recommended default for most new integrations.

Text modes

Provider estimates are USD per million input / output text tokens, before any future TronXVI markup.

ModeProvider modelProvider price / 1MBest for
scoutgpt-5.4-mini$0.75 / $4.50Lowest-cost text traffic and fast general responses.
atlasgpt-5.6-terra$2 / $12Balanced default for most production chat integrations.
sentinelgpt-5.6-sol$5 / $30Highest-quality text output when response quality matters most.

Voice tiers

TierProvider modelProvider price / 1M tokensBest for
scout_voicegpt-realtime-2.1-mini$0.60 / $2.40 text · $10 / $20 audioFast, lower-cost realtime voice.
atlas_voicegpt-realtime-1.5$4 / $16 text · $32 / $64 audioBalanced realtime voice for most assistant products.
sentinel_voicegpt-realtime-2.1$4 / $24 text · $32 / $64 audioMost capable realtime voice for demanding conversations.

Image tiers

All three public image tiers use the server-owned gpt-image-2 model. Tier selection controls quality; callers cannot send an upstream model or a raw quality value.

TierProvider modelQuality1024×1024 output estimateBest for
scoutgpt-image-2low$0.006 / imageFast drafts, thumbnails, and quick iteration.
atlasgpt-image-2medium$0.053 / imageThe balanced default for product and marketing images.
sentinelgpt-image-2high$0.211 / imageFinal assets and detailed, high-fidelity work.

Output estimates by size

SizeScoutAtlasSentinel
1024×1024$0.006 / image$0.053 / image$0.211 / image
1024×1536$0.005 / image$0.041 / image$0.165 / image
1536×1024$0.005 / image$0.041 / image$0.165 / image

Estimates cover image output only. Prompt text can add provider cost. Reference-image inputs and image editing are not supported by this route.

Web Search

Platform sends the query to Brave using its own server-held credential, then returns clean results and source URLs to your authenticated backend.

curl -X POST "$TRONXVI_API_URL/api/platform/v1/web/search" \
  -H "Authorization: Bearer $TRONXVI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "latest AI news in Australia",
    "country": "AU",
    "searchLanguage": "en",
    "count": 8
  }'
Web Search is an authenticated Platform tool, not a customer-selectable provider model. Platform keeps the Brave credential on its server.
The direct route returns normalized title, URL, snippet, source name, and citations. It accepts only query, count, country, and searchLanguage.
query is required, limited to 400 characters and 50 words. count defaults to 8 and accepts 1 through 10; country is an uppercase two-letter code and searchLanguage is a lowercase 2–5 character code.
Pass tools: [{ type: web_search }] to the chat route when you want the selected TronXVI text tier to answer from fresh results and return citations.
Each key has a Web Search entitlement, requests-per-minute limit, and monthly allowance. Requests outside those limits are rejected before Brave is called.
Brave searches are currently recorded at an estimated $0.005 per request; your application must never expose a Brave credential to its browser or customer environment.

Routes developers actually call

Customer applications should use the authenticated /api/platform/v1 data-plane routes. Provisioning and key-management routes are signed-in administrator console routes, not external customer APIs.

MethodRoutePurpose
POST/api/platform/v1/chat/streamRun General Chat through the API key and receive canonical general_chat.event.v2 SSE events with structured renderable output.
POST/api/platform/v1/images/generateGenerate one image through the authenticated Scout, Atlas, or Sentinel image tier.
POST/api/platform/v1/web/searchRun an authenticated Brave Web Search and return normalized cited results.
GET/api/platform/developersDevelopment-console route: list local developer workspaces. Do not expose to external users.
POST/api/platform/developersDevelopment-console route: create a local developer workspace.
POST/api/platform/projectsDevelopment-console route: create a local project to own keys and usage.
POST/api/platform/keysDevelopment-console route: issue a TronXVI developer API key.
PATCH/api/platform/keys/{keyId}Development-console route: rename, expire, move, or revoke a TronXVI API key.
GET/api/platform/developers/{developerAccountId}Admin console route: load workspace state for the signed-in administrator.
POST/api/platform/v1/realtime/sessionsAuthenticate a server-held TronXVI key and issue a short-lived browser realtime client secret.

Authenticated realtime session example

Voice sessions should use a short-lived client secret rather than the long-lived server API key.

POST /api/platform/v1/realtime/sessions
Authorization: Bearer <server-issued-api-key>
Content-Type: application/json

{
  "mode": "atlas_voice",
  "voice": "adrian"
}
Request the realtime session from your backend, not directly from untrusted client code.
Use TronXVI tier names such as atlas_voice and lowercase TronXVI voice names such as maya or adrian.
mode defaults to atlas_voice, voice defaults to cedar, and instructions accepts at most 4,000 characters. Raw provider model IDs and unexpected fields are rejected.
Send the server-issued Authorization value from the server. The response returns a short-lived client secret with a 600-second lifetime for the browser or mobile session.
Return only the current session secret to the intended signed-in browser or app, establish the WebRTC session with that secret, and obtain a new session from your backend when it expires or reconnects.
Do not expose the long-lived TronXVI key or a raw provider model ID in browser code.

Voice names and client handoff

Use a public TronXVI voice name in your request; Platform resolves it to the provider voice shown below.

Public nameRequest valueResolved provider voice
Masonmasonalloy
Skyeskyeash
Gracegraceballad
Mayamayacoral
Leoleoecho
Ivyivysage
Chloechloeshimmer
Judejudeverse
Elenaelenamarin
Adrianadriancedar
After your backend receives client_secret, give it only to the currently authorised browser or mobile session. That client establishes its own OpenAI Realtime WebRTC connection; Platform does not proxy the live audio stream.
Discard the secret when the session ends. Request a fresh secret from your backend after expiry, reconnect, or a new signed-in client session.

Image request example

Image generation is server-to-server and authenticated with the same TronXVI API key as text requests.

curl -X POST "$TRONXVI_API_URL/api/platform/v1/images/generate" \
  -H "Authorization: Bearer $TRONXVI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A polished product hero image of a dark glass bottle on a black background",
    "mode": "atlas",
    "size": "1024x1024"
  }'
Send only scout, atlas, or sentinel as mode. The API rejects raw provider model IDs and raw quality values.
Scout uses low quality, Atlas uses medium quality, and Sentinel uses high quality on gpt-image-2.
prompt is required and accepts up to 8,000 characters. size defaults to 1024x1024 and accepts only 1024x1024, 1024x1536, or 1536x1024.
The API returns the selected tier, provider model, quality, size, and estimated output cost with the image.
This route creates one prompt-only image. It does not accept reference images, image editing controls, raw provider settings, or customer-selected quality values.
Store the TronXVI API key in your application server; never make this request directly from browser code.

Integration flow

Use this sequence when handing the integration off to an application engineer.

1. Provision a workspace

Use the current console only from an authorised administrator session.

Create the developer account in Platform, then create a project for the application or environment you want to isolate.

Generate the TronXVI API key your backend will use for authenticated requests.

2. Integrate Web Search

Enable TRONXVI_ENABLED_TOOLS=web_search in your own server environment when the application should be able to search.

Call /api/platform/v1/web/search for raw cited results.

Never configure a Brave API key in the customer application. Platform enforces the key entitlement, rate limit, monthly allowance, and server-side provider call.

3. Integrate realtime voice

Request a short-lived client secret from /api/platform/v1/realtime/sessions using your server-held key.

Pass the selected voice tier such as atlas_voice and a TronXVI voice name such as Adrian.

Use the returned client secret in the browser or application session instead of exposing the long-lived server key.

Mini engine scope

This docs page describes the platform console, not the broader public TronXVI chat surface.

What it supports

Create developer accounts, projects, and developer API keys for the platform workspace.
Run authenticated Brave Web Search through /api/platform/v1/web/search, or add the Web Search tool to a text request for a cited answer.
Track usage, latency, token counts, and estimated cost per developer API key.
Issue short-lived voice session client secrets through /api/platform/v1/realtime/sessions.
Record voice-session issuance, selected tier, provider model, status, and latency per developer API key.

What it does not support

The image route creates one prompt-only image. It does not support image editing or reference-image uploads.
The General Chat renderer covers the typed capabilities currently emitted by the canonical answer contract. Function calling, File Search, MCP, Skills are not public customer capabilities in this integration until their contracts and renderer blocks are published.
It does not currently enforce prepaid credit balance, auto-recharge, monthly cap, or insufficient-funds shutdown behavior.
Realtime stream token usage is provider-billed after session issue; the Platform console currently records session issuance rather than final audio token totals.
The long-lived TronXVI developer API key should not be exposed directly to browser voice clients.

Runtime and storage

These details matter when you are integrating locally and handing short-lived realtime session secrets to your own client.

Runtime requirements

The platform app depends on the Railway backend API at https://api.tronxvi.com in production.
OPENAI_API_KEY must be configured in the backend for authenticated realtime session issuance to work.
BRAVE_SEARCH_API_KEY is the server-only Platform Web Search credential.
The platform app itself runs separately from the backend and reads its live state through backend routes.

Persistence behavior

Developer accounts, projects, keys, and usage events persist through the configured production storage service.
Voice session secrets are never saved in Platform state or browser storage.

Data handling and retention

Use this current-state matrix when deciding what data is safe to place in the development console.

SurfaceCurrent behavior
Developer stateAccounts, projects, hashed key records, and usage events are stored by the configured production persistence service.
API key materialThe full key is returned only at creation. The console retains only its prefix and must not be used to store plaintext keys.
Realtime secretNever saved in Platform state, browser storage, or usage records. It expires after 600 seconds and must only reach the intended signed-in application session.
DurabilityThe current state store is a local JSON file, not transactional storage. There is no documented backup, recovery, retention, or deletion service-level commitment.

Run and operate Platform

These settings belong to the Platform app. They are separate from the customer backend environment shown above.

NEXT_PUBLIC_API_URL=https://api.tronxvi.com
NEXT_PUBLIC_APP_URL=https://infinity.tronxvi.com
NEXT_PUBLIC_PLATFORM_URL=https://infinity.tronxvi.com/platform/
Platform runs in the Infinity Vercel project at https://infinity.tronxvi.com/platform/ and reads the Railway API at https://api.tronxvi.com. Configure production values through the deployment environment.
Production Platform builds require NEXT_PUBLIC_API_URL, NEXT_PUBLIC_APP_URL, and NEXT_PUBLIC_PLATFORM_URL. TRONXVI identity sessions are established by the central identity service; do not put secret credentials in browser configuration.
Customer integrations use TRONXVI_* variables in their own backend. Platform itself owns OPENAI_API_KEY and BRAVE_SEARCH_API_KEY; customer browsers must never receive any of those secrets.
Check the backend health endpoint before troubleshooting an integration. Configure production origins, TLS, and CORS at deployment time for your own customer backend; the documented routes are intended for server-to-server calls.
This page documents the current /api/platform/v1 data-plane contract. No separate changelog or deprecation window is published yet, so re-check this page when upgrading an integration.

Route contracts

These are the concrete request and response shapes the current platform console exposes.

List developers

GET /api/platform/developers
{
  "developers": [
    {
      "id": "acct_001",
      "display_name": "Acme Dev",
      "email": "dev@acme.test",
      "status": "active",
      "default_mode": "atlas"
    }
  ]
}
Returns all developer workspaces visible to the platform console.
The response body is an object with a developers array.

Create developer

POST /api/platform/developers
{
  "display_name": "Acme Dev",
  "email": "dev@acme.test",
  "default_mode": "atlas"
}
{
  "developer_account": {
    "id": "acct_001",
    "display_name": "Acme Dev",
    "email": "dev@acme.test",
    "status": "active",
    "default_mode": "atlas"
  }
}
display_name and email are required.
Duplicate developer emails return a validation error.

Create project

POST /api/platform/projects
{
  "developer_account_id": "acct_001",
  "name": "Core API",
  "description": "Primary integration project"
}
{
  "project": {
    "id": "proj_001",
    "developer_account_id": "acct_001",
    "name": "Core API",
    "slug": "core-api",
    "description": "Primary integration project",
    "key_count": 0,
    "active_key_count": 0,
    "created_at": "2026-07-19T10:00:00Z",
    "archived_at": null
  }
}
developer_account_id and name are required.
Project slugs are generated by the backend and may be adjusted for collisions.

Create API key

POST /api/platform/keys
{
  "developer_account_id": "acct_001",
  "project_id": "proj_001",
  "label": "Primary API key",
  "allowed_modes": ["scout", "atlas", "sentinel", "scout_voice", "atlas_voice", "sentinel_voice"],
  "expires_at": "2026-12-31",
  "allowed_tools": ["web_search"],
  "web_search_requests_per_minute": 20,
  "web_search_monthly_limit": 1000,
  "spend_limit_usd": 25
}
{
      "api_key": "<server-issued-api-key>",
  "key_id": "key_001",
      "key_prefix": "<provider-issued-key-prefix>",
  "developer_account_id": "acct_001",
  "project_id": "proj_001",
  "label": "Primary API key",
  "allowed_modes": ["scout", "atlas", "sentinel", "scout_voice", "atlas_voice", "sentinel_voice"],
  "allowed_tools": ["web_search"],
  "web_search_requests_per_minute": 20,
  "web_search_monthly_limit": 1000,
  "spend_limit_usd": 25,
  "created_at": "2026-07-19T10:02:00Z",
  "expires_at": "2026-12-31T23:59:59Z"
}
The full api_key value is returned only once at creation time.
Persist the key immediately. Later responses only expose the key prefix.
Use null or omit expires_at to create a key that never expires. A YYYY-MM-DD date expires at the end of that UTC day.
allowed_modes defaults to all three text and three voice modes. Those text-mode entitlements also control the matching image tiers.
spend_limit_usd is optional and must be greater than zero when supplied. It is a per-key estimated-usage guard, not a billing balance.

Update API key

PATCH /api/platform/keys/{keyId}
{
  "label": "Renamed key",
  "project_id": "proj_002",
  "expires_at": "2026-07-25",
  "allowed_tools": ["web_search"],
  "web_search_requests_per_minute": 20,
  "web_search_monthly_limit": 1000,
  "revoke": false
}
{
  "id": "key_001",
  "developer_account_id": "acct_001",
  "project_id": "proj_002",
  "project_name": "Mobile SDK",
  "label": "Renamed key",
      "key_prefix": "<provider-issued-key-prefix>",
  "allowed_tools": ["web_search"],
  "web_search_requests_per_minute": 20,
  "web_search_monthly_limit": 1000,
  "status": "active",
  "created_at": "2026-07-19T10:02:00Z",
  "last_used_at": null,
  "revoked_at": null,
  "expires_at": "2026-07-25T23:59:59Z",
  "spent_usd": 0.0
}
All request fields are optional.
Set revoke to true to revoke the key.
A plain YYYY-MM-DD expiry is normalized to the end of that UTC day.
spend_limit_usd is intentionally not an update field. Issue a new key when the existing limit is no longer appropriate.

Developer console payload

GET /api/platform/developers/{developerAccountId}
{
  "developer_account": {
    "id": "acct_001",
    "display_name": "Acme Dev",
    "email": "dev@acme.test",
    "status": "active",
    "default_mode": "atlas"
  },
  "projects": [
    {
      "id": "proj_001",
      "developer_account_id": "acct_001",
      "name": "Core API",
      "slug": "core-api",
      "description": "",
      "key_count": 1,
      "active_key_count": 1,
      "created_at": "2026-07-19T10:00:00Z",
      "archived_at": null
    }
  ],
  "api_keys": [
    {
      "id": "key_001",
      "developer_account_id": "acct_001",
      "project_id": "proj_001",
      "project_name": "Core API",
      "label": "Primary key",
      "key_prefix": "<provider-issued-key-prefix>",
      "status": "active",
      "created_at": "2026-07-19T10:02:00Z",
      "last_used_at": "2026-07-19T10:05:00Z",
      "revoked_at": null,
      "expires_at": null,
      "spent_usd": 0.0325
    }
  ],
  "usage_summary": {
    "total_requests": 2,
    "successful_requests": 1,
    "rejected_requests": 0,
    "rate_limited_requests": 0,
    "error_requests": 1,
    "total_input_tokens": 17,
    "total_output_tokens": 7,
    "total_tokens": 24,
    "total_estimated_cost_usd": 0.0325,
    "last_request_at": "2026-07-19T10:05:00Z"
  },
  "recent_usage": [],
  "usage_daily": [],
  "usage_chart": []
}
This is the main console payload consumed by the platform UI.
It includes projects, keys, recent usage, daily usage, and chart data.

Platform Web Search

POST /api/platform/v1/web/search
{
  "query": "latest AI news in Australia",
  "country": "AU",
  "searchLanguage": "en",
  "count": 8
}
{
  "status": "ok",
  "provider": "brave",
  "query": "latest AI news in Australia",
  "result_count": 1,
  "estimated_cost_usd": 0.005,
  "results": [
    {
      "id": "web-1",
      "title": "Example source",
      "url": "https://example.com/news",
      "snippet": "A result snippet.",
      "source_name": "example.com",
      "published_at": null
    }
  ],
  "citations": ["https://example.com/news"]
}
Send the server-issued Authorization value from the customer's backend. Never send a Brave key.
The route accepts only query, count, country, and searchLanguage. Provider-specific credentials and raw options are rejected.
Platform checks Web Search entitlement, rate limit, and monthly allowance before calling Brave.

Create an authenticated realtime session

POST /api/platform/v1/realtime/sessions
{
  "mode": "atlas_voice",
  "voice": "adrian",
  "instructions": "You are a concise, helpful product assistant."
}
{
  "status": "ok",
  "client_secret": "rt_xxxxx",
  "client_secret_expires_at": 1789999999,
  "mode": "atlas_voice",
  "model": "gpt-realtime-1.5",
  "voice": "cedar",
  "session": {}
}
Send the server-issued Authorization value from the customer's backend, never from browser code.
The response returns a short-lived client secret for browser or mobile WebRTC sessions.
Voice aliases such as adrian are resolved to the provider voice returned in the response.

Error contract and recovery

Inspect the HTTP status and detail object together. Preserve request_id when contacting support or correlating your own logs.

{
  "detail": {
    "code": "usage_limit_exceeded",
    "message": "This API key has reached its spend limit.",
    "retryable": false,
    "request_id": "request-uuid",
    "spend_limit_usd": 25
  }
}
Every Platform HTTP error has detail.code, detail.message, detail.retryable, and detail.request_id. Depending on the route it can also include route, model, tool, mode, or spend_limit_usd.
Do not retry validation_error, auth_error, permission_error, or usage_limit_exceeded until the request, entitlement, or configuration has changed. These failures are non-retryable.
Use bounded backoff for retryable rate_limited and provider_failure responses. missing_configuration requires Platform operator configuration, while model_unavailable means the selected voice model is temporarily unavailable.
Key-mode or tool denial returns 403 permission_error. Web Search rate limits return 429 rate_limited; a monthly Web Search allowance or per-key spend limit returns 429 usage_limit_exceeded.

Auth failures

Platform chat uses developer API key auth. These abbreviated examples share the standard retryable and request_id fields shown above.

Missing bearer token

{
  "detail": {
    "code": "auth_error",
    "message": "Developer API key is required."
  }
}

Invalid key

{
  "detail": {
    "code": "auth_error",
    "message": "Developer API key is invalid."
  }
}

Revoked key

{
  "detail": {
    "code": "auth_error",
    "message": "Developer API key has been revoked."
  }
}

Expired key

{
  "detail": {
    "code": "auth_error",
    "message": "Developer API key has expired."
  }
}

Disabled account

{
  "detail": {
    "code": "auth_error",
    "message": "Developer account is not active."
  }
}

Validation and permission failures

Project and key provisioning routes use explicit validation and permission error shapes. These abbreviated examples share the standard retryable and request_id fields shown above.

Missing project name

{
  "detail": {
    "code": "validation_error",
    "message": "Project name is required."
  }
}

Unknown developer account

{
  "detail": {
    "code": "validation_error",
    "message": "Developer account was not found."
  }
}

Duplicate developer email

{
  "detail": {
    "code": "validation_error",
    "message": "Developer email already exists."
  }
}

Unknown project on key update

{
  "detail": {
    "code": "validation_error",
    "message": "Developer project was not found."
  }
}

Invalid key expiry

{
  "detail": {
    "code": "validation_error",
    "message": "Expiry date is invalid."
  }
}

Archived project

{
  "detail": {
    "code": "permission_error",
    "message": "Developer project is archived."
  }
}

Usage, cost, and status semantics

The console exposes product telemetry. Treat estimated cost and fallback token counts as operational signals, not billing-grade accounting.

Usage notes

estimated_cost_usd is a product estimate, not a billing ledger.
Current requests are checked for API-key validity before execution, then usage is recorded after the request completes or fails.
Each successful Web Search is recorded as a separate web_search usage event with its current estimated Brave cost of $0.005.
Per-key Web Search rate and monthly allowances are enforced before the provider call, but they are not a substitute for future invoice-grade credit enforcement.
A configured per-key spend limit is enforced before a later request after completed successful estimated usage has reached that key's limit. It applies to chat, images, Web Search, and realtime-session issuance.
Because there is no balance gate today, a request that would take an account from positive estimated spend to zero is not stopped mid-answer by platform billing.
The platform does not currently return an insufficient-credit or payment-required error for zero balance.
If direct provider token usage is unavailable, the platform falls back to a simple text-length token estimate.
Latency comes from response metadata when available and falls back to wall-clock request timing otherwise.
Developers can rely on usage events for product telemetry and rough comparisons, but not as invoice-grade accounting.

Status definitions

TypeValueMeaning
API keyactiveThe key is currently usable.
API keyrevokedThe key was manually revoked and can no longer authenticate.
API keyexpiredThe key expiry time has passed.
UsageokThe request completed successfully.
UsageerrorThe request failed because of a backend or provider-side failure.
UsagerejectedThe request failed with a non-rate-limit client error.
Usagerate_limitedThe request failed because of rate limiting.

Documentation status and support

Use this page as the current in-sidebar reference for the documented Platform data-plane behavior.

Current API version: /api/platform/v1. This sidebar page is the user-facing reference for the supported data-plane routes in this workspace.
The console-management routes require a signed-in administrator and are not customer-facing data-plane routes. They remain subject to the backend ownership limitation described above.
There is no separate changelog, SDK, generated OpenAPI document, or published deprecation window today. Keep integrations defensive and re-check this page when changing versions or providers.
For help with a current workspace issue, use Support or Report a bug from the sidebar profile menu and include the request_id from any failed API response.