Перейти к содержимому
Для команд разработки

API к моделям

OpenAI-совместимый API для ваших сервисов, агентов и инструментов разработки. Подходят официальные SDK OpenAI и любой инструмент, где можно указать свой адрес API: нужны только адрес, ключ команды и ID модели.

Адрес API

https://api.xwires.ai/v1

Ключи и ID моделей — в «Кабинет компании → API к моделям»
Содержание

01Что это

API к моделям — продукт xWires для команд разработки. Компания подключает его по заявке, а дальше админ компании сам создаёт в кабинете ключ каждой команде или сервису, задаёт лимиты трат и видит расход по каждому запросу. Запросы идут через шлюз xWires и списываются с баланса компании по её ценам. API совместим с API OpenAI: готовый код и инструменты работают, если поменять адрес, ключ и модель.

Вызвать модель можно двумя способами:

Chat CompletionsResponses
ПутьChat Completions/chat/completionsResponses/responses
В SDK OpenAIChat Completionsclient.chat.completions.create()Responsesclient.responses.create()
Что отправляетеChat Completionsmessages: сообщения с ролямиResponsesinput: сообщения или блоки
Поиск в интернетеChat CompletionsТолько своими функциями (function calling) на вашей сторонеResponsesВстроенный: инструмент web_search
Когда братьChat CompletionsЧат, генерация текста и кода, перенос готового кода с OpenAIResponsesОтветы со свежими данными из интернета, агенты

Какие модели xWires продаёт сейчас, сколько они принимают и что умеют — в раздел 4.

Это не API управления компанией. Тот нужен кадровой и учётной системам для подписок ChatGPT, у него свой адрес и свои ключи, и он описан в отдельном руководстве. Ключ API управления к моделям не подходит, и наоборот.

02Быстрый старт

  1. Админ компании открывает в xWires «Кабинет компании → API к моделям» и создаёт ключ команды: ключ показывается один раз. ID моделей — в таблице «Модели и цены» там же. Если API ещё не подключено, оставьте заявку на странице «API к моделям».
  2. Положите адрес, ключ и ID модели в переменные окружения сервера:
shell
export XWIRES_BASE_URL="https://api.xwires.ai/v1"
export XWIRES_API_KEY="ключ вашей команды из кабинета"
export XWIRES_MODEL="ID модели из кабинета"
  1. Отправьте первый запрос:
curl
curl "$XWIRES_BASE_URL/chat/completions" \
  -H "Authorization: Bearer $XWIRES_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "'"$XWIRES_MODEL"'",
    "messages": [
      {"role": "system", "content": "Ты — помощник разработчика. Отвечай кратко."},
      {"role": "user", "content": "Привет! Что ты умеешь?"}
    ]
  }'
Ответ 200, значения для примера
{
  "id": "0217923680000000000000000000000000000000000000000000",
  "object": "chat.completion",
  "created": 1792368000,
  "model": "<ID модели>",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Помогаю с разработкой: пишу, объясняю и отлаживаю код, отвечаю на технические вопросы.",
        "reasoning_content": "The user greets me and asks what I can do, in one short answer…"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 131,
    "completion_tokens": 184,
    "total_tokens": 315,
    "prompt_tokens_details": {
      "cached_tokens": 0
    },
    "completion_tokens_details": {
      "reasoning_tokens": 124
    }
  }
}

В агентах для программирования, LangChain и других инструментах выберите OpenAI-совместимого провайдера (OpenAI compatible) и укажите те же три значения: адрес API (base URL), ключ и ID модели. Код на Python и Node.js — в раздел 5.

03Адрес, ключ и модель

Адрес API

https://api.xwires.ai/v1 — базовый адрес, к которому добавляется путь: /chat/completions или /responses. Все запросы — HTTPS POST с телом JSON и заголовком Content-Type: application/json; список моделей — GET /models, одна модель по ID — GET /models/{model}. В SDK OpenAI адрес передаётся как base_url (Python) или baseURL (Node.js).

Описание API в формате OpenAPI 3.0 — openapi.json: адрес, ключ, пути, их поля и ошибки шлюза. Его берут генераторы клиентов, Postman и Insomnia.

Ключ

Ключ идёт в заголовке Authorization: Bearer каждого запроса и начинается с sk-xw-. Ключи создаёт админ компании в «Кабинет компании → API к моделям»: у каждой команды или сервиса свой, по нему виден расход и задаётся лимит трат. Целиком ключ показывается один раз, при создании; дальше в кабинете видно только его начало.

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

ID модели

Модель выбирается полем model в каждом запросе. ID модели — её имя у производителя, например claude-opus-5-5; тот же ID приходит в поле model ответа. ID моделей — в кабинете, в таблице «Модели и цены», вместе с ценами компании за 1 млн токенов. Модели, открытые ключу, отдаёт GET /models с ключом команды: у каждой контекст и предел вывода, цен в ответе нет. В примерах этого руководства ID берётся из переменной XWIRES_MODEL.

curl
curl "$XWIRES_BASE_URL/models" \
  -H "Authorization: Bearer $XWIRES_API_KEY"

Рассуждение перед ответом

Модели с рассуждением (раздел 4) сначала рассуждают, потом отвечают. Рассуждение приходит вместе с ответом: в Chat Completions — в message.reasoning (у части моделей — в message.reasoning_content), в Responses — отдельным элементом reasoning перед сообщением. Показывать его пользователю не обязательно, а язык у него бывает другим, чем у ответа. Токены рассуждения входят в токены ответа (completion_tokens, из них reasoning_tokens) и в предел max_tokens: если предел мал, модель потратит его на рассуждение и вернёт пустой ответ с finish_reason: length. Поэтому max_tokens не задавайте вовсе или оставляйте запас на сотни токенов.

04Модели

Моделей в продаже сейчас нет: они появятся здесь и в каталоге на странице «API к моделям». Модели, открытые ключу, — в «Кабинет компании → API к моделям» и в ответе GET /models, а цены компании — только в кабинете.

05Chat Completions

POST на адрес API с путём /chat/completions — тот же запрос, что у OpenAI, поэтому подходят официальные SDK и готовый код. Пример на curl — в раздел 2.

Параметры

ПараметрТипОбязательныйЧто значит
modelТипстрокаОбязательныйдаЧто значитID модели из кабинета
messagesТипмассивОбязательныйдаЧто значитДиалог по порядку: сообщения с role (system, user или assistant) и content
streamТиплогическийОбязательныйнетЧто значитtrue — ответ приходит по частям, событиями SSE, по мере того как модель его пишет. По умолчанию false
temperatureТипчислоОбязательныйнетЧто значитСлучайность ответа, обычно от 0 до 1: чем выше, тем разнообразнее ответ, чем ниже, тем предсказуемее
max_tokensТипцелоеОбязательныйнетЧто значитПредел токенов ответа вместе с рассуждением модели: слишком малый оставит ответ пустым

Python

Нужен официальный SDK OpenAI версии 1.0 или новее: pip install --upgrade "openai>=1.0".

Python 3.9+
import os

from openai import OpenAI

client = OpenAI(
    base_url=os.environ["XWIRES_BASE_URL"],
    api_key=os.environ["XWIRES_API_KEY"],
    timeout=120,
)
MODEL = os.environ["XWIRES_MODEL"]
messages = [
    {"role": "system", "content": "Ты — помощник разработчика. Отвечай кратко."},
    {"role": "user", "content": "Привет! Что ты умеешь?"},
]

# Ответ целиком
completion = client.chat.completions.create(model=MODEL, messages=messages)
print(completion.choices[0].message.content)
print(completion.usage)

# Ответ по частям, по мере того как модель его пишет
stream = client.chat.completions.create(model=MODEL, messages=messages, stream=True)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
print()

Node.js

Официальный SDK OpenAI: npm install openai.

Node.js 18+, модуль ES (.mjs)
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: process.env.XWIRES_BASE_URL,
  apiKey: process.env.XWIRES_API_KEY,
  timeout: 120_000,
});
const model = process.env.XWIRES_MODEL;
const messages = [
  { role: "system", content: "Ты — помощник разработчика. Отвечай кратко." },
  { role: "user", content: "Привет! Что ты умеешь?" },
];

// Ответ целиком
const completion = await client.chat.completions.create({ model, messages });
console.log(completion.choices[0].message.content);
console.log(completion.usage);

// Ответ по частям, по мере того как модель его пишет
const stream = await client.chat.completions.create({ model, messages, stream: true });
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
process.stdout.write("\n");

Ответ

  • choices[0].message.content — текст ответа, choices[0].message.reasoning — рассуждение модели перед ним.
  • choices[0].finish_reason — почему модель остановилась: stop — ответ закончен, length — ответ с рассуждением дошёл до max_tokens.
  • usage — токены запроса (prompt_tokens, из них взятые из кэша — prompt_tokens_details.cached_tokens), ответа (completion_tokens, из них рассуждение — completion_tokens_details.reasoning_tokens) и всего (total_tokens).
  • В ответе по частям сначала идут куски с choices[0].delta.reasoning, потом с текстом ответа в choices[0].delta.content; примеры выше печатают только текст. С "stream_options": {"include_usage": true} в запросе usage придёт в последнем куске, без него — не придёт. Этот кусок может нести и choices с finish_reason: берите usage из куска, где оно не null, а не по пустому choices; кусок без choices пропускайте, как в примерах.

06Responses и веб-поиск

POST на адрес API с путём /responses — интерфейс со встроенными инструментами на стороне сервера. Главный из них — поиск в интернете, web_search: модель сама ищет и отвечает со свежими данными, без вашего поискового API и цикла вызова функций.

Поиск есть не у каждой модели: у тех, где он есть, в кабинете в таблице «Модели и цены» стоит цена вызова поиска и предел поисков на запрос. Каждый поиск списывается по этой цене, а его результаты входят в токены ввода. Запрос с поиском к модели без него получает 400 unsupported_feature и ничего не стоит.

Из встроенных инструментов шлюз пропускает только поиск. Интерпретатор кода, поиск по файлам, генерация картинок, MCP-серверы и загрузка страниц получают 400 unsupported_feature у любой модели и тоже ничего не стоят. Свои функции, которые выполняет ваш код, работают как обычно, кроме загружаемых по требованию (defer_loading).

Параметры

ПараметрТипОбязательныйЧто значит
modelТипстрокаОбязательныйдаЧто значитID модели из кабинета
inputТипмассивОбязательныйдаЧто значитСообщения с role и content. content — строка или список блоков, например {"type": "input_text", "text": "…"}
toolsТипмассивОбязательныйнетЧто значитВстроенные инструменты. {"type": "web_search"} включает поиск в интернете
max_tool_callsТипцелоеОбязательныйнетЧто значитСколько поисков модель может сделать за запрос. Больше предела модели не выйдет: шлюз ставит его сам
streamТиплогическийОбязательныйнетЧто значитtrue — ответ по частям, событиями SSE. По умолчанию false

Python

Тот же SDK OpenAI: в input можно передать сообщения со строкой в content. В output ответа приходят рассуждение (элемент reasoning) и сообщение с блоком output_text, а свойство SDK output_text собирает из них только текст ответа.

Python 3.9+
import os

from openai import OpenAI

client = OpenAI(
    base_url=os.environ["XWIRES_BASE_URL"],
    api_key=os.environ["XWIRES_API_KEY"],
    timeout=120,
)

response = client.responses.create(
    model=os.environ["XWIRES_MODEL"],
    input=[{"role": "user", "content": "Какие новости в мире ИИ за эту неделю?"}],
    tools=[{"type": "web_search"}],
    max_tool_calls=2,
)
print(response.output_text)

curl, ответ по частям

В REST-запросе content — список блоков input_text. С stream: true ответ приходит событиями SSE.

curl
curl "$XWIRES_BASE_URL/responses" \
  -H "Authorization: Bearer $XWIRES_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "'"$XWIRES_MODEL"'",
    "stream": true,
    "tools": [{"type": "web_search"}],
    "max_tool_calls": 3,
    "input": [
      {
        "role": "user",
        "content": [{"type": "input_text", "text": "Какие новости в мире ИИ за эту неделю?"}]
      }
    ]
  }'

Поиски каждого запроса видны в «Расходе токенов» в кабинете, вместе с его токенами и списанной суммой.

07Ошибки

Ошибка приходит с кодом HTTP и телом, как у OpenAI: {"error": {"code": "…", "message": "…", "type": "…"}}. SDK OpenAI превращают её в исключение с этим кодом. Отказ шлюза — нет денег, лимит, ключ — приходит до модели, ничего не стоит и помечен заголовком X-Xwires-Refusal с его кодом. Ошибка самой модели приходит с её кодом и текстом, без этого заголовка, даже если код такой же, как у отказа шлюза. У каждого ответа есть заголовок X-Request-Id: если пишете нам, приложите его.

КодЧто случилосьЧто делать
400 Bad RequestЧто случилосьНеверный JSON, нет обязательного поля или недопустимое значение; unsupported_feature — модель не умеет того, что просит запрос, например поиск, или шлюз не пропускает встроенный инструментЧто делатьИсправьте запрос: повтор не поможет
401 UnauthorizedЧто случилосьinvalid_api_key — нет ключа, ключ неверный, заменён или отозван; expired_api_key — срок ключа вышелЧто делатьПроверьте заголовок Authorization: Bearer и ключ. Новый ключ админ компании создаёт в кабинете
402 Payment RequiredЧто случилосьinsufficient_balance — на балансе компании не осталось денегЧто делатьБаланс пополняет xWires по оплаченному счёту. Повтор не поможет, пока баланса нет
403 ForbiddenЧто случилосьspend_limit_exceeded — исчерпан лимит трат ключа или компании за день или месяц; model_not_allowed — модель не открыта ключу или компании; account_disabled — шлюз для компании закрытЧто делатьЛимиты меняет админ в кабинете; дневной лимит обновится в 00:00 UTC, месячный — 1-го числа. Если закрыт шлюз, напишите на support@xwires.ai
404 Not FoundЧто случилосьmodel_not_found — такой модели нет или она больше не продаётся; либо ID с провайдером, как goat-claude/claude-opus-5-5, — тогда новый ID в сообщении ошибки; либо ошибка в адресе или путиЧто делатьСверьте ID модели с кабинетом или GET /models
429 Too Many RequestsЧто случилосьrate_limit_exceeded — слишком много запросов или токенов в минуту на ключ; too_many_concurrent_requests — у компании слишком много запросов сразу, и за 10 секунд место не освободилосьЧто делатьПовторите через столько секунд, сколько в заголовке Retry-After, или с нарастающей паузой (раздел 8)
500, 502, 503Что случилосьСбой или перегрузка у модели; billing_unavailable — шлюз не может проверить балансЧто делатьПовторите с нарастающей паузой

08В продакшене

  • Таймаут. Для ответа целиком начните с 60–120 секунд и подстройте по своим запросам; модели с рассуждением на сложных задачах думают дольше. Длинный ответ лучше получать по частям (stream): первые слова придут сразу, а соединение не простаивает.
  • Повторы. 429, 500, 503 и обрыв соединения повторяйте с нарастающей паузой — 1, 2, 4, 8 секунд с небольшим случайным разбросом — и ограничьте число попыток. Если в ответе 429 есть Retry-After, ждите столько секунд, сколько в нём. 400, 401, 402, 403 и 404 повтором не исправить. SDK OpenAI повторяют такие ошибки сами, по умолчанию дважды (max_retries в Python, maxRetries в Node.js).
  • Учёт. Пишите usage из ответа в свои логи вместе с командой или сервисом и X-Request-Id: по нему запрос находится в «Расходе токенов» в кабинете. В ответе по частям usage придёт в последнем куске, если в запросе есть "stream_options": {"include_usage": true}.
  • Кэш. Агенты раз за разом отправляют одно и то же начало запроса: системный промпт, код, историю. Держите это начало неизменным, а то, что меняется, ставьте в конец: повторяющееся начало модель берёт из кэша, и такие токены стоят дешевле нового ввода. Кэш включается сам, а сколько токенов запроса пришло из него, показывает usage.prompt_tokens_details.cached_tokens.

09Расход и лимиты

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

Админ видит расход в «Кабинет компании → Расход токенов» через несколько секунд после ответа: траты за месяц в долларах и прогноз, баланс, по моделям и ключам и каждый запрос. Дни и месяцы считаются по UTC.

  • Лимиты трат. Админ задаёт их в «Кабинет компании → API к моделям»: на компанию или ключ, на все модели или одну, за день и за месяц. Запрос сверх лимита получает 403 spend_limit_exceeded.
  • Баланс. Запрос пускается, пока на балансе есть деньги, и дорабатывает до конца, даже если уводит баланс в минус. Пока баланс не больше нуля, запросы получают 402 insufficient_balance.
  • Обрыв. Если клиент ушёл посреди ответа, запрос списывается по оценке: ввод — по размеру запроса, вывод — по тому, что модель успела написать.
  • Запросы в минуту и одновременно. Когда у компании идёт столько запросов, сколько ей можно одновременно, следующий ждёт свободного места до 10 секунд и только потом получает 429 too_many_concurrent_requests. Если упираетесь в 429 или ждёте рост нагрузки, напишите на support@xwires.ai: сколько запросов в минуту и сколько одновременных запросов нужно в пике.

10Безопасность

  • Ключ — секрет компании: только на сервере, у каждой команды свой (раздел 3).
  • Ключ мог оказаться у посторонних — админ сразу заменяет или отзывает его в кабинете, а лимит трат на ключ ограничит ущерб, пока этого не заметили.
  • Вопросы о подключении, ключах и лимитах — на support@xwires.ai.