# api9 · Native API Mirror — подключение для агентов

Прозрачный проброс к **настоящему API любого провайдера** под одним ключом api9.
Агент получает **100 % нативного функционала** провайдера (все модели, параметры,
эксклюзивные эндпоинты), а реальный ключ провайдера **никогда не покидает api9** —
берётся из авто-ротируемого пула и меняется при 401/403/429.

---

## 1. Ссылки

| Ресурс | URL |
|---|---|
| Этот гайд (MD) | https://api9.ru/mirror-agents.md |
| Базовый гайд по зеркалам | https://api9.ru/mirror.md |
| Живой список зеркал + счётчик ключей | https://api9.ru/mirror (нужен токен) |
| Источник истины по провайдерам/модальностям | https://api9.ru/providers.yml |
| Рекомендации по использованию | https://api9.ru/usage.md |
| Обзор платформы | https://api9.ru/readme.md |
| DaData passthrough (отдельный) | https://api9.ru/dadata.md |
| DaData — полный справочник полей | https://api9.ru/dadata-reference.md |
| Панель (выдать client-ключ, статусы пулов) | https://api9.ru |

---

## 2. База подключения

- **Base URL:** `https://api9.ru`
- **Формат:** `{METHOD} /mirror/{provider}/{нативный-путь}`
- **Авторизация api9:** заголовок `Authorization: Bearer <API9_TOKEN>`
- Тело, query, заголовки — **ровно как в родном API провайдера**. Авторизацию к
  провайдеру подставляет api9; свой `Authorization` можно не слать или слать любой —
  он всё равно заменяется на ключ из пула.

### Как получить `<API9_TOKEN>`

Для агентов **не используйте мастер-токен**. Заведите отдельный client-ключ
(`aim_ck_…`) с лимитами RPM/сутки в панели https://api9.ru (раздел ключей) и
раздайте его агенту. Мастер-токен держите только на сервере.

```bash
export API9_TOKEN=aim_ck_xxxxxxxxxxxxxxxxxxxxxxxx
```

---

## 3. OpenAI SDK (для OpenAI-совместимых провайдеров)

`base_url` указывает на зеркало **конкретного** провайдера; ключ провайдера
подставит api9.

### Python

```python
from openai import OpenAI
import os

client = OpenAI(
    api_key="unused",                              # api9 игнорирует, ключ из пула
    base_url="https://api9.ru/mirror/groq",
    default_headers={"Authorization": f"Bearer {os.environ['API9_TOKEN']}"},
)

r = client.chat.completions.create(
    model="llama-3.3-70b-versatile",
    messages=[{"role": "user", "content": "привет"}],
)
print(r.choices[0].message.content)
```

### TypeScript / Node

```ts
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "unused",
  baseURL: "https://api9.ru/mirror/deepseek",
  defaultHeaders: { Authorization: `Bearer ${process.env.API9_TOKEN}` },
});

const r = await client.chat.completions.create({
  model: "deepseek-chat",
  messages: [{ role: "user", content: "привет" }],
});
console.log(r.choices[0].message.content);
```

> SDK кладёт свой `Authorization: Bearer <apiKey>`, но api9 его игнорирует и
> использует `default_headers.Authorization` (ключ api9), затем подменяет на реальный
> ключ провайдера. Если SDK не даёт задать `default_headers` — используйте прямые
> HTTP-вызовы (раздел 4).

---

## 4. curl

```bash
# Chat (нативный Groq)
curl -s https://api9.ru/mirror/groq/chat/completions \
  -H "Authorization: Bearer $API9_TOKEN" -H "Content-Type: application/json" \
  -d '{"model":"llama-3.3-70b-versatile","messages":[{"role":"user","content":"hi"}]}'

# Каталог моделей провайдера (что реально живо на пуле)
curl -s https://api9.ru/mirror/openrouter/models -H "Authorization: Bearer $API9_TOKEN"

# Anthropic Messages (x-api-key подставит api9)
curl -s https://api9.ru/mirror/anthropic/v1/messages \
  -H "Authorization: Bearer $API9_TOKEN" -H "Content-Type: application/json" \
  -d '{"model":"claude-3-5-haiku-20241022","max_tokens":64,"messages":[{"role":"user","content":"hi"}]}'

# Gemini (ключ уходит в ?key=, подставляет api9)
curl -s "https://api9.ru/mirror/gemini/v1beta/models/gemini-2.5-flash:generateContent" \
  -H "Authorization: Bearer $API9_TOKEN" -H "Content-Type: application/json" \
  -d '{"contents":[{"parts":[{"text":"hi"}]}]}'
```

### Стриминг (SSE)

`"stream":true` пробрасывается насквозь — чанки идут как есть:

```bash
curl -N https://api9.ru/mirror/groq/chat/completions \
  -H "Authorization: Bearer $API9_TOKEN" -H "Content-Type: application/json" \
  -d '{"model":"llama-3.3-70b-versatile","messages":[{"role":"user","content":"считай до 5"}],"stream":true}'
```

---

## 5. Схемы авторизации (api9 подставляет сам)

Агенту делать ничего не нужно — таблица для понимания, как ключ доходит до провайдера.

| Схема | Как передаётся ключ | Провайдеры |
|---|---|---|
| `bearer` | `Authorization: Bearer <k>` | openai, groq, cerebras, mistral, together, deepseek, fireworks, openrouter, xai, nvidia, novita, sambanova, deepinfra, hyperbolic, perplexity, moonshot, dashscope, zhipu, cohere, voyage, huggingface, tavily, firecrawl, llamacloud, stability, recraft, leonardo, luma, runway, github_models и др. |
| `google` | `?key=<k>` в URL | gemini |
| `anthropic` | `x-api-key: <k>` + `anthropic-version` | anthropic |
| `xi` | `xi-api-key: <k>` | elevenlabs |
| `token` | `Authorization: Token <k>` | replicate, deepgram |
| `x-api-key` / `exa` | `x-api-key: <k>` | exa, cartesia (+`Cartesia-Version`) |
| `pinecone` | `Api-Key: <k>` + version | pinecone |
| `brave` | `X-Subscription-Token: <k>` | brave_search |
| `fal` | `Authorization: Key <k>` | fal |
| `gitlab` | `PRIVATE-TOKEN: <k>` | gitlab |
| `raw` | `Authorization: <k>` | assemblyai |

Полный актуальный список — `GET https://api9.ru/mirror`.

---

## 6. Живые провайдеры (пример пути на каждый)

Счётчики ключей меняются — точное число всегда в `GET /mirror`. Ниже — типовые пути.

| Категория | Провайдеры | Путь-пример |
|---|---|---|
| Chat / LLM | groq, deepseek, openrouter, nvidia, cerebras, together, mistral, moonshot, zhipu, dashscope, sambanova, chutes, perplexity, deepinfra, featherless, github_models | `/mirror/{p}/chat/completions` |
| Эмбеддинги | voyage, together, nvidia, deepinfra | `/mirror/{p}/embeddings` |
| Реранк | cohere | `/mirror/cohere/v2/rerank` |
| Изображения | stability, recraft, leonardo, fal, luma | `/mirror/stability/v2beta/stable-image/generate/core` |
| Аудио TTS | elevenlabs, cartesia, deepgram | `/mirror/elevenlabs/v1/text-to-speech/{voice}` |
| Аудио STT | deepgram, assemblyai | `/mirror/assemblyai/transcript` |
| Видео | runway, luma | `/mirror/runway/...` |
| Поиск | tavily, exa, brave_search | `/mirror/tavily/search` |
| Vector DB | pinecone | `/mirror/pinecone/...` |
| Gemini | gemini | `/mirror/gemini/v1beta/models/{m}:generateContent` |
| Anthropic | anthropic | `/mirror/anthropic/v1/messages` |
| RAG / docs | llamacloud | `/mirror/llamacloud/...` |

---

## 7. Примеры по категориям

**Эмбеддинги:**
```bash
curl -s https://api9.ru/mirror/voyage/embeddings -H "Authorization: Bearer $API9_TOKEN" \
  -H "Content-Type: application/json" -d '{"model":"voyage-3-lite","input":["привет"]}'
```

**Реранк:**
```bash
curl -s https://api9.ru/mirror/cohere/v2/rerank -H "Authorization: Bearer $API9_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"rerank-v3.5","query":"кофе","documents":["кофейня","погода"],"top_n":1}'
```

**Изображения (Stability):**
```bash
curl -s https://api9.ru/mirror/stability/v2beta/stable-image/generate/core \
  -H "Authorization: Bearer $API9_TOKEN" -F prompt="red apple" -F output_format="png" -o out.png
```

**Аудио TTS (ElevenLabs):**
```bash
curl -s https://api9.ru/mirror/elevenlabs/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM \
  -H "Authorization: Bearer $API9_TOKEN" -H "Content-Type: application/json" \
  -d '{"text":"привет","model_id":"eleven_multilingual_v2"}' -o out.mp3
```

**Поиск (Tavily):**
```bash
curl -s https://api9.ru/mirror/tavily/search -H "Authorization: Bearer $API9_TOKEN" \
  -H "Content-Type: application/json" -d '{"query":"ФНС России","max_results":3}'
```

---

## 8. Поведение и ошибки

- **Ротация ключей:** 401/403 → ключ в cooldown (1 ч), берётся следующий; 429 →
  короткий cooldown (3 мин). До 4 ключей за запрос (`AI_MIRROR_RETRY`).
- **Не-авторизационные коды** (400/404/422/5xx от самого провайдера) возвращаются
  клиенту **как есть** — это ответ на ваш запрос, а не проблема ключа.
- `502 mirror {provider}: all N pooled keys failed (...)` — все ключи провайдера
  сейчас нерабочие/исчерпаны.
- `404 provider '<x>' has no mirror` — провайдера нет в реестре (`GET /mirror`).
- `503 no usable pooled keys` — по провайдеру сейчас нет живых ключей.
- Заголовок ответа `x-mirror-provider: <provider>` — маркер ответа через зеркало.

---

## 9. Когда `/mirror`, а когда `/v1`

| Нужно | Эндпоинт |
|---|---|
| Авто-выбор провайдера, единый OpenAI-формат, макс. скорость | `POST /v1/chat/completions` c `model:"auto"` |
| Конкретный провайдер, но единый OpenAI-формат | `POST /v1/chat/completions` c `model:"groq/…"` |
| **Нативный эндпоинт/параметр/модель, которых нет в `/v1`** | **`/mirror/{provider}/…`** |
| Обогащение компаний | `POST /enrich` (dadata/checko/kontur/hunter/apollo) |
