# CloseRouter V2 API

Краткая клиентская документация по публичному V2 API.

Base URL:

```text
https://api.closerouter.dev/v1
```

Этот base URL используется для публичного V2 inference API. Кабинет, billing, admin и остальные business API остаются на:

```text
https://api.closerouter.dev/v1
```

Новые inference-интеграции должны использовать V2 endpoints ниже.

## Авторизация

Создайте API-ключ в кабинете CloseRouter и передавайте его одним из способов:

```http
Authorization: Bearer closerouter_your_key
```

или:

```http
x-api-key: closerouter_your_key
```

Для `POST`-запросов используйте:

```http
Content-Type: application/json
```

Не вставляйте API-ключи в frontend-код, публичные репозитории, логи и скриншоты.

## Endpoint-ы

Все пути указаны относительно base URL.

| Method | Path | Назначение |
| --- | --- | --- |
| `GET` | `/models` | Список доступных моделей, цены, modalities, endpoint-ы |
| `GET` | `/models/count` | Количество доступных моделей |
| `GET` | `/models/{provider}/{model}/endpoints` | Параметры и streaming для конкретной модели |
| `GET` | `/providers` | Логические публичные провайдеры без upstream-деталей |
| `GET` | `/credits` | Текущий баланс и суммарное использование аккаунта |
| `POST` | `/chat/completions` | OpenAI-style Chat Completions |
| `POST` | `/responses` | OpenAI Responses API |
| `POST` | `/messages` | Anthropic-style Messages API |
| `POST` | `/images/generations` | Генерация изображений |
| `POST` | `/videos/submit` | Создать video task |
| `GET` | `/videos/tasks/{task_id}` | Проверить статус video task и получить outputs |

## Модели

ID модели имеет формат:

```text
provider/model
```

Примеры:

```text
openai/gpt-5.4-mini
anthropic/claude-haiku-4.5
google/veo-3.1
```

Перед генерацией загрузите каталог:

```bash
export CLOSEROUTER_API_KEY="closerouter_your_key"

curl https://api.closerouter.dev/v1/models \
  -H "Authorization: Bearer $CLOSEROUTER_API_KEY"
```

Полезные поля в ответе:

- `id`: публичный ID модели для поля `model`
- `pricing`: цена модели
- `endpoints`: поддерживаемые API, например `chat`, `responses`, `messages`, `images_generations`, `videos_submit`
- `supported_parameters`: параметры, которые имеет смысл отправлять модели
- `architecture.input_modalities` и `architecture.output_modalities`: поддерживаемые типы ввода/вывода

Фильтры каталога:

```bash
curl "https://api.closerouter.dev/v1/models?output_modalities=text" \
  -H "Authorization: Bearer $CLOSEROUTER_API_KEY"

curl "https://api.closerouter.dev/v1/models?output_modalities=video" \
  -H "Authorization: Bearer $CLOSEROUTER_API_KEY"
```

Публичный каталог не раскрывает internal upstream names, upstream URLs, upstream paths, priorities, routing weights, API keys или health state.

## Chat Completions

```bash
curl https://api.closerouter.dev/v1/chat/completions \
  -H "Authorization: Bearer $CLOSEROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.4-mini",
    "messages": [
      { "role": "user", "content": "Reply with exactly: ok" }
    ],
    "max_tokens": 16
  }'
```

Пример ответа:

```json
{
  "id": "chatcmpl_...",
  "object": "chat.completion",
  "model": "openai/gpt-5.4-mini",
  "provider": "OpenAI",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "ok"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 11,
    "completion_tokens": 5,
    "total_tokens": 16
  }
}
```

## OpenAI JavaScript SDK

```ts
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.CLOSEROUTER_API_KEY,
  baseURL: 'https://api.closerouter.dev/v1',
});

const completion = await client.chat.completions.create({
  model: 'openai/gpt-5.4-mini',
  messages: [{ role: 'user', content: 'Reply with exactly: ok' }],
  max_tokens: 16,
});

console.log(completion.choices[0]?.message?.content);
```

## Responses API

```bash
curl https://api.closerouter.dev/v1/responses \
  -H "Authorization: Bearer $CLOSEROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.4-mini",
    "input": "Reply with exactly: ok",
    "max_output_tokens": 16
  }'
```

`GET /responses` не является endpoint-ом получения ответа. Используйте только `POST /responses`.

## Messages API

Формат совместим с Anthropic-style Messages API, но ключ остаётся ключом CloseRouter.

```bash
curl https://api.closerouter.dev/v1/messages \
  -H "Authorization: Bearer $CLOSEROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-haiku-4.5",
    "max_tokens": 16,
    "messages": [
      { "role": "user", "content": "Reply with exactly: ok" }
    ]
  }'
```

Для Anthropic-compatible клиентов можно использовать `x-api-key`.

## Images API

```bash
curl https://api.closerouter.dev/v1/images/generations \
  -H "Authorization: Bearer $CLOSEROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gemini-3-pro-image-preview",
    "prompt": "A minimal product photo on a white background",
    "n": 1,
    "size": "1024x1024"
  }'
```

Перед отправкой запроса проверьте, что у модели в каталоге есть endpoint `images_generations` и `architecture.output_modalities` содержит `image`.

## Streaming

Включите streaming:

```json
{
  "stream": true
}
```

Перед этим проверьте, что модель поддерживает streaming:

```bash
curl https://api.closerouter.dev/v1/models/openai/gpt-5.4-mini/endpoints \
  -H "Authorization: Bearer $CLOSEROUTER_API_KEY"
```

Chat streaming возвращает Server-Sent Events:

```text
data: {...}

data: [DONE]
```

Пример:

```bash
curl -N https://api.closerouter.dev/v1/chat/completions \
  -H "Authorization: Bearer $CLOSEROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-haiku-4.5",
    "messages": [
      { "role": "user", "content": "Reply with exactly: ok" }
    ],
    "max_tokens": 16,
    "stream": true
  }'
```

## Fallback-модели

Можно передать список допустимых кандидатов:

```json
{
  "model": "openai/gpt-5.4-mini",
  "models": [
    "anthropic/claude-haiku-4.5"
  ]
}
```

Если указаны и `model`, и `models`, сначала используется `model`, затем элементы `models`.

## Видео

Video API асинхронный.

Создать задачу:

```bash
curl https://api.closerouter.dev/v1/videos/submit \
  -H "Authorization: Bearer $CLOSEROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "google/veo-3.1",
    "prompt": "A clean product shot of a futuristic API dashboard",
    "duration": 5,
    "aspect_ratio": "16:9"
  }'
```

Ответ:

```json
{
  "id": "video-task-id",
  "status": "pending",
  "model": "google/veo-3.1"
}
```

Проверить статус:

```bash
curl https://api.closerouter.dev/v1/videos/tasks/video-task-id \
  -H "Authorization: Bearer $CLOSEROUTER_API_KEY"
```

Готовый результат:

```json
{
  "id": "video-task-id",
  "status": "completed",
  "outputs": ["https://.../output.mp4"],
  "error": null,
  "model": "google/veo-3.1",
  "duration_seconds": 5.02
}
```

## Баланс

```bash
curl https://api.closerouter.dev/v1/credits \
  -H "Authorization: Bearer $CLOSEROUTER_API_KEY"
```

Ответ:

```json
{
  "data": {
    "total_credits": 12.34,
    "total_usage": 5.67
  }
}
```

`total_credits` — текущий доступный баланс. `total_usage` — суммарное списание за использование API.

## Ошибки

Ошибки возвращаются в едином JSON-формате:

```json
{
  "error": {
    "code": "invalid_request",
    "message": "Request body must be a JSON object",
    "status": 400,
    "metadata": {
      "request_id": "..."
    }
  }
}
```

Сохраняйте `metadata.request_id` для обращения в поддержку.

Частые коды:

| Status | Code | Значение |
| --- | --- | --- |
| `400` | `invalid_request` | Неверный JSON, отсутствует `model`, неизвестная модель или неверный параметр |
| `401` | `invalid_api_key` | Нет ключа или ключ неверный |
| `402` | `insufficient_balance` | Недостаточно средств |
| `429` | `rate_limited` | Временный лимит запросов |
| `503` | `no_available_provider` | Для выбранной модели и endpoint сейчас нет доступного маршрута |

## Рекомендации

- Перед интеграцией загрузите `GET /models`.
- Показывайте пользователю только модели, поддерживающие нужный endpoint.
- Используйте `GET /models/{provider}/{model}/endpoints`, чтобы проверить streaming и параметры.
- Логируйте `request_id` из ошибок.
- Храните API-ключ только на backend/server-side стороне приложения.
