Chat completions
Use POST /v1/chat/completions for chat, assistant workflows, and server-side app integrations. The endpoint supports non-streaming JSON responses and Server-Sent Events streaming.
Request
{
"model": "mistral-small-latest",
"messages": [
{"role": "system", "content": "You are a concise assistant."},
{"role": "user", "content": "Write a haiku about Amsterdam."}
],
"temperature": 0.7,
"stream": false
}
Response
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1717200000,
"model": "mistral-small-latest",
"choices": [{
"index": 0,
"message": {"role": "assistant", "content": "Canals under grey skies..."},
"finish_reason": "stop"
}],
"usage": {"prompt_tokens": 18, "completion_tokens": 25, "total_tokens": 43}
}
Supported request fields
model- required unless supplied by a preset. Must be a chat-capable model from/v1/models.messages- required OpenAI-style message list.temperature,top_p,max_tokens,frequency_penalty,presence_penalty,stop,seed- forwarded where supported by the provider.reasoning_effort-low/medium/high(or the provider's native levels). Translated automatically to each deployment's accepted vocabulary, so the same request works across every model.max_tokens- routing is cap-aware: requests are served by a deployment that can satisfy the requested cap; the value is only clamped (to the largest available cap, advertised asmax_output_tokensin/v1/models) when no deployment can satisfy it. Sending a large value as "no preference" is safe.stream- set totruefor SSE streaming.toolsandtool_choice- OpenAI function calling on models taggedtoolson the models page. The model may return several tool calls in one turn.response_format-{"type": "json_object"}or{"type": "json_schema", ...}for structured output, forwarded to the provider. Support for strict schemas depends on the model.logprobs,logit_bias,user,prompt_cache_key- forwarded to the provider.top_logprobsis not accepted.max_completion_tokens- alias ofmax_tokens.nis accepted only as 1.parallel_tool_calls,stream_options,store,metadata,service_tier- accepted for SDK compatibility and not forwarded. The final usage is always sent at the end of a stream (see streaming).presetorX-Preset- apply saved defaults from your account.- Any other field is rejected with
400, so a typo or an unsupported sampler never fails silently.
Tool calling
{
"model": "glm-5.3",
"messages": [{"role": "user", "content": "What is the weather in Arnhem?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Current weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
}],
"tool_choice": "auto"
}
The response carries choices[0].message.tool_calls; send each result back as a {"role": "tool", "tool_call_id": ..., "content": ...} message, exactly as with OpenAI.
Structured output
{
"model": "mistral-small-latest",
"messages": [{"role": "user", "content": "Extract the invoice number and total."}],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "invoice",
"strict": true,
"schema": {
"type": "object",
"properties": {
"number": {"type": "string"},
"total_eur": {"type": "number"}
},
"required": ["number", "total_eur"],
"additionalProperties": false
}
}
}
}
Choosing a provider
By default ozeye picks a provider for the model and fails over to another provider of the same model if the first one is unavailable. You pay the price of the provider that serves the request, so a failover can cost more or less than the first provider. Two controls change that:
- Provider prefix: send
provider/provider_model_idasmodel(the provider id and that provider's model id, as listed for the model inGET /v1/models/catalog) to start with that provider. Failover to other providers of the same model can still happen. - Provider blocklist: exclude providers for your whole account in dashboard settings or with
PUT /v1/account/provider-blocks. Blocked providers never receive your requests, also not as a fallback. Blocking every provider of a model except one pins the model to that provider.
curl -X PUT https://ozeye.ai/v1/account/provider-blocks \
-H "Authorization: Bearer $OZEYE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"providers": ["inceptron", "tensorx"]}'
# response: {"blocked": ["inceptron", "tensorx"]}
Error semantics
Provider rejections caused by the request (invalid parameters, unknown model) return the provider's 4xx status with its error message, so agent harnesses can fix the request instead of retrying. Upstream rate limits return 429 with a Retry-After header. Genuine upstream failures return 502 with the provider name and a request id.
Model validation
Unknown models, wrong-modality models, unpriced models, or models without a configured provider are rejected before any upstream provider call. This prevents accidental routing to unsupported or unpriced infrastructure.