Skip to content

Model catalog and calls ​

An open agent can list models actually available to the current Personal or Team context, then call the Xiaoya gateway. Provider credentials, upstream URLs, and internal routes are never returned.

Personal catalog ​

http
GET /api/v1/open/models
Authorization: Bearer <personal-access-token>

The token needs the model scope. Entries include a stable modelCode, display name, model type, input/output capabilities, parameter-schema version, and parameterSpec.

json
{
  "success": true,
  "data": [{
    "modelCode": "othan-2.0",
    "displayName": "Othan 2.0",
    "modelType": "chat",
    "inputsText": true,
    "inputsImage": true,
    "outputsText": true,
    "structuredOutputMode": "prompt",
    "outputsImage": false,
    "parameterSchemaVersion": 1,
    "parameterSpec": { "temperature": { "type": "number", "minimum": 0, "maximum": 2 } }
  }],
  "request_id": "req_01"
}

Structured JSON output capability ​

The structuredOutputMode field in Personal and Team catalog entries declares the available text output mode:

ValueRequest behavior
promptDescribe the JSON format in the prompt without requesting a native response_format.
json_objectSend response_format: { "type": "json_object" } to request a JSON object.
json_schemaSend response_format.type: "json_schema" with a JSON Schema; json_object is also supported.

The default is prompt. Treat a missing field in older catalogs as prompt as well. Do not infer native JSON support from the legacy supportsJson flag or a model name. This additive field preserves the meaning of existing capability and parameter fields. Callers must still parse the response and validate their business schema.

TTS gateway ​

The same model scope can list available TTS configurations and voices, then synthesize audio:

http
GET /api/proxy/v1/tts/options
Authorization: Bearer <access-token>

Read the catalog first and let the user explicitly choose ttsConfigId and one of its voices[].voiceId values. Models do not fix a voice: the compatibility field defaultVoiceId is an empty string, not an instruction to select the first candidate. Voice IDs are opaque and may contain spaces or parentheses. An empty voice library does not hide an enabled model with an active price and output formats: retain its management/cloning link, but require a valid voice before generation.

The catalog is scoped to the trusted Personal/Team context and contains shared voices plus voices available to that account. Public-sponsored sessions can use shared voices only. The voice fields shared, state, activationPoints, and expiresAt describe ownership, lifecycle, and the pending first-use cost/deadline. Reload the catalog when the account or Team changes; never reuse another space's voice cache. channelId identifies same-channel compatibility, not authorization.

In ordinary account contexts, voiceLibraryUrl links to the personal/Team voice library; it is null for public-sponsored sessions. Users create, rename, delete, or explicitly pay to preview voices through that portal's existing browser sign-in, not an OAuth voice-management API. New clones must be formally used within the displayed seven-day deadline. Creation does not charge points or implicitly synthesize a preview. The first synthesis or explicit paid preview reserves and settles the creation-time cloning tariff together with synthesis; after activation, other models on the same channel do not charge that cloning tariff again. Show the cost before execution and do not present an explicit preview as a free test.

http
POST /api/proxy/v1/audio/speech
Authorization: Bearer <access-token>
X-Request-ID: <stable-request-id>
Content-Type: application/json

{
  "tts_config_id": "<ttsConfigId>",
  "voice": "<voiceId>",
  "input": "Text to synthesize",
  "response_format": "mp3",
  "speed": 1.0
}

input must contain 1–9,999 characters and cannot be all whitespace. Choose a format from the model's current outputFormats. Additional optional parameters are volume, pitch, emotion, sample_rate, bitrate, audio_channel, language_boost, text_normalization, and latex_read. See TtsSpeechInput in the complete API reference for types, ranges, and enums; do not pass through undeclared provider parameters.

X-Request-ID is required for every billable request. A successful response contains binary audio in the selected format and always sets Cache-Control: no-store. Read these response headers:

HeaderMeaning
X-Xiaoya-Request-IdRequest ID confirmed by the platform for idempotency
X-Xiaoya-Tts-Config-Id / X-Xiaoya-Voice-IdXiaoya TTS configuration and voice actually used
X-Xiaoya-Input-Characters / X-Xiaoya-Usage-CharactersAccepted input characters and provider-confirmed settlement characters
X-Xiaoya-Actual-Usage / X-Xiaoya-Audio-Duration-MsActual pricing units and generated audio duration
X-Xiaoya-Charged-PointsTotal points finally charged, including any first-use cloning tariff settled by this request

Retries within the same account context must reuse the same X-Request-ID. If the provider outcome is unknown, the platform keeps the reservation for reconciliation and the caller must not retry under a new ID. TTS_VOICE_ACTIVATION_IN_PROGRESS prevents another request from activating a voice while its first use is unconfirmed; do not promise a refund or encourage resubmission. Persist successful audio in your application: a settled retry returns TTS_REQUEST_ALREADY_SETTLED rather than synthesizing again. Public options never expose provider credentials, upstream model names, or internal URLs.

Team catalog ​

http
GET /api/v1/open/teams/<team-id>/models
Authorization: Bearer <team-access-token>

The response also contains the Team context version, plan version, catalog version, and model items. Invalidate cached catalogs when Team, role, membership, or entitlement context changes.

json
{
  "success": true,
  "data": {
    "teamId": "team_01",
    "teamContextVersion": 7,
    "planVersionId": "plan_version_03",
    "catalogVersion": "sha256:catalog-digest",
    "items": [{
      "modelCode": "othan-2.0",
      "displayName": "Othan 2.0",
      "modelType": "chat",
      "inputsText": true,
      "inputsImage": true,
      "outputsText": true,
      "structuredOutputMode": "prompt",
      "outputsImage": false,
      "parameterSchemaVersion": 1,
      "parameterSpec": {}
    }]
  },
  "request_id": "req_02"
}

Chat Completions gateway ​

http
POST /api/proxy/v1/chat/completions
Authorization: Bearer <access-token>
Content-Type: application/json

{
  "model": "<modelCode>",
  "messages": [{ "role": "user", "content": "Summarize this document." }],
  "stream": true
}

Personal OAuth calls may stream. Team OAuth calls currently require a complete trusted workflow context and non-streaming mode.

bash
curl 'https://claw.zhenhuiai.com/api/proxy/v1/chat/completions' \
  --header 'Authorization: Bearer <personal-access-token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "model":"othan-2.0",
    "messages":[{"role":"user","content":"Summarize this in three points"}],
    "stream":false
  }'
json
{
  "id": "chatcmpl_01",
  "object": "chat.completion",
  "created": 1788067200,
  "model": "othan-2.0",
  "choices": [{
    "index": 0,
    "message": { "role": "assistant", "content": "1. ...\n2. ...\n3. ..." },
    "finish_reason": "stop"
  }],
  "usage": { "prompt_tokens": 120, "completion_tokens": 48, "total_tokens": 168 }
}

Set stream to true for Personal SSE calls and read data: events through data: [DONE]. Handle transport failures, non-2xx JSON errors, and errors delivered in the stream.

json
{
  "success": false,
  "code": "OPEN_AGENT_SCOPE_REQUIRED",
  "message": "The model scope is required",
  "request_id": "req_error_01"
}
Call pathModel cost owner
Agent's own provider or gatewayAgent developer
Xiaoya gateway with a Personal tokenCurrent user balance
Xiaoya gateway with a Team tokenTeam shared wallet, constrained by member quota

The developer still owns application hosting, storage, and workflow costs.

See the complete API reference for every body field, header, and response schema.

OAuth credentials and model-provider secrets must remain on trusted servers.