glm-5.2
GLM-5.2 — Z.AI's open-weight flagship for long-horizon coding. OpenAI-compatible /v1/chat/completions on api.reapi.ai with a 1M-token lossless context window, 128K max output, thinking that can be switched off, and a reasoning-effort dial no other GLM model takes.
Z.AI's GLM-5.2 — a flagship foundation model built for long-horizon tasks —
exposed through api.reapi.ai as a drop-in OpenAI-compatible Chat Completions
endpoint. A 1M-token context window Z.AI describes as solid and lossless,
128K max output, thinking on by default but switchable off, a
reasoning_effort dial that no other model in the GLM family accepts, genuinely
tunable temperature / top_p, function calling with streamed tool arguments,
JSON mode and context caching. Text in, text out. The wire model id is
glm-5.2 — with the dot. Current rates live on the
model page and on
api.reapi.ai/pricing.
The URL and the model id differ. This page and the model page spell the slug
glm-5-2 because a URL cannot carry the dot. The string your request body needs
is glm-5.2. Sending glm-5-2 as the model is the first thing to check on an
unknown-model error.
Quick example
curl https://api.reapi.ai/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "glm-5.2",
"messages": [
{ "role": "user", "content": "Refactor this module and add tests." }
],
"thinking": { "type": "enabled" },
"reasoning_effort": "max",
"max_tokens": 8192,
"stream": true
}'from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.reapi.ai/v1",
)
stream = client.chat.completions.create(
model="glm-5.2",
messages=[{"role": "user", "content": "Refactor this module and add tests."}],
max_tokens=8192,
stream=True,
extra_body={
"thinking": {"type": "enabled"},
"reasoning_effort": "max",
},
)
for chunk in stream:
delta = chunk.choices[0].delta
reasoning = getattr(delta, "reasoning_content", None)
if reasoning:
print(reasoning, end="")
if delta.content:
print(delta.content, end="")import OpenAI from "openai";
const client = new OpenAI({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.reapi.ai/v1",
});
const stream = await client.chat.completions.create({
model: "glm-5.2",
messages: [{ role: "user", content: "Refactor this module and add tests." }],
max_tokens: 8192,
stream: true,
// @ts-expect-error vendor-specific fields pass through
thinking: { type: "enabled" },
reasoning_effort: "max",
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
body, _ := json.Marshal(map[string]any{
"model": "glm-5.2",
"messages": []map[string]string{
{"role": "user", "content": "Refactor this module and add tests."},
},
"thinking": map[string]string{"type": "enabled"},
"reasoning_effort": "max",
"max_tokens": 8192,
})
req, _ := http.NewRequest("POST",
"https://api.reapi.ai/v1/chat/completions", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(string(out))
}Authentication
Chat models are served from the api.reapi.ai gateway, which has its own console
and its own key. Create the key there, then send it as a bearer token:
Authorization: Bearer YOUR_API_KEYThe gateway key is not the same credential as a media-generation key used
against reapi.ai/api/v1. Sign in at
api.reapi.ai to create one.
Endpoint
POST /v1/chat/completionsBase URL https://api.reapi.ai. The wire format is OpenAI-compatible, so the
same SDKs (openai-python, openai-node, openai-go, …) work once you swap the
base URL, the key and the model string. Vendor-specific fields such as thinking
go through the SDK's pass-through mechanism — extra_body in Python.
Request body
model — string, required
Must be glm-5.2 exactly, dot included.
messages — array, required
Conversation history, each entry an object with role and content. Roles are
system, user, assistant and tool. Text only — see
Modality.
max_tokens — integer
Upper bound on output tokens for this response. This model supports a 128K maximum output and the schema accepts values up to 131,072. Reasoning is generated before the answer and draws on the same allowance.
stream — boolean, default false
When true, tokens arrive as server-sent events terminated by data: [DONE].
Reasoning and answer arrive as separate deltas — reasoning_content and
content.
thinking — object, default {"type": "enabled"}
Chain-of-thought control. See Reasoning.
reasoning_effort — string, default "max"
How hard the model thinks; applies only while thinking is enabled. See Reasoning for the value-collapsing behaviour, which is the one surprise on this model.
temperature / top_p — numbers
Actually tunable here. See Sampling parameters.
tools / tool_choice / tool_stream — optional
Function definitions, selection strategy and streamed arguments. See Tool calling.
response_format — object, optional
{"type": "text"} (default) or {"type": "json_object"}. See
Structured output.
stop — array, optional
Stop words. Only one is supported despite the array shape.
group — string, default "default"
Token group on the gateway. Leave it at default unless your account has been
given another group to route through.
Reasoning
Two things are unusual here, and both cut in the developer's favour.
1. Thinking is on by default, and can be turned off. thinking defaults to
{"type": "enabled"}, and {"type": "disabled"} is accepted — a switch several
models in this class no longer offer.
2. With thinking on, the model decides per request whether to think. Z.AI contrasts this explicitly with the previous generation, which reasoned unconditionally. Leaving thinking enabled therefore does not mean paying for reasoning on every trivial turn.
The effort ladder collapses
reasoning_effort accepts seven values for cross-provider compatibility, but they
map onto three behaviours:
| You send | What actually happens |
|---|---|
max | Default. Deep reasoning. |
xhigh | Mapped to max. |
high | Enhanced reasoning — the real middle setting. |
medium | Mapped to high. |
low | Mapped to high. |
minimal | Skips thinking. |
none | Skips thinking. |
A middling value does not buy a middling cost. low and medium both behave
as high, so a client that drops to low expecting a cheap pass gets the same
work as high. The only ways down are high, or skipping thinking entirely with
minimal / none.
Prior-turn reasoning is dropped by default
thinking.clear_thinking defaults to true: the model ignores
reasoning_content from earlier turns and keeps only visible text, tool calls and
tool results. That keeps multi-turn context short and cheap, and it is why this
model needs no special history handling out of the box.
Set it to false for Preserved Thinking — and then the full, unmodified,
correctly ordered reasoning_content history must be forwarded. Missing,
truncated, rewritten or reordered blocks degrade the result.
Sampling parameters
Unlike several open-weight peers that pin these, both work:
| Parameter | Range | Default |
|---|---|---|
temperature | 0.0 – 1.0 | 1.0 |
top_p | 0.01 – 1.0 | 0.95 |
temperature is capped at 1.0. Code carried over from a provider that allows
up to 2.0 will be rejected. Z.AI also advises tuning one of the two rather
than both — temperature for creative latitude, top_p for convergence.
A separate do_sample flag defaults to true; setting it false makes both
sampling parameters stop taking effect.
Tool calling
toolsaccepts up to 128 functions.tool_choiceacceptsautoonly — the model decides when a call is warranted. There is norequiredor per-function forcing on this model.tool_stream: truestreams tool-call arguments as they are generated instead of delivering the complete call at once. Concatenatedelta.tool_calls[*].function.argumentsacross chunks.
After executing calls, append one tool message per call with the matching
tool_call_id before asking for the next completion.
Structured output
{ "response_format": { "type": "json_object" } }This is JSON mode, not JSON Schema — you do not supply a schema and the model does not validate against one. Ask for the shape you want in the prompt as well, which Z.AI recommends explicitly. If you need schema-guaranteed fields, validate on your side after parsing.
Modality
| Modality | Supported |
|---|---|
| Text in | ✅ |
| Text out | ✅ |
| Image in | ❌ |
| Video in | ❌ |
Z.AI's model card lists input and output modalities for this model as text. Vision is a different model in their lineup. If a step in your workflow needs a screenshot read, route that step elsewhere — this model is a strong choice for the code around it, not for looking at it.
Context caching
Caching is part of this model's capability set and rewards the obvious shape: keep a long stable prefix — system prompt, knowledge document, tool definitions — in front of a changing question, and let repeat requests reuse it. No cache id and no TTL to manage.
Z.AI prices cached input as its own dimension. reAPI does not publish a separate cached-input rate for this model, so treat caching as a latency and context-length benefit here, and bill against the input and output rates in the pricing table.
Pricing dimensions
Billing is per token, in USD, against your api.reapi.ai balance, with
separate input and output rates. Three things to keep in mind:
- Reasoning tokens bill as output. Thinking is on by default at the deepest effort setting, which is the usual reason a bill exceeds an estimate built from visible answer length.
- Effort is the first lever. Because the ladder collapses, the meaningful
choices are deep (
max), enhanced (high) or none at all. - Output dominates. For most generative workloads the output rate decides the invoice.
Both token rates sit at about a third below Z.AI's published per-token rate. Current numbers are on the model page and api.reapi.ai/pricing — those tables are the canonical source, not this page.
Chat models bill in USD on the gateway balance. They do not draw down the
integer credits used by the media-generation endpoints on reapi.ai/api/v1.
Response shape
Non-streaming (stream: false)
{
"id": "chatcmpl-...",
"object": "chat.completion",
"created": 1785000000,
"model": "glm-5.2",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"reasoning_content": "...",
"content": "..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 1204,
"completion_tokens": 860,
"total_tokens": 2064
}
}reasoning_content is a sibling of content. Unless you have turned off
clear_thinking, you do not need to send it back.
Streaming (stream: true)
Server-sent events, each data: line carrying a chat.completion.chunk.
Reasoning arrives in choices[0].delta.reasoning_content and the answer in
choices[0].delta.content, terminated by data: [DONE].
Errors
Failures use the gateway's standard envelope. See the errors catalog for the full code list. Common cases:
| Trigger | What to do |
|---|---|
| Missing or invalid bearer token | Create a key in the api.reapi.ai console |
Unknown model value | Send glm-5.2 with the dot — not the hyphenated slug |
temperature above 1.0 | Lower it; the ceiling is 1.0 on this model |
tool_choice set to required or a named function | Only auto is supported |
An image part in messages | Not a multimodal model — route vision elsewhere |
More than one entry in stop | Only one stop word is supported |
max_tokens above the ceiling | Lower it; the documented ceiling is 131,072 |
reasoning_effort sent with thinking disabled | It only takes effect while thinking is enabled |
| Insufficient balance | Top up on the gateway |
| Upstream rate limit | Retry with backoff, or route through another model |
Tips
- Send the whole project, then ask for the audit first. Z.AI's own recommended opening move is an architecture map, module responsibilities, API contracts, data flows and technical debt — before any edit.
- Bound long tasks explicitly. State what must not change (business logic, API signatures, runtime behaviour) and ask for the plan, impact scope, risk boundaries and verification method up front.
- Give it your real engineering standards. Lint rules, build commands, test requirements, commit conventions and prohibited actions belong in the prompt; adherence under long context is what this generation improved.
- Pick an effort behaviour, not a number. Deep, enhanced, or none — the values in between are aliases.
- Mind the
temperatureceiling of 1.0, and tune one sampling parameter rather than both. - Stream anything interactive, and render
reasoning_contentseparately from the answer rather than concatenating them. - Front-load the stable bulk of your prompt so caching can do its job.
Related
- GLM-5.2 model page — current rates
- Kimi K3 — the other open-weight 1M-context coding flagship
- Errors catalog
- Authentication
- Quickstart