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 as max_output_tokens in /v1/models) when no deployment can satisfy it. Sending a large value as "no preference" is safe.
  • stream - set to true for SSE streaming.
  • tools and tool_choice - OpenAI function calling on models tagged tools on 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_logprobs is not accepted.
  • max_completion_tokens - alias of max_tokens. n is 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).
  • preset or X-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_id as model (the provider id and that provider's model id, as listed for the model in GET /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.