Для ШІ-агентів: покрокова інструкція з налаштування — /docs/agents.md, індекс документації — /llms.txt.
Довідник API
Усе про запити до шлюзу: протоколи, адреси, ключі та параметри. Нижче — стримінг, виклик інструментів, міркування, плагіни та вартість запиту у відповіді.
Протоколи та адреси#
Шлюз приймає формати OpenAI та Anthropic. Базова адреса для SDK OpenAI — https://gate.joingonka.ai/v1, для SDK Anthropic — https://gate.joingonka.ai. Усі протоколи працюють на одному ключі й одному балансі: запит у будь-якому форматі йде одним і тим самим шляхом.
| Метод і шлях | Формат | Для чого | Особливості |
|---|---|---|---|
POST /v1/chat/completions | OpenAI Chat Completions | Чат, агенти, виклик інструментів | Основний шлях: інші формати шлюз перекладає в нього. |
POST /v1/messages | Anthropic Messages | Claude Code та SDK Anthropic | Базова адреса без /v1; моделі claude-* замінюються рекомендованою; поле max_tokens обов'язкове. |
POST /v1/responses | OpenAI Responses | Codex CLI та нові SDK OpenAI | Без стану: історію надсилайте повністю в кожному запиті. |
POST /v1/completions | OpenAI Completions (legacy) | Автодоповнення та правка коду в редакторах | suffix передається моделі підказкою; у відповіді logprobs: null. |
POST /v1/embeddings | OpenAI 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
claudecurl https://gate.joingonka.ai/v1/messages \
-H "x-api-key: $JOINGONKA_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "MiniMaxAI/MiniMax-M2.7",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "What is Gonka?"}]
}'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 OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://gate.joingonka.ai/v1",
apiKey: process.env.JOINGONKA_API_KEY,
});
const response = await client.chat.completions.create({
model: "MiniMaxAI/MiniMax-M2.7",
messages: [{ role: "user", content: "What is Gonka?" }],
});
console.log(response.choices[0].message.content);curl https://gate.joingonka.ai/v1/chat/completions \
-H "Authorization: Bearer $JOINGONKA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "MiniMaxAI/MiniMax-M2.7",
"messages": [{"role": "user", "content": "What is Gonka?"}]
}'import os
import anthropic
client = anthropic.Anthropic(
base_url="https://gate.joingonka.ai",
api_key=os.environ["JOINGONKA_API_KEY"],
)
message = client.messages.create(
model="MiniMaxAI/MiniMax-M2.7",
max_tokens=1024,
messages=[{"role": "user", "content": "What is Gonka?"}],
)
print(message.content[0].text)Потокова відповідь#
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)import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://gate.joingonka.ai/v1", apiKey: process.env.JOINGONKA_API_KEY });
const stream = await client.chat.completions.create({
model: "MiniMaxAI/MiniMax-M2.7",
messages: [{ role: "user", content: "What is Gonka?" }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}curl -N https://gate.joingonka.ai/v1/chat/completions \
-H "Authorization: Bearer $JOINGONKA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "MiniMaxAI/MiniMax-M2.7",
"messages": [{"role": "user", "content": "What is Gonka?"}],
"stream": true
}'import os
import anthropic
client = anthropic.Anthropic(base_url="https://gate.joingonka.ai", api_key=os.environ["JOINGONKA_API_KEY"])
with client.messages.stream(
model="MiniMaxAI/MiniMax-M2.7",
max_tokens=1024,
messages=[{"role": "user", "content": "What is Gonka?"}],
) as stream:
for text in stream.text_stream:
print(text, 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— один виклик на чанк: склеєні мережею виклики шлюз розрізає.
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: збільште ліміт відповіді.
{
"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.
{
"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}]
}{
"model": "MiniMaxAI/MiniMax-M2.7",
"messages": [{"role": "user", "content": "What is new in the Gonka network?"}],
"plugins": [{"id": "web", "mode": "agent", "max_searches": 3}]
}Вартість і службові поля#
Відповідь без стріму містить вартість запиту в 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— у мережі немає ембедингових моделей. - Коди помилок, ліміти й таймаути — у розділі Помилки та ліміти.