---
title: Быстрый старт
description: Заведите аккаунт, выпустите ключ и сделайте настоящий вызов — три шага между браузером и ответом модели.
keywords: быстрый старт, начало, ключ, первый запрос, стриминг
group: get-started
---

## Заведите аккаунт {#create-account keywords="аккаунт, регистрация, зарегистрироваться"}

Всё в этом разделе происходит в консоли. Аккаунт — это адрес почты и пароль; ничего ставить не нужно, и карту никто не спрашивает до того, как ключ окажется у вас в руках.

:::steps
- **Откройте консоль** — это отдельный хост продукта, и там живут все операции с аккаунтом.
- **Создайте аккаунт** — адрес, пароль не короче двенадцати символов и два согласия, которых просит форма.
- **Вы уже внутри** — тот же ответ, что создаёт аккаунт, выпускает и сессию: консоль сама ставит себе куку и открывает обзор, входить отдельно не нужно и копировать нечего.
:::

Письмо с подтверждением адреса обычно приходит своим чередом. Его ссылка удостоверяет, что адрес ваш, и сегодня этим всё и исчерпывается: ни ключ, ни первый вызов её не ждут — поэтому и не пришедшее письмо не тупик. Отправка делается по мере возможности: под нагрузкой её могут пропустить, а ошибку доставки — проглотить, и регистрация в любом случае состоится.

## Выпустите ключ {#create-key keywords="ключ, консоль, секрет, показ"}

Ключ создаётся на экране ключей в консоли. Секрет показывается **один раз**, на том экране, который его создаёт, и больше никогда: платформа хранит только его хэш вместе с префиксом и хвостом, которые называют ключ в списке. Скопируйте его в своё хранилище секретов, не уходя с этого экрана, — потом прочитать его вам не сможет никто, включая поддержку, а лекарство от потерянного ключа — новый ключ.

> [Открыть консоль →](https://console.kumorouter.com/) · [Как пишется заголовок →](page:authentication)

## Сделайте вызов {#first-call keywords="запрос, chat completions, curl, base url"}

Направьте любой OpenAI-совместимый клиент на `https://api.kumorouter.com/v1` и дайте ему ключ. В этом вся миграция: меняются base URL и ключ, а остальной ваш код — нет.

Модель называется каноническим именем или псевдонимом, который несёт опубликованный каталог. `<model>` ниже стоит вместо такого имени — спросите список у шлюза командой `curl https://api.kumorouter.com/v1/models` или посмотрите ставки в [прайс-листе](https://kumorouter.com/pricing).

Потолок вывода обязателен. `max_tokens` (или `max_completion_tokens` — это то же самое) позволяет платформе сделать резерв под вызов до того, как он уйдёт к провайдеру; запрос без него отвергается, а не остаётся неограниченным.

:::code-group
```bash title=curl
curl https://api.kumorouter.com/v1/chat/completions \
  -H "Authorization: Bearer $KUMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<model>",
    "max_tokens": 128,
    "messages": [{ "role": "user", "content": "Объясни токены одной строкой." }]
  }'
```
```python title=Python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.kumorouter.com/v1",
    api_key=os.environ["KUMO_API_KEY"],
)

answer = client.chat.completions.create(
    model="<model>",
    max_tokens=128,
    messages=[{"role": "user", "content": "Объясни токены одной строкой."}],
)
print(answer.choices[0].message.content)
```
```javascript title=Node
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.kumorouter.com/v1",
  apiKey: process.env.KUMO_API_KEY,
});

const answer = await client.chat.completions.create({
  model: "<model>",
  max_tokens: 128,
  messages: [{ role: "user", content: "Объясни токены одной строкой." }],
});

const reply = answer.choices[0].message.content;
```
:::

Ответ принадлежит самому этому протоколу, а не переведён из другого: choices, причина завершения и счётчики токенов приходят в той форме, которую клиент уже разбирает.

```json title=Response
{
  "id": "chatcmpl-8f2b7e10c9",
  "object": "chat.completion",
  "model": "<model>",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Токены — это небольшие куски текста, которые модель читает и пишет."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 12,
    "completion_tokens": 18,
    "total_tokens": 30
  }
}
```

## Включите поток {#stream keywords="стриминг, поток, sse, server-sent events, чанки"}

Добавьте `"stream": true` — и тот же вызов ответит как `text/event-stream`: события `chat.completion.chunk` в порядке прихода, затем завершающий кадр `[DONE]`. Попросите счётчики токенов через `stream_options` — и перед этим кадром придёт чанк с расходом.

Отказ, решённый до первого события, приходит обычной JSON-ошибкой — ровно так же, как в унарном вызове. Сбой после начала потока обрывает его **без** завершающего кадра: именно так клиент отличает законченный ответ от обрезанного, поэтому поток, остановившийся до `[DONE]`, считайте неудачным вызовом, а не коротким.

:::code-group
```bash title=curl
curl -N https://api.kumorouter.com/v1/chat/completions \
  -H "Authorization: Bearer $KUMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<model>",
    "max_tokens": 128,
    "stream": true,
    "stream_options": { "include_usage": true },
    "messages": [{ "role": "user", "content": "Напиши хайку про задержку." }]
  }'
```
```python title=Python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.kumorouter.com/v1",
    api_key=os.environ["KUMO_API_KEY"],
)

stream = client.chat.completions.create(
    model="<model>",
    max_tokens=128,
    stream=True,
    stream_options={"include_usage": True},
    messages=[{"role": "user", "content": "Напиши хайку про задержку."}],
)
for chunk in stream:
    for choice in chunk.choices:
        print(choice.delta.content or "", end="", flush=True)
```
```javascript title=Node
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.kumorouter.com/v1",
  apiKey: process.env.KUMO_API_KEY,
});

const stream = await client.chat.completions.create({
  model: "<model>",
  max_tokens: 128,
  stream: true,
  stream_options: { include_usage: true },
  messages: [{ role: "user", content: "Напиши хайку про задержку." }],
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
```
:::

> [Каждая операция, поле за полем →](page:api-reference) · [Как выглядит отказ →](page:errors)

## Убедитесь, что ключ работает {#verify-key keywords="проверка, проверить, личность"}

Прежде чем вшивать ключ куда-либо, спросите у платформы, что она о нём думает. Эхо личности — единственная операция, которая отвечает личностью самого предъявленного ключа: его именем, тем, чем он оплачивается, и сроком, — поэтому она говорит «да, ключ живой, и вот что ему разрешено» без единой написанной вами строки.

> [Проверить ключ →](page:key-check)
