CoreAI API
Run open models hosted in Uzbekistan. Send JSON requests and receive JSON responses or streamed events.
Overview
The API uses Bearer authentication and the Chat Completions request and response format.
Quickstart
Create a key, set it as an environment variable, and send your first request.
- Create a key in the API console. The plaintext is shown once.
- Store it in an environment variable:
export COREAI_API_KEY="cai_..." - Send an authenticated POST request to the chat completions endpoint.
curl https://inference-api.coreai.uz/v1/chat/completions \
-H "Authorization: Bearer $COREAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemma4-31b-it",
"messages": [
{"role": "user", "content": "Salom!"}
]
}'Authentication
Include your CoreAI key as a Bearer token on every /v1 request. Keys begin with cai_ and are managed in the API console.
Authorization: Bearer $COREAI_API_KEY
Content-Type: application/jsonModels
List the model identifiers currently available to your account.
/v1/modelsList available modelscurl https://inference-api.coreai.uz/v1/models \
-H "Authorization: Bearer $COREAI_API_KEY"Chat completions
Send a conversation as ordered role/content messages. Each request is stateless: include the prior messages your application wants the model to consider.
/v1/chat/completionsGenerate a model response| Parameter | Type | Default | Description |
|---|---|---|---|
| model | string | required | Model ID returned by GET /v1/models. |
| messages | array | required | Ordered system, user, assistant, and tool messages. |
| stream | boolean | false | Stream response chunks over SSE. |
| temperature | number | model default | Sampling randomness from 0 to 2. |
| top_p | number | model default | Nucleus sampling probability from 0 to 1. |
| max_tokens | integer | model default | Maximum number of output tokens. |
| stop | string | array | null | Up to four sequences that stop generation. |
| seed | integer | null | Best-effort deterministic sampling seed. |
| reasoning | object | false | Set enabled to true or false. Set exclude to true to omit reasoning text from the response. |
| tools | array | null | Function definitions the model may call. |
| tool_choice | string | object | auto / none | Controls function selection: none, auto, required, or a named function. |
| parallel_tool_calls | boolean | true | Allow multiple function calls in one response. |
Response
{
"id": "chatcmpl_...",
"object": "chat.completion",
"model": "gemma4-31b-it",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "Salom!"
},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 9,
"completion_tokens": 4,
"total_tokens": 13
}
}Streaming
Set stream to true to receive tokens as they are generated rather than waiting for the complete response.
curl -N https://inference-api.coreai.uz/v1/chat/completions \
-H "Authorization: Bearer $COREAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemma4-31b-it",
"messages": [{"role": "user", "content": "Salom!"}],
"stream": true,
"stream_options": {"include_usage": true}
}'The response uses text/event-stream. Each frame contains a chat completion chunk. The stream ends with data: [DONE]. With include_usage enabled, the terminal usage chunk contains token totals.
Reasoning
Gemma 4 31B supports thinking on/off. Thinking is off by default. Set reasoning.enabled to true to enable it for a request. Effort levels are unsupported.
curl https://inference-api.coreai.uz/v1/chat/completions \
-H "Authorization: Bearer $COREAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemma-4-31b-it",
"messages": [{"role": "user", "content": "Compare two deployment plans."}],
"reasoning": {"enabled": true}
}'Tool calling
Tool calling is currently unavailable. The examples below show the function-calling request format.
Define functions
curl https://inference-api.coreai.uz/v1/chat/completions \
-H "Authorization: Bearer $COREAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.8-27b",
"messages": [{"role": "user", "content": "What is the weather in Tashkent?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
}],
"tool_choice": "auto"
}'Function call
{
"choices": [{
"message": {
"role": "assistant",
"content": null,
"tool_calls": [{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"Tashkent\"}"
}
}]
},
"finish_reason": "tool_calls"
}]
}Send the function result
{
"model": "qwen3.8-27b",
"messages": [
{"role": "user", "content": "What is the weather in Tashkent?"},
{
"role": "assistant",
"content": null,
"tool_calls": [{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"Tashkent\"}"
}
}]
},
{"role": "tool", "tool_call_id": "call_abc123", "content": "{\"temperature_c\":18}"}
]
}In a stream, call fragments arrive in choices[0].delta.tool_calls. Concatenate function.arguments fragments in order.
Data retention
Free-tier API prompts, request parameters, and generated responses are retained for up to 30 days and may be reviewed to evaluate quality, understand usage, and prevent abuse.
API content does not appear in web-chat history or the usage console. Plaintext API keys and request headers are not stored with content records.
Errors and limits
Errors use a stable JSON envelope with a human-readable message, type, parameter, and machine-readable code.
400Invalid request or unsupported field401Missing, invalid, expired, or revoked API key403Current Terms of Service acceptance required404Unknown or unavailable model429Shared account request limit reached503Inference capacity temporarily unavailableSuccessful and rate-limited responses include x-ratelimit-limit-requests, x-ratelimit-remaining-requests, and x-ratelimit-reset-requests. Honor Retry-After on 429 and 503 responses.