API reference

Chat completions

POST/api/v1/chat/completions is the primary endpoint, and /v1/chat/completions is the same endpoint under the prefix most SDKs append for you. OpenAI-compatible request and response shapes.

Request

json
{
  "model": "deepseek/deepseek-v4-pro",
  "messages": [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "Summarise this contract."}
  ],
  "temperature": 0.7,
  "max_tokens": 1024,
  "stream": false
}

Parameters

FieldTypeNotes
modelstringAny model ID from the catalogue, e.g. deepseek/deepseek-v4-pro. Omit it (and models) to use your workspace's default model
modelsarrayOrdered fallback list. Each model is tried in turn until one answers. Sent with model, model is tried first
presetstringA preset slug from your workspace. Its model and settings apply to the request
providerobjectRouting preferences: order, only, ignore, allow_fallbacks, sort ("price", "latency" or "throughput") and require_parameters. Any other key is 400 unsupported_parameter. See Provider routing
messagesarray, requiredOpenAI message format: system, user, assistant, tool
temperaturenumber0–2. Omit it and the provider's own default stands. A route that refuses it does not receive it; see Sampling fields a route refuses
max_tokensintegerCap on output tokens, reasoning included. max_completion_tokens is the same cap under the OpenAI name; send either. A few models return one or two tokens over it (65 or 66 for a cap of 64). A thinking model can spend a small cap on reasoning and return empty content; see Thinking and max_tokens for the caps to use, the admission hold and what is billed
streambooleanServer-sent events. See Streaming
stream_optionsobjectThe final usage chunk is sent by default; {"include_usage": false} turns it off
toolsarrayFunction-calling definitions. See Tool calling

The request body accepts extension fields, but forwarding and validation depend on the selected route. Native adapters translate messages, tools and model-specific controls; unsupported fields may be refused or reported in X-TokenHub-Ignored-Fields. AI Hub adjusts what the route needs: it renames max_tokens or max_completion_tokens to the one the provider accepts, drops a thinking switch that an always-thinking model would refuse, and asks the provider for usage on a stream. Unless a preset supplies one, it never adds a sampling parameter such as temperature. With neither model nor models and no workspace default, the request is 400 invalid_request.

Sampling fields a route refuses

AI Hub tracks seven sampling fields: temperature, top_p, top_k, frequency_penalty, presence_penalty, seed and stop. Some routes refuse one of them. For example, some reasoning models refuse a temperature or top_p other than 1 on most routes. When the route about to serve a request is recorded as refusing a field you sent, AI Hub removes that field, whatever its value, from the request it sends to that route, and the call succeeds. The decision is made per route: a fallback route that accepts the field still receives it.

The X-TokenHub-Ignored-Fields response header names the removed fields, comma-separated, for example temperature,top_p. It describes the route that served the response, and it is sent on JSON and streamed responses. When nothing was removed, the header is absent.

To refuse the request rather than lose a field, send "provider": {"require_parameters": true}. AI Hub then skips the routes that refuse a field you sent, and answers 400 unsupported_parameter when no route is left. See Provider routing.

In the model catalogue, supported_parameters lists one of these fields only when every route that serves the model has been tested and accepted it.

For image, audio, PDF and video content parts, see Multimodal inputs. Chat Completions, Messages and Responses have different input boundaries.

Uploaded video in chat

To send a large MP4 or MOV, first upload the file in this workspace. Put its ID in a video_url content part as tokenhub://files/<file_id>. Use the object form shown below; a string-valued video_url is not a file reference. The file must still be uploaded and unexpired. A missing or foreign file is refused before the provider call.

json
{
  "model": "qwen/qwen3.8-omni-flash",
  "messages": [{
    "role": "user",
    "content": [
      {"type": "text", "text": "Find the key moments in this video."},
      {"type": "video_url", "video_url": {"url": "tokenhub://files/file_…"}}
    ]
  }]
}

Response

json
{
  "id": "chatcmpl-8c1f0e2a",
  "object": "chat.completion",
  "created": 1788393600,
  "model": "deepseek/deepseek-v4-pro",
  "choices": [{
    "index": 0,
    "message": {"role": "assistant", "content": "..."},
    "finish_reason": "stop"
  }],
  "usage": {
    "prompt_tokens": 412,
    "completion_tokens": 186,
    "total_tokens": 598
  }
}

id is the provider's own response id, passed through. AI Hub's id for the request is the X-Generation-Id header, and it is the id your Activity log shows. model is the catalogue ID of the model that actually served the request, which may not be the first candidate when a fallback list was sent.

The usage object is authoritative for the tokens a request consumed, and carries token counts only — there is no cost field on this endpoint. Cost is derived from those counts and appears in your Activity log as cost_usd, a decimal string in USD.

Reasoning models and max_tokens

A reasoning (“thinking”) model counts its reasoning tokens inside max_tokens. When the cap is low, reasoning can use all of it and the response returns empty content with finish_reason: "length". On production on 2026-10-23, z-ai/glm-5.3 with max_tokens: 1000 returned empty content.

  • Set max_tokens above what the model reasons, or omit it. Thinking and max_tokens lists which models think, the switch and effort fields for each, recommended minimum caps, the admission hold and how reasoning streams.
  • To lower the reasoning, send the model's switch or effort field, for example "reasoning_effort": "low" on z-ai/glm-5.3 or "enable_thinking": false on qwen/qwen3.8-max.
  • For long answers, set stream: true. A non-streamed call waits for the whole answer before the first byte. See Streaming.

Response headers

HeaderValue
X-Generation-IdAI Hub's request id, req_ plus 26 characters. Sent on errors too, so quote it when you contact support
X-Provider-NameThe provider that served the response
X-TokenHub-Ignored-FieldsThe request fields the serving route did not receive, comma-separated, such as temperature,top_p. Absent when every field was forwarded
X-TokenHub-Credential-Sourceshared when AI Hub's provider account paid, byok when your workspace's own provider key did
X-RateLimit-*-Requests, X-RateLimit-*-TokensThe key's rate limits, when it has any. See Rate limits & caps

Support and limits

Send the exact model ID and messages. A model's context length, output cap, tools and structured formats are in its supported_parameters on the model card. Streaming uses Chat SSE; see Streaming.

Gateway validation, defaults and response forms are in the operation index and the OpenAPI schemas.

Error codes and recovery are in Errors and recovery. Keep the request or job ID from each response: it identifies the call in Activity and for support.