# Chat

> Original: https://api.6io.io/en/docs/chat/ (HTML). All pages: https://api.6io.io/llms.txt

Chat works over the OpenAI protocol: `POST /v1/chat/completions`. Any SDK or program where you can change the address and the key will do. The models are the groups `op` ([OpenRouter](https://api.6io.io/md/en/openrouter.md)) and `vn` ([Venice](https://api.6io.io/md/en/venice.md)).

## A request

```bash
curl https://api.6io.io/v1/chat/completions \
  -H "Authorization: Bearer sixio_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "op/openai/gpt-4o-mini",
    "messages": [
      {"role": "system", "content": "Answer briefly."},
      {"role": "user", "content": "What is Idempotency-Key for?"}
    ],
    "temperature": 0.3,
    "max_tokens": 200
  }'
```

The parameters (`temperature`, `max_tokens`, `tools`, `response_format` and others) go to the provider as they are. What they mean and which models understand them is in the provider's documentation: [OpenRouter](https://openrouter.ai/docs/api-reference/parameters) for `op`, [Venice](https://docs.venice.ai/api-reference/endpoint/chat/completions) for `vn`.

The response comes in the OpenAI format. `model` holds the name you sent (`op/…`), and the request ID is in the `X-Sixio-Request-Id` header.

Set `max_tokens`. Before sending, we reserve money for the longest answer you allowed, and the smaller `max_tokens` is, the smaller the reserve. Only what was actually spent is charged. More in [Balance and prices](https://api.6io.io/md/en/billing.md).

## Streaming

With `"stream": true` the answer arrives as it is generated, as SSE.

```python
from openai import OpenAI

client = OpenAI(base_url="https://api.6io.io/v1", api_key="sixio_sk_...")
stream = client.chat.completions.create(
    model="op/openai/gpt-4o-mini",
    messages=[{"role": "user", "content": "Tell a short fairy tale"}],
    max_tokens=300,
    stream=True,
)
for chunk in stream:
    if chunk.choices:  # the last chunk carries only usage, no text
        print(chunk.choices[0].delta.content or "", end="", flush=True)
```

- The last chunk has `usage`. Its `usage.cost` is the cost at the provider in dollars, not our charge. The amount in credits is in `GET /v1/requests/{id}`.
- If you close the connection early, the generation at the provider may already be running. It will be paid for.
- If there is a proxy between you and the API (nginx and the like), turn off response buffering. We send the `X-Accel-Buffering: no` header.

## Catalog and prices

`GET /v1/models` returns the chat models in the OpenAI format. Each one has an added `pricing` field:

```json
{
  "id": "op/openai/gpt-4o-mini",
  "object": "model",
  "owned_by": "openai",
  "pricing": {
    "currency": "credits",
    "prompt_per_million": "11.850000000000",
    "completion_per_million": "47.400000000000",
    "request": "0.000000000000"
  }
}
```

| Field | Meaning |
| --- | --- |
| `prompt_per_million` | the price of a million input tokens, credits |
| `completion_per_million` | the price of a million output tokens, credits |
| `request` | the fee for the request itself, if the model has one |

The list holds chat models only. For fal and Sixio models see `GET /native/fal/models` and `GET /native/sixio/models`. Models with a floating price ("dynamic" at the provider) are not sold.

The final price depends on how many tokens were actually spent, so it can differ from the estimate made from the catalog.

## Free models

Models with a price of 0 in the catalog (at OpenRouter such names have the suffix `:free`) are called like all the others, and the charge for them is zero. The condition: the API balance must be above zero. With a zero balance or in debt the answer is `402 insufficient_funds`.

To find them in the catalog:

```python
import requests

models = requests.get(
    "https://api.6io.io/v1/models",
    headers={"Authorization": "Bearer sixio_sk_..."},
).json()["data"]

free = [
    m["id"] for m in models
    if float(m["pricing"]["prompt_per_million"]) == 0 and float(m["pricing"]["completion_per_million"]) == 0
]
print(free)
```

The provider's quota for free models is shared by all its clients, so they may answer `503 upstream_busy`. In that case nothing is charged: retry after `Retry-After`.

## Groups op and vn

Chat is the same for both groups, but each has its own specifics:

- [OpenRouter models (op)](https://api.6io.io/md/en/openrouter.md): how to find a model's providers and their prices, choose a provider and the sorting, what about plugins and web search.
- [Venice models (vn)](https://api.6io.io/md/en/venice.md): the system prompt, paid search, the price.

## What is not supported yet

These requests are refused before any charge with `400 unsupported_parameter`:

- web search and the provider's paid server tools: the fields `plugins` and `web_search_options`, the model suffix `:online`, `tools` of the type `openrouter:…`;
- choosing a model around the `model` field: the fields `models` (a list of fallback models) and `preset`;
- input that is not text: images, audio and files in `messages`.

Function calling (`tools`) and the other parameters work as at the provider.
