API Documentation
Endpoint-by-endpoint reference for the X-Serve API.
Base URL
https://api.netpreme.com/v1
The API follows the OpenAI schema, so an OpenAI client works once you change the base URL and the key. Two other dialects are also served, described under their own endpoints below.
Authentication
Every request carries a bearer token:
Authorization: Bearer sk-...
Create keys under Settings > API Keys in the Console. The same key works on every endpoint
and every dialect. An x-api-key header isn't accepted, even on the Anthropic-compatible
endpoint.
Endpoints
| Method | Path | Dialect |
|---|---|---|
| POST | /v1/chat/completions |
OpenAI Chat Completions |
| POST | /v1/responses |
OpenAI Responses |
| POST | /v1/messages |
Anthropic Messages |
| POST | /v1/messages/count_tokens |
Anthropic Messages |
| GET | /v1/models |
Model discovery |
| GET | /v1/models/{model} |
Model discovery |
POST /v1/chat/completions
| Method | Syntax |
|---|---|
| POST | https://api.netpreme.com/v1/chat/completions |
Description
Generates a chat completion. This is the default endpoint and the one to use unless a client you already have expects one of the other dialects.
Parameters
| Name | Type | Req. | Description |
|---|---|---|---|
model |
string | Y | zai-org/GLM-5.2-FP8 or moonshotai/Kimi-K3. Case-sensitive. An unknown value returns 404. |
messages |
array | Y | Standard OpenAI message objects with role and content. |
stream |
boolean | N | When true, the reply arrives as server-sent events ending with data: [DONE]. |
reasoning_effort |
string | N | One of none, minimal, low, medium, high, xhigh, max. At none the model answers directly. At every other level it reasons first and returns that separately. An unrecognized value returns 400. Coverage differs by model. zai-org/GLM-5.2-FP8 serves none, high, and max. moonshotai/Kimi-K3 serves none, low, high, and max. The Console draws each model's ladder. Behavior on a level a model doesn't serve differs between the two: zai-org/GLM-5.2-FP8 accepts it and reasons anyway, and moonshotai/Kimi-K3 fails the request. Stay on the levels the model serves. |
max_tokens |
integer | N | Caps generated tokens. Reasoning counts against this budget. |
tools |
array | N | Function definitions the model may call. When the model chooses one, finish_reason is tool_calls and message.content is null. |
Other parameters in the OpenAI schema pass through to the model.
Request
curl https://api.netpreme.com/v1/chat/completions \
-H "Authorization: Bearer $NETPREME_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "zai-org/GLM-5.2-FP8",
"reasoning_effort": "none",
"max_tokens": 40,
"messages": [{"role": "user", "content": "Say hello in five words."}]
}'
Response
{
"id": "99a282d080092df7",
"object": "chat.completion",
"created": 1787244180,
"model": "zai-org/GLM-5.2-FP8",
"service_tier": null,
"system_fingerprint": null,
"choices": [
{
"index": 0,
"finish_reason": "stop",
"logprobs": null,
"message": {
"role": "assistant",
"content": "Hello, I am saying hello.",
"reasoning_content": null
}
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 8,
"total_tokens": 20,
"prompt_tokens_details": {"audio_tokens": null, "cached_tokens": 0}
}
}
message.reasoning_content holds the model's reasoning and is null when reasoning_effort is
none. usage.prompt_tokens_details.cached_tokens reports how many input tokens came from
cache, which matters because X-Serve prices cached input separately.
Tool calling
With tools in the request, the model can answer with a call instead of text. finish_reason
is tool_calls and message.content is null:
{
"finish_reason": "tool_calls",
"message": {
"role": "assistant",
"content": null,
"tool_calls": [{
"id": "chatcmpl-tool-a452b272a39007a4",
"type": "function",
"function": {"name": "get_weather", "arguments": "{\"city\": \"Paris\"}"}
}]
}
}
Run the function yourself, then send the conversation back with a tool message carrying the
result. tool_call_id matches the id from the previous response:
"messages": [
{"role": "user", "content": "What is the weather in Paris?"},
{"role": "assistant", "tool_calls": [{"id": "chatcmpl-tool-a452b272a39007a4", "type": "function",
"function": {"name": "get_weather", "arguments": "{\"city\": \"Paris\"}"}}]},
{"role": "tool", "tool_call_id": "chatcmpl-tool-a452b272a39007a4", "content": "18C, light rain"}
]
The next response carries finish_reason of stop and the answer written from your result.
Both models behave the same way. See Inference for the worked exchange.
POST /v1/responses
| Method | Syntax |
|---|---|
| POST | https://api.netpreme.com/v1/responses |
Description
The OpenAI Responses API. Use it when a client expects that shape. Codex does. The reasoning
arrives as an item of type reasoning in the output array rather than as a separate field,
and usage appears only in the terminal snapshot.
Request
curl https://api.netpreme.com/v1/responses \
-H "Authorization: Bearer $NETPREME_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "zai-org/GLM-5.2-FP8", "input": "say hi"}'
Response
Abridged, since the object carries the full Responses schema:
{
"id": "resp_8fa309b927b04b2285f5e8db89720a9f",
"object": "response",
"status": "completed",
"model": "zai-org/GLM-5.2-FP8",
"output": [
{"type": "reasoning", "status": "completed", "summary": [{"type": "summary_text", "text": "..."}]},
{"type": "message", "role": "assistant", "status": "completed",
"content": [{"type": "output_text", "text": "Hi there! How can I help you today?"}]}
],
"usage": {
"input_tokens": 14,
"output_tokens": 121,
"total_tokens": 135,
"input_tokens_details": {"cached_tokens": 0},
"output_tokens_details": {"reasoning_tokens": 0}
}
}
POST /v1/messages
| Method | Syntax |
|---|---|
| POST | https://api.netpreme.com/v1/messages |
Description
The Anthropic Messages API. Use it when a client expects that shape. Claude Code does.
max_tokens is mandatory here, and reasoning counts against it, so a small value can return a
thinking block with no answer.
Parameters
| Name | Type | Req. | Description |
|---|---|---|---|
model |
string | Y | zai-org/GLM-5.2-FP8 or moonshotai/Kimi-K3. |
max_tokens |
integer | Y | Mandatory in this dialect. Allow room for reasoning. |
messages |
array | Y | Anthropic message objects. |
Send anthropic-version: 2023-06-01 alongside the bearer token.
Request
curl https://api.netpreme.com/v1/messages \
-H "Authorization: Bearer $NETPREME_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "zai-org/GLM-5.2-FP8",
"max_tokens": 2048,
"messages": [{"role": "user", "content": "In one sentence, what can you help me with?"}]
}'
Response
{
"id": "msg_...",
"type": "message",
"role": "assistant",
"model": "zai-org/GLM-5.2-FP8",
"content": [
{"type": "thinking", "thinking": "..."},
{"type": "text", "text": "..."}
],
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {"input_tokens": 23, "output_tokens": 655}
}
POST /v1/messages/count_tokens
| Method | Syntax |
|---|---|
| POST | https://api.netpreme.com/v1/messages/count_tokens |
Description
Counts the input tokens a Messages request would consume, without generating anything.
Request
curl https://api.netpreme.com/v1/messages/count_tokens \
-H "Authorization: Bearer $NETPREME_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "zai-org/GLM-5.2-FP8",
"messages": [{"role": "user", "content": "Say hello in five words."}]
}'
Response
{"input_tokens": 9}
GET /v1/models
| Method | Syntax |
|---|---|
| GET | https://api.netpreme.com/v1/models |
Description
Lists the models your key can call.
Request
curl https://api.netpreme.com/v1/models \
-H "Authorization: Bearer $NETPREME_API_KEY"
Response
{
"object": "list",
"data": [
<!-- generated:model-list:start -->
{"id": "zai-org/GLM-5.2-FP8", "object": "model", "created": 0, "owned_by": "Netpreme"},
{"id": "zai-org/GLM-5.3", "object": "model", "created": 0, "owned_by": "Netpreme"},
{"id": "moonshotai/Kimi-K3", "object": "model", "created": 0, "owned_by": "Netpreme"}
<!-- generated:model-list:end -->
]
}
GET /v1/models/{model}
| Method | Syntax |
|---|---|
| GET | https://api.netpreme.com/v1/models/{model} |
Description
Returns one model by id.
Request
curl https://api.netpreme.com/v1/models/zai-org/GLM-5.2-FP8 \
-H "Authorization: Bearer $NETPREME_API_KEY"
Response
{"id": "zai-org/GLM-5.2-FP8", "object": "model", "created": 0, "owned_by": "Netpreme"}
Not supported
These parts of the OpenAI schema are reachable but do nothing today. Their errors don't say so plainly, which is why this page names them.
| Path | What happens |
|---|---|
POST /v1/embeddings |
Returns 404 Model not found for either model. X-Serve serves no embedding model. |
POST /v1/completions |
Returns 200, but the models are chat models and the output isn't usable. Use /v1/chat/completions. |
response_format |
Accepted on chat completions and ignored. Neither json_schema nor json_object constrains the reply: schema mode returns the same prose as a request without the parameter, and object mode returns JSON wrapped in a Markdown fence. Parse defensively or prompt for the shape you want. |
Errors
Errors use the shape of the dialect you called. These are the ones you are most likely to meet.
| Status | Example body | Cause |
|---|---|---|
| 400 | {"message":"Failed to deserialize the JSON body into the target type: unknown variant \bogus`, expected one of `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`","type":"Bad Request","code":400}` |
A parameter value outside the accepted set. The message names the whole set. |
| 401 | {"error":{"message":"Invalid or revoked API Key.","type":"invalid_api_key"}} |
The key is wrong, or someone revoked it. |
| 401 | {"error":{"message":"Missing API Key. Pass it in the Authorization header as \"Bearer sk-...\".","type":"invalid_api_key"}} |
No Authorization header, or an x-api-key header instead of a bearer token. |
| 404 | {"error":{"code":404,"message":"The model \zai-org/GLM-5.2-FP8-x` does not exist.","param":"model","type":"NotFoundError"}}| Unknown model id. The id carries no reasoning level, so usereasoning_effort` instead. |
|
| 409 | You can have a maximum of 5 active API Keys. Revoke an active Key before creating another. |
You already hold the most active keys allowed. |
| 429 | The API Key has exceeded its requests-per-minute limit. | Slow down or ask for a higher limit. |
X-Serve doesn't count requests that fail authentication against your usage, because it can't attribute them to an account.
Limits
| Limit | Default |
|---|---|
| Active API keys | 5 |
| API key name length | 40 characters |
| Requests per minute | 60 |
| Tokens per minute | 100,000 |
Each key carries its own rate limits, so yours may differ from the preceding defaults.
See also
- Quickstart to get a key and send a first request.
- Inference for streaming, reasoning control, and worked examples.
- Available Models for what each model accepts.
To read the list from the API:
curl https://api.netpreme.com/v1/models \
-H "Authorization: Bearer $NETPREME_API_KEY"
```json { "object": "list", "data": [
{"id": "zai-org/GLM-5.2-FP8", "object": "model", "created": 0, "owned_by": "Netpreme"},
{"id": "zai-org/GLM-5.3", "object": "model", "created": 0, "owned_by": "Netpreme"},
{"id": "moonshotai/Kimi-K3", "object": "model", "created": 0, "owned_by": "Netpreme"}
] } ```ok