Authenticating...

Chat Completions API

Copy Page as Markdown

Use the Chat Completions API to generate a response from SubQ for a list of conversation messages. For server-managed multi-turn conversations with system instructions and built-in web search, see Responses API.

POST /v1/chat/completions

All requests must include a valid API key in the Authorization header. See Authentication for details.

Request body

Send a JSON object with the required model and messages fields. Omit optional fields unless you need to change generation behavior.

FieldTypeRequiredDescription
modelstringYesModel ID to use, such as subq-preview. See Models.
messagesarrayYesConversation messages in order. Must contain at least one message.
streambooleanNoWhen false or omitted, returns one JSON response. When true, returns server-sent events.
temperaturenumberNoSampling temperature from 0 to 2. Higher values make output more random.
max_tokensintegerNoCaps generated tokens. Must be at least 1. See Token limits.
top_pnumberNoNucleus sampling value from 0 to 1. Use this or temperature, not both, for most requests.
stopstring or string[]NoStop sequence or sequences where generation should stop.
reasoning_effortstringNoHow much internal reasoning the model should use before answering. See Reasoning effort.
response_formatobjectNoConstrain the assistant reply to a JSON Schema. See Structured outputs.
toolsarrayNoFunction tools the model may call. See Function calling.
tool_choicestring or objectNoControl whether and which tools the model may call ("auto", "required", "none", or a specific function).

This page documents the non-streaming response. For a non-streaming request, omit stream or set it to false.

Token limits

max_tokens caps the tokens generated in the completion. It is a spending limit, not a response-length limit.

  • Applies only to generated output—not the prompt.
  • Reasoning is part of that output. Unless reasoning_effort is none, the model reasons before answering from the same allowance, so a request can return 200 OK with an empty content and finish_reason of "length"—billed, with nothing visible. A larger max_tokens makes this less likely but does not rule it out; reasoning_effort of none does.
  • Input and output share the same context window. If max_tokens plus the input cannot fit, the API returns 400 with code context_length_exceeded. Do not set max_tokens to the full window.
  • Use this parameter exclusively; do not send max_completion_tokens.
  • If set, the minimum value is 1. If omitted, the response can use all remaining context space.
  • If generation hits the cap, choices[0].finish_reason is "length".
{
  "model": "subq-preview",
  "messages": [
    {
      "role": "user",
      "content": "In three bullets, explain the difference between indemnification, limitation of liability, and insurance requirements in a software contract."
    }
  ],
  "max_tokens": 500
}
cURLNode.jsTypeScriptPython

Reasoning effort

Set top-level reasoning_effort to control how much internal reasoning the model uses before it answers. Possible values are none, low, medium, high, and max. Which values are accepted, and what the default is when you omit the field, depends on the model.

  • Reasoning tokens are billed as output tokens. They are included in usage.completion_tokens and counted in max_tokens. A one-word classification can bill dozens of times more with reasoning enabled than without.
  • There is no bounded default. Omitting reasoning_effort does not mean light reasoning—the model may reason at length. Set it explicitly on any request with a latency or cost ceiling.

Only none gives a guarantee: zero reasoning tokens and a null reasoning_content, even when max_tokens is set.

{
  "model": "subq-preview",
  "messages": [
    {
      "role": "user",
      "content": "Classify this transaction dispute into exactly one category: [FRAUD, BILLING, LOAN, TECHNICAL]. Return only the category name.\n\nTicket: 'I see a charge of $45.22 from a gas station in Ohio, but I live in California and haven't traveled all year. Please cancel my card!'"
    }
  ],
  "reasoning_effort": "none"
}
cURLNode.jsTypeScriptPython

Choosing a value

Effort selects a reasoning strategy, not a token budget: higher effort does not reliably mean more tokens, and the relationship differs by prompt and by model version. Benchmark the candidates on your own prompts rather than assuming an ordering.

WorkloadSuggested effort
Classification, routing, extraction, short answersnone
Open-ended analysis and multi-step workmedium or high; compare both
Tight max_tokensnone, or expect empty content

Messages

Each message has a role and content.

FieldTypeRequiredDescription
rolestringYesOne of system, user, assistant, or tool.
contentstring or content part[]YesMessage text as a plain string, or an array of content parts.

Use system for durable instructions, user for user input, assistant for prior model responses (including messages that contain tool_calls), and tool for tool result messages already produced by your application. See Function calling.

The simplest content shape is a string:

{
  "role": "user",
  "content": "Summarize this release note."
}

You can also send text content parts:

{
  "role": "user",
  "content": [
    { "type": "text", "text": "Summarize this release note." }
  ]
}

For document input, send a text instruction and one or more file parts in the same user message:

{
  "role": "user",
  "content": [
    { "type": "text", "text": "Summarize these documents." },
    {
      "type": "file",
      "filename": "financial-report-2026.pdf",
      "mime_type": "application/pdf",
      "file_data": "JVBERi0xLjcKJdDUxdgK..."
    },
    {
      "type": "file",
      "filename": "meeting-notes.txt",
      "mime_type": "text/plain",
      "file_data": "U3ViUSBkb2N1bWVudCBub3Rlcy4uLg=="
    }
  ]
}

Document file parts accept inline base64 (file_data) or an uploaded file_id. Image, audio, video, URL-based file inputs, and other content part types are rejected. See Sending files for file part examples. For the Responses API, use input_file with file_id instead — see Uploaded files.

Request examples

Use cURL for direct HTTP calls, or use the official OpenAI SDK with SubQ's base URL.

cURLNode.jsTypeScriptPython

Response

A non-streaming request returns a JSON object with the OpenAI-compatible chat completion shape.

{
  "id": "chatcmpl-e1395060-5a57-4182-a833-c5a208137f70",
  "object": "chat.completion",
  "created": 1784314379,
  "model": "subq-preview",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "*   **Indemnification** is a contractual obligation where one party agrees to compensate the other for losses, damages, or legal costs arising from third-party claims (such as intellectual property infringement or data breaches), effectively shifting the financial risk of those specific external liabilities to the responsible party.\n*   **Limitation of Liability** caps the maximum amount of damages one party can be forced to pay the other for breach of contract or negligence, often excluding consequential or indirect damages, thereby protecting both sides from catastrophic financial exposure beyond a predefined threshold (e.g., fees paid in the prior 12 months).\n*   **Insurance Requirements** mandate that one or both parties maintain specific types and minimum amounts of insurance coverage (such as general liability, professional liability, or cyber insurance) to ensure there are financial resources available to cover potential claims, serving as a verification of financial capacity rather than a direct transfer of risk between the contracting parties."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 110,
    "completion_tokens": 188,
    "total_tokens": 298
  }
}

Response fields

FieldTypeDescription
idstringUnique completion ID.
objectstringObject type. Non-streaming responses use chat.completion.
createdintegerUnix timestamp, in seconds, for when the completion was created.
modelstringModel ID used for the completion.
choicesarrayGenerated choices. SubQ returns at least one choice for a successful request.
usageobjectToken usage for the request.

Choice fields

FieldTypeDescription
indexintegerChoice index.
message.rolestringRole of the returned message, usually assistant.
message.contentstringGenerated text. May be null when the model returns tool calls, and an empty string when max_tokens was consumed before the answer began—see Token limits.
message.reasoning_contentstringThe model's internal reasoning for this turn, when reasoning is enabled. null when reasoning_effort is none. Treat it as diagnostic output: do not parse it or show it to end users.
message.tool_callsarrayPresent when the model requests function calls. See Function calling.
finish_reasonstringReason generation stopped. Common values include stop, length (hit max_tokens or the remaining window), and tool_calls. Handle unknown string values defensively.

Usage fields

FieldTypeDescription
prompt_tokensintegerTokens counted from the request messages.
completion_tokensintegerTokens generated in the response, including any reasoning tokens. Billed at the output rate.
reasoning_tokensintegerOf those generated tokens, how many were internal reasoning. 0 when reasoning_effort is none.
total_tokensintegerSum of prompt and completion tokens.

The two counters are reported independently—on a truncated response reasoning_tokens can exceed completion_tokens—so test message.content rather than subtracting them.