Для ИИ-агентов: пошаговая инструкция по настройке — /docs/agents.md, индекс документации — /llms.txt.

Справочник API

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

Протоколы и адреса#

Шлюз принимает форматы OpenAI и Anthropic. Базовый адрес для SDK OpenAI — https://gate.joingonka.ai/v1, для SDK Anthropic — https://gate.joingonka.ai. Все протоколы работают на одном ключе и одном балансе: запрос в любом формате идёт одним и тем же путём.

Метод и путьФорматДля чегоОсобенности
POST /v1/chat/completionsOpenAI Chat CompletionsЧат, агенты, вызов инструментовОсновной путь: остальные форматы шлюз переводит в него.
POST /v1/messagesAnthropic MessagesClaude Code и SDK AnthropicБазовый адрес без /v1; модели claude-* заменяются рекомендуемой; поле max_tokens обязательно.
POST /v1/responsesOpenAI ResponsesCodex CLI и новые SDK OpenAIБез состояния: историю присылайте целиком в каждом запросе.
POST /v1/completionsOpenAI Completions (legacy)Автодополнение и правка кода в редакторахsuffix передаётся модели подсказкой; в ответе logprobs: null.
POST /v1/embeddingsOpenAI EmbeddingsВекторные представления текстаОтвет 501: в сети нет эмбеддинговых моделей.

Справочные адреса#

Отвечают без ключа. Таблица моделей с контекстом и статусом — в разделе Модели.

Метод и путьОписание
GET /v1/modelsСписок моделей: контекст, цены, поддерживаемые параметры — поля в формате OpenRouter.
GET /v1/models/{model}Карточка одной модели; слэш в id — как есть или %2F. Скрытая или неизвестная модель — 404 model_not_found.
GET /v1/capabilitiesВозможности шлюза: параметры, протоколы, плагины, поля стоимости и лимиты (limits).
GET /v1/pluginsПлагины: id и название.
GET /v1/network-statusСостояние моделей сети: доступность, задержки, аптайм.
GET /v1/nodesСводка пула нод: сколько всего, активных и в карантине.
GET /v1/web-search/enginesВключён ли веб-поиск и в каком состоянии его движки.

Anthropic Messages#

  • Базовый адрес — https://gate.joingonka.ai: SDK сам добавит /v1/messages.
  • Ключ — в заголовке x-api-key (так шлёт SDK Anthropic) или Authorization: Bearer.
  • Модели claude-* шлюз заменяет рекомендуемой (MiniMaxAI/MiniMax-M2.7); в поле model ответа остаётся имя, которое прислал клиент.
  • max_tokens обязателен, как в API Anthropic; больше потолка модели — срезается.
  • Стрим — события Anthropic; в паузах шлюз шлёт event: ping, сбой приходит событием event: error.
  • Рассуждения модели в ответ не попадают: блоков thinking нет.
  • Встроенный инструмент web_search исполняет плагин веб-поиска шлюза — см. раздел Плагины.
  • Подсчёта токенов (/v1/messages/count_tokens) нет — ответ 404.

Claude Code проще настроить установщиком — подключение инструментов. Вручную — переменными окружения; ANTHROPIC_MODEL закрепляет модель сети.

export ANTHROPIC_BASE_URL=https://gate.joingonka.ai
export ANTHROPIC_AUTH_TOKEN=$JOINGONKA_API_KEY
export ANTHROPIC_MODEL=MiniMaxAI/MiniMax-M2.7
claude

OpenAI Responses#

  • Шлюз не хранит ответы: присылайте всю историю в input. Поля previous_response_id и conversation — ошибка 400 с кодом.
  • store принимается и ничего не меняет.
  • Инструменты: function и web_search — его исполняет плагин веб-поиска. Другие встроенные инструменты шлюз пропускает, и запрос выполняется без них; требовать такой инструмент через tool_choice — ошибка 400.
  • Части input_image и input_file — ошибка 400: модели сети работают с текстом.
  • Адреса состояния (GET /v1/responses/{id}, DELETE /v1/responses/{id}, GET /v1/responses/{id}/input_items, POST /v1/responses/{id}/cancel, POST /v1/responses/compact) отвечают 404 с кодом — ответов шлюз не хранит.
  • Codex CLI: задайте свой id провайдера в model_provider (не openai) — тогда Codex сжимает историю сам, без /v1/responses/compact.

Legacy Completions#

  • prompt — строка или массив из одной строки; ответ — в choices[].text. Несколько промптов или токены вместо текста — ошибка 400.
  • suffix передаётся модели подсказкой в промпте: настоящего заполнения середины у сети нет.
  • В ответе logprobs: null; best_of игнорируется; echo работает.

Ключи и авторизация#

Ключ передаётся в заголовке Authorization: Bearer jg-… или x-api-key: jg-… — на всех адресах. Ключ создаётся после регистрации на странице gate.joingonka.ai/keys.

ПрефиксКлючЗапросы к моделям
jg-Обычный ключ аккаунтада
gc-Дочерний ключ: свои лимиты, расход — с баланса владельцада
gm-Управляющий ключ: только управление дочерниминет — 403 forbidden
  • Каждому ключу в кабинете можно задать лимит расходов на день, месяц и всего; превышение — 402 child_key_limit_exceeded.
  • Число запросов в минуту на ключ ограничено — значения в разделе Лимиты.
  • Без ключа работает только демо-чат на сайте: запрос без ключа из своего кода получит 402 с is_demo.
  • Ключами управляют только в кабинете: /api/keys с API-ключом недоступен. Баланс и расход по ключу — API аккаунта.

Ключ — секрет: не храните его в репозитории и в коде фронтенда, передавайте через переменные окружения.

Примеры#

Один и тот же запрос в четырёх SDK. Модель — рекомендуемая (MiniMaxAI/MiniMax-M2.7), ключ — из переменной окружения JOINGONKA_API_KEY.

import os
from openai import OpenAI

client = OpenAI(
    base_url="https://gate.joingonka.ai/v1",
    api_key=os.environ["JOINGONKA_API_KEY"],
)

response = client.chat.completions.create(
    model="MiniMaxAI/MiniMax-M2.7",
    messages=[{"role": "user", "content": "What is Gonka?"}],
)
print(response.choices[0].message.content)

Потоковый ответ#

import os
from openai import OpenAI

client = OpenAI(base_url="https://gate.joingonka.ai/v1", api_key=os.environ["JOINGONKA_API_KEY"])

stream = client.chat.completions.create(
    model="MiniMaxAI/MiniMax-M2.7",
    messages=[{"role": "user", "content": "What is Gonka?"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

Параметры запроса#

Параметры POST /v1/chat/completions, которые шлюз гарантирует сам, — список supported_parameters в ответе возможностей:

ПараметрОписание
temperatureСлучайность ответа: чем выше, тем разнообразнее.
top_pОтбор токенов по суммарной вероятности.
top_kОтбор из k самых вероятных токенов.
min_pОтсечка маловероятных токенов относительно самого вероятного.
frequency_penaltyШтраф за частые повторы.
presence_penaltyШтраф за уже встречавшиеся токены.
repetition_penaltyМножитель против повторов.
stopСтроки, на которых генерация останавливается.
seedЗерно для воспроизводимости.
max_tokensЛимит токенов ответа; больше потолка модели — срезается до потолка.
max_completion_tokensДругое имя max_tokens: шлюз переносит значение в него.
toolsФункции, которые модель может вызвать, в формате OpenAI.
tool_choiceВызывать ли функцию: на выбор модели, никогда, обязательно или конкретную.
response_formatСтруктурированный ответ: json_object или json_schema.
  • Без temperature шлюз подставляет 0.7.
  • Без max_tokens шлюз подставляет умолчание модели: без стрима — короче, в стриме — потолок модели. Числа по моделям — в разделе Лимиты.

Передаются в сеть как есть#

reasoning_effort, reasoning, enable_thinking, chat_template_kwargs, thinking_token_budget, min_tokens, logit_bias, n, parallel_tool_calls, extra_body. Шлюз их не проверяет: значение вне списка сети — ошибка 400 с типом api_error.

Не передаются в сеть#

Остальные поля шлюз принимает и не передаёт в сеть — например, user, metadata, store, logprobs, top_logprobs, thinking, stream_options, web_search_options. usage в стриме приходит всегда.

Стриминг#

  • stream: true — ответ событиями SSE; последнее событие — data: [DONE].
  • Перед завершением приходит чанк с usage — всегда, даже без stream_options.
  • В паузах шлюз каждые 15 с шлёт комментарий : keep-alive — SSE-клиенты его пропускают.
  • Пока поток не открыт, отказ приходит обычным кодом ответа; после открытия — чанком joingonka-error.
  • В delta.tool_calls — один вызов на чанк: склеенные сетью вызовы шлюз разрезает.
SSE
data: {"object":"chat.completion.chunk","model":"MiniMaxAI/MiniMax-M2.7","choices":[{"index":0,"delta":{"content":"Hi"},"finish_reason":null}]}

data: {"object":"chat.completion.chunk","model":"MiniMaxAI/MiniMax-M2.7","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: {"object":"chat.completion.chunk","model":"MiniMaxAI/MiniMax-M2.7","choices":[],"usage":{"prompt_tokens":12,"completion_tokens":2,"total_tokens":14}}

data: [DONE]

Служебные чанки шлюза#

Их можно узнать по полю id:

idКогда и что внутри
joingonka-errorСбой после открытия потока: поле error, затем обрыв без [DONE].
joingonka-stream-stalledСеть молчала дольше допустимой паузы: поток закрывается с finish_reason: stop.
joingonka-stream-unfinishedСеть оборвала генерацию: finish_reason: length — продолжите следующим запросом.
joingonka-citationsИсточники веб-поиска в delta.annotations — перед завершением.
joingonka-metaСтоимость и тайминги — только с заголовком x-joingonka-meta: 1.

Стрим в других протоколах#

  • Anthropic Messages: события от message_start до message_stop, в паузах event: ping, сбой — event: error.
  • OpenAI Responses: события response.*, сбой — response.failed.
  • Legacy Completions: при сбое — data: {"error": …}, затем [DONE].

Вызов инструментов#

  • Формат OpenAI: tools и tool_choice. Старый формат functions и function_call тоже принимается — ответ придёт в нём же.
  • В стриме — один вызов на чанк: клиенты, которые читают только первый элемент, не теряют вызовы.
  • Историю, на которой сеть ответила бы ошибкой 400, шлюз чинит: роль developer становится system, пустые и повторяющиеся id вызовов получают уникальные, arguments объектом превращается в строку JSON, пропущенный type дополняется, вызов без имени убирается вместе с результатом.
  • Вызов, который модель написала разметкой в тексте, шлюз переносит в tool_calls; ложные вызовы в ответе на запрос без инструментов убирает.
  • Генерация оборвалась посреди аргументов — придёт finish_reason: length, а не tool_calls: увеличьте лимит ответа.
JSON
{
  "model": "MiniMaxAI/MiniMax-M2.7",
  "messages": [{"role": "user", "content": "What is the weather in Paris?"}],
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "Current weather for a city",
      "parameters": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"]
      }
    }
  }]
}

Ограничения JSON-Schema#

Схемы инструментов и response_format сеть компилирует в грамматику; регулярные выражения — движком RE2. Шлюз приводит схему к форме, которую сеть примет:

  • $ref раскрываются на месте, разделы $defs и definitions удаляются; рекурсивная ссылка становится схемой без ограничений.
  • pattern с конструкциями, которых нет в RE2 (просмотр вперёд и назад, обратные ссылки, атомарные группы, сверхжадные квантификаторы), снимается; повторы больше 1000 сокращаются до 1000.
  • anyOf и oneOf из констант сворачиваются в enum; если несворачиваемых веток больше 16, объединение снимается.

Схема может стать мягче исходной — проверяйте аргументы вызова на своей стороне.

Структурированный ответ#

response_format: {"type": "json_object"} — ответ валидным JSON, {"type": "json_schema", "json_schema": {"name": …, "schema": …}} — по вашей схеме с ограничениями выше. Обрезанный JSON без стрима чинит плагин response-healing.

JSON
{
  "model": "MiniMaxAI/MiniMax-M2.7",
  "messages": [{"role": "user", "content": "Name three planets."}],
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "planets",
      "schema": {
        "type": "object",
        "properties": {"planets": {"type": "array", "items": {"type": "string"}}},
        "required": ["planets"]
      }
    }
  }
}

Рассуждения#

  • Рассуждения модели приходят отдельно от ответа: message.reasoning_content, в стриме — delta.reasoning_content. Поле reasoning шлюз переименовывает в этот формат.
  • Рассуждения тратят max_tokens: при маленьком лимите ответ обрывается (finish_reason: length) ещё до текста.
  • Если текста ответа нет, а рассуждения есть, шлюз переносит их в content — кроме ответов с вызовом инструмента.
  • reasoning_effort и reasoning.effort передаются в сеть. Если у модели только два режима, шлюз приводит значение к ним: none и minimal — к low, более высокие — к рассуждению по умолчанию.
  • Если нода отвергла значение, шлюз понижает его (max и xhigh → high, minimal → low, иначе снимает поле) и повторяет запрос.
  • В /v1/messages рассуждения не передаются — блоков thinking нет.

Плагины#

Плагины включаются полем plugins — массивом строк или объектов с опциями. Список — GET /v1/plugins.

ПлагинОписаниеУсловия
response-healingЧинит обрезанный JSON в ответе модели.Только без стрима и если ответ начинается с { или [.
privacy-sanitizationМаскирует в текстовых сообщениях email, IPv4, номера карт, JWT, 64-символьные hex-ключи и ключи вида sk-…, gw_…, gm-…, Bearer ….Режим — поле privacy_mode: redact (по умолчанию) или tokenize.
file-parserИзвлекает текст из PDF.Если текст сообщения целиком — PDF в base64: data:application/pdf;base64,… или без префикса.
webВеб-поиск: результаты подмешиваются в запрос, ответ получает ссылки на источники.Вместе с privacy-sanitization — ошибка 400.
  • Опции: max_results — от 1 до 10, по умолчанию 5; engine — подсказка движка; search_prompt — свой текст перед результатами; enabled: false — выключить поиск.
  • Источники — в message.annotations[].url_citation; в стриме — чанком joingonka-citations перед завершением.
  • mode: "agent" — модель сама решает, искать ли и что; max_searches — от 1 до 5, по умолчанию 3.
  • Оплата: в обычном режиме — только токены (результаты поиска входят во входные токены); в режиме агента — токены всех шагов плюс 1000 nGNK за каждый выполненный поиск (x_joingonka.web_search_surcharge_ngonka).
  • В Anthropic Messages и OpenAI Responses встроенный инструмент web_search исполняет этот же плагин в режиме агента.
{
  "model": "MiniMaxAI/MiniMax-M2.7",
  "messages": [{"role": "user", "content": "What is new in the Gonka network?"}],
  "plugins": [{"id": "web", "max_results": 5}]
}

Стоимость и служебные поля#

Ответ без стрима несёт стоимость запроса в usage:

ПолеОписание
usage.cost_gnkСтоимость запроса в GNK
usage.platform_fee_gnkИз неё — наценка платформы, GNK
usage.total_cost_gnkИтог к списанию в GNK
usage.total_cost_usdИтог в долларах по текущему курсу GNK
  • В стриме usage содержит только токены; стоимость — в чанке joingonka-meta.
  • С заголовком x-joingonka-meta: 1 ответ POST /v1/chat/completions получает блок x_joingonka: стоимость (cost_ngonka), баланс после списания (balance_ngonka, только без стрима) и тайминги (ttft_ms). Другие протоколы этот блок не отдают.
  • x-request-id — идентификатор запроса: приложите его к обращению в поддержку.
  • Retry-After приходит с 429: столько секунд подождать перед повтором.
  • Заголовки X-Title и HTTP-Referer (как у OpenRouter) помогают шлюзу узнать ваше приложение; их текст не сохраняется.

Ограничения#

  • Изображения: части image_url заменяются текстовой заглушкой — модель картинку не видит (vision: false в возможностях).
  • Из браузера API доступен только с доменов JoinGonka (проверка Origin): вызывайте его со своего сервера, ключ во фронтенд не кладите.
  • Эмбеддинги: POST /v1/embeddings отвечает 501 — в сети нет эмбеддинговых моделей.
  • Коды ошибок, лимиты и таймауты — в разделе Ошибки и лимиты.