# Текст и чат: как использовать

> Гайд по /v1/chat/completions — лимиты токенов, стриминг через SSE и usage-чанк, tools и response_format, картинки на входе (vision).

Веб-версия: https://ai.trackly.one/developers/docs/text · Индекс документации: https://ai.trackly.one/llms.txt

Текстовые модели живут за `POST /v1/chat/completions` — контракт тот же, что
у OpenAI. В `model` подставляется id из [/v1/models](https://ai.trackly.one/developers/docs/models)
(например, `openai/gpt-5-mini` или `anthropic/claude-sonnet-4.6`), в
`messages` — история диалога. Работают стриминг, tools, `response_format` и
картинки на входе. Деньги списываются после успешного ответа по фактическому
`usage`, при ошибке провайдера — не списываются.

## Как отправить запрос?

Минимум — `model` и `messages`. Роли сообщений: `system`, `user`,
`assistant`, `tool`, `developer`. Опциональные параметры
(`temperature`, `top_p`, `stop`, `n`, `seed` и другие) прокидываются в модель
как есть — полный список полей в
[референсе chat/completions](https://ai.trackly.one/developers/docs/reference/chat-completions).

**Обычный запрос**

```bash
curl https://api.trackly.one/v1/chat/completions \
  -H "Authorization: Bearer $TRACKLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5-mini",
    "messages": [
      { "role": "system", "content": "Отвечай кратко." },
      { "role": "user", "content": "Что такое эмбеддинги?" }
    ],
    "max_completion_tokens": 512
  }'
```

```python
resp = client.chat.completions.create(
    model="openai/gpt-5-mini",
    messages=[
        {"role": "system", "content": "Отвечай кратко."},
        {"role": "user", "content": "Что такое эмбеддинги?"},
    ],
    max_completion_tokens=512,
)
print(resp.choices[0].message.content)
print(resp.usage)  # prompt_tokens / completion_tokens / total_tokens
```

```javascript
const resp = await client.chat.completions.create({
  model: "openai/gpt-5-mini",
  messages: [
    { role: "system", content: "Отвечай кратко." },
    { role: "user", content: "Что такое эмбеддинги?" },
  ],
  max_completion_tokens: 512,
});
console.log(resp.choices[0].message.content);
console.log(resp.usage);
```

Ответ — стандартный `chat.completion`: текст в
`choices[0].message.content`, расход токенов в `usage`.

## max_tokens или max_completion_tokens?

Оба поля принимаются, шлюз сам нормализует их под семейство модели:

- `openai/*` — в модель уходит только `max_completion_tokens` (GPT-5 и
  o-серия отвергают `max_tokens`); если вы прислали `max_tokens`, мы его
  переименуем;
- остальные семейства (`anthropic/*`, `google/*`, `deepseek/*`,
  `yandex/*`) — в модель уходит только `max_tokens`, обратное
  переименование тоже автоматическое.

Так что берите любое поле — старый код с `max_tokens` продолжит работать на
всех моделях. Одно исключение: оба поля сразу с разными значениями — это 400
`invalid_request_error` с указанием `param`.

## Как стримить ответ?

`stream: true` — и ответ пойдёт чанками по SSE (`data: {...}`, в конце
`data: [DONE]`).

**Стриминг с usage-чанком**

```bash
curl -N https://api.trackly.one/v1/chat/completions \
  -H "Authorization: Bearer $TRACKLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "google/gemini-2.5-flash",
    "messages": [{ "role": "user", "content": "Расскажи анекдот про программиста" }],
    "stream": true,
    "stream_options": { "include_usage": true }
  }'
```

```python
stream = client.chat.completions.create(
    model="google/gemini-2.5-flash",
    messages=[{"role": "user", "content": "Расскажи анекдот про программиста"}],
    stream=True,
    stream_options={"include_usage": True},
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")
    if chunk.usage:  # финальный чанк: choices пустой, зато есть usage
        print("\n", chunk.usage)
```

```javascript
const stream = await client.chat.completions.create({
  model: "google/gemini-2.5-flash",
  messages: [{ role: "user", content: "Расскажи анекдот про программиста" }],
  stream: true,
  stream_options: { include_usage: true },
});
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
  if (chunk.usage) console.log("\n", chunk.usage);
}
```

Поведение `usage` в стриме — как у OpenAI:

- прислали `stream_options: { "include_usage": true }` — после последнего
  контент-чанка придёт ещё один, с пустым `choices` и заполненным `usage`;
- не прислали — usage-чанка не будет, `[DONE]` приходит сразу после
  последнего контент-чанка.

Биллинг от этой опции не зависит: расход считается по фактическому usage
провайдера в обоих случаях.

## Работают ли tools и response_format?

Да, поля `tools`, `tool_choice` и `response_format` — полноценная часть
схемы и передаются модели без изменений; `tool_calls` в ответе тоже
проходят как есть. Важная честная оговорка: поддержка этих возможностей
зависит от конкретной модели, шлюз её не гарантирует и не эмулирует. Если
модель не умеет structured output или function calling, её ошибку вы
получите в исходном виде.

То же относится к `n`, `seed`, `logprobs`, `frequency_penalty`,
`presence_penalty` — прозрачный passthrough.

## Как отправить картинку (vision)?

Через content parts с `image_url` — обычный OpenAI-формат. Подойдёт и
внешний URL, и data-URL с base64. Модель должна уметь vision (например,
`openai/gpt-5`, `anthropic/claude-sonnet-4.6`, `google/gemini-2.5-flash` —
смотрите пометки в [каталоге моделей](https://ai.trackly.one/developers/models)); text-only модель
ответит 400 `unsupported_capability`.

**Картинка на входе**

```bash
curl https://api.trackly.one/v1/chat/completions \
  -H "Authorization: Bearer $TRACKLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "google/gemini-2.5-flash",
    "messages": [{
      "role": "user",
      "content": [
        { "type": "text", "text": "Что на этой картинке?" },
        { "type": "image_url", "image_url": { "url": "https://example.com/photo.jpg" } }
      ]
    }]
  }'
```

```python
resp = client.chat.completions.create(
    model="google/gemini-2.5-flash",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "Что на этой картинке?"},
            {"type": "image_url", "image_url": {"url": "https://example.com/photo.jpg"}},
        ],
    }],
)
print(resp.choices[0].message.content)
```

```javascript
const resp = await client.chat.completions.create({
  model: "google/gemini-2.5-flash",
  messages: [{
    role: "user",
    content: [
      { type: "text", text: "Что на этой картинке?" },
      { type: "image_url", image_url: { url: "https://example.com/photo.jpg" } },
    ],
  }],
});
console.log(resp.choices[0].message.content);
```

## Сколько это стоит?

Тариф у каждой модели свой, единица — токены. Актуальные цены в рублях — на
странице [цен для разработчиков](https://ai.trackly.one/developers/pricing); списание происходит
после успешного ответа по `usage`. Попробовать модели без кода можно в
[чате на сайте](https://ai.trackly.one/chat/chat) — тот же каталог, тот же баланс.
