Internalize / Docs
API reference

Chat Completions

OpenAI-compatible text and function calls, backed by durable inference jobs.

View as Markdown

POST /v1/chat/completions requires inference scope. The same rate, reservations, adapter ownership checks, and settlement rules apply as native inference.

Customer scope

Supply optional tenant_id in the body or X-Internalize-Tenant in the headers. If both are present they must match. A tenant-restricted key supplies its own tenant when omitted and rejects another tenant. Without either, an unrestricted key uses the separate project namespace. Use the same tenant for learning, inference, job reads, and version changes. See Serve multiple customers.

Request

{
  "model": "glm-5.3",
  "messages": [{ "role": "user", "content": "Hello!" }],
  "max_completion_tokens": 2048,
  "temperature": 0,
  "stream": false
}
FieldBehavior
modelRequired; glm-5.3 only
messages1–64 messages; text, assistant function calls, and completed tool-result turns
subject_idOptional; routes through that subject's active adapter
adapter_versionOptional retained version, or base; non-base pinning requires a subject
max_completion_tokens1–4,096, default 2,048; includes reasoning
max_tokensLegacy alias; do not send both limits
temperature0–1, default 0
toolsUp to 32 function definitions with unique names
tool_choiceauto, none, required, or a named function
parallel_tool_callsBoolean; false permits at most one returned call
response_formattext or json_object; JSON is validated after generation
streamFalse by default; true returns buffered SSE
stream_options.include_usageAdds a final usage chunk when streaming
nOnly 1 is supported

Unknown fields are rejected. strict: true tools, json_schema, images, audio, logprobs, and Responses-specific fields are unsupported. JSON validation is not constrained decoding; invalid JSON can yield a failed job with consumed inference tokens charged.

Each message's normalized text is bounded to 16,000 JavaScript string-length units. Serialized normalized messages plus tools must fit 64,000 units. The HTTP body limit is 100,000 bytes. Function argument strings have a 16,000-unit bound. The actual tokenizer context ceiling is also enforced before paid execution.

Routing

Omitting the subject always selects base, even if the project's default subject has learned versions. Use subject_id or X-Internalize-Subject for adapted inference. If both appear, their values must match. A missing or expired explicitly requested adapter fails; it does not silently fall back.

The subject comes from your server's authorization mapping. A key is project-scoped and can optionally be restricted to a tenant; it is not restricted to one subject. Pinned versions must belong to the key’s project, the selected tenant, and the supplied subject.

Conversation and tools

system, developer, user, assistant, and tool roles are accepted. Developer messages normalize to system messages. Content may be a string or an array of text blocks. Null assistant content is accepted when function calls are present.

Assistant calls need unique IDs and JSON-object argument strings. Every call must receive exactly one matching tool result before the next assistant generation. The final message must be a user message or the end of a completed tool-result block. The server emits function calls; your runtime authorizes and executes them.

Response

A successful JSON response includes the standard id, object, created, model, choices, and usage fields. choices[0].message contains final text, tool_calls, or both. finish_reason is stop, length, or tool_calls.

The internalize extension contains job_id, subject_id, and the resolved adapter_version. Response headers include X-Internalize-Job-Id, Idempotency-Key, and X-Request-Id. Inference usage includes all generated reasoning tokens, but reasoning text is never returned.

Stream behavior

SSE sends keepalive comments while the durable job runs. After validation it emits a content/tool delta, a finish chunk, optional usage, and [DONE]. Tool deltas include their index, ID, function name, and complete argument string.

This stream is buffered until final validation, not token-live generation. Disconnecting or cancelling the client stream does not cancel the underlying job. The same job remains visible in Activity and through /v1/jobs/{id}.

Recovery and deadlines

A supplied Idempotency-Key is strongly recommended for paid operations. Reusing it with the same normalized payload and submitting credential returns the original job. A conflicting body or another key returns 409. If omitted, the gateway generates an operation key and returns it in the response header.

The HTTP wait is bounded to about four minutes. A pending, failed, or reconciliation result after admission uses 409 and includes error.job_id, error.status_url, and retryable: false. Poll that existing job. A stream already admitted reports the same error envelope in a data frame before [DONE].

Disable automatic framework retries unless they reuse a persisted operation key. If a connection fails before you save the generated key or job ID, a fresh request may create new paid work. Use native asynchronous inference when your application needs a job receipt immediately.

On this page