POST /v1/chat/completions
OpenAI Chat Completions API compatible endpoint
Generate a response using the OpenAI Chat Completions format. This endpoint is compatible with the OpenAI SDK and Codex CLI.
Endpoint
POST https://api.runars.ca/v1/chat/completionsAuthentication
Include your API key as a Bearer token:
-H "Authorization: Bearer sk-runars-..."Request body
For a comparison of common parameters across all endpoints, see Parameters Reference.
| Field | Type | Required | Description |
|---|---|---|---|
model | string | Yes | Model identifier, must be "glm-5.2" |
messages | array | Yes | Array of message objects with role and content |
max_tokens | integer | No | Maximum tokens in the response (default: unlimited) |
temperature | number | No | Sampling temperature (0–2, default: 1) |
top_p | number | No | Nucleus sampling threshold (0–1) |
stream | boolean | No | Enable streaming (default: false) |
tools | array | No | Array of tool/function definitions (optional for tool calling) |
tool_choice | string|object | No | Which tool to use ("auto", "required", or specific tool) |
stream_options | object | No | Streaming options, including include_usage |
Message format
Each message in the messages array:
{
"role": "user" or "assistant",
"content": "text content"
}Or with tool calls:
{
"role": "assistant",
"content": "Optional text",
"tool_calls": [
{
"id": "call_...",
"type": "function",
"function": {
"name": "tool_name",
"arguments": "{...}"
}
}
]
}Response (non-streaming)
{
"id": "chatcmpl-...",
"object": "chat.completion",
"created": 1234567890,
"model": "glm-5.2",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "The response text here."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 42,
"completion_tokens": 15,
"total_tokens": 57
}
}Response (streaming)
With stream: true, the endpoint returns server-sent events:
event: message_start
data: {"object":"chat.completion","model":"glm-5.2",...}
event: message_delta
data: {"object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":""}}]}
event: message_delta
data: {"object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"The "}}]}
event: message_delta
data: {"object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"response "}}]}
event: message_stop
data: {"object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}Examples
Simple text request
curl https://api.runars.ca/v1/chat/completions \
-H "Authorization: Bearer sk-runars-..." \
-H "content-type: application/json" \
-d '{
"model": "glm-5.2",
"messages": [
{
"role": "user",
"content": "What is the capital of France?"
}
]
}'Using the OpenAI SDK with streaming
import OpenAI from "openai"
const openai = new OpenAI({
baseURL: "https://api.runars.ca/v1",
apiKey: process.env.OPENAI_API_KEY,
})
const stream = await openai.chat.completions.create({
model: "glm-5.2",
messages: [
{
role: "user",
content: "Tell me a short story about a robot.",
},
],
stream: true,
})
for await (const chunk of stream) {
if (chunk.choices[0].delta.content) {
process.stdout.write(chunk.choices[0].delta.content)
}
}With tool calling
curl https://api.runars.ca/v1/chat/completions \
-H "Authorization: Bearer sk-runars-..." \
-H "content-type: application/json" \
-d '{
"model": "glm-5.2",
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name"
}
},
"required": ["location"]
}
}
}
],
"messages": [
{
"role": "user",
"content": "What is the weather in Toronto?"
}
]
}'The response will include a tool_calls array with the tool name and arguments. You can then send the tool result back in a subsequent message.
Streaming with usage tracking
To get token usage in a streaming response, pass stream_options:
curl https://api.runars.ca/v1/chat/completions \
-H "Authorization: Bearer sk-runars-..." \
-H "content-type: application/json" \
-d '{
"model": "glm-5.2",
"stream": true,
"stream_options": {
"include_usage": true
},
"messages": [
{
"role": "user",
"content": "Say hello"
}
]
}'The final message will include usage data.
Error responses
400 Bad Request
Invalid request:
{
"error": {
"message": "Invalid request: missing required field 'messages'",
"type": "invalid_request_error",
"param": null,
"code": null
}
}401 Unauthorized
Invalid or missing API key:
{
"error": {
"message": "Unauthorized",
"type": "invalid_request_error",
"param": null,
"code": "invalid_api_key"
}
}429 Too Many Requests
Rate limit exceeded:
{
"error": {
"message": "Rate limit exceeded",
"type": "server_error",
"param": null,
"code": "insufficient_quota"
}
}The response includes a Retry-After header indicating how long to wait.
Token usage
- Prompt tokens: Input tokens (messages + any system prompt).
- Completion tokens: Output tokens.
- Total tokens: Sum of prompt and completion tokens.
All count towards pricing and rate limits. See Pricing for rates.