API совместим с OpenAI Chat Completions: подходят OpenAI SDK и любые программы, в которых можно указать адрес OpenAI-совместимого API.
https://artaill.ru/api/gateway/v1Authorization: Bearer … с API-ключомAPI-ключ создаётся в кабинете: для него выбирают доступные модели и месячный бюджет. Ключ показывается один раз — сохраните его. Запросы оплачиваются с баланса аккаунта в пределах бюджета ключа.
Пути указаны относительно Base URL.
POST /chat/completionsGET /modelsGET /models/{id} — одна модель.Цены — на странице моделей. Каталог в JSON с ролями сообщений и параметрами каждой модели — /api/gateway/catalog, ключ для него не нужен.
Потерянный ключ восстановить нельзя: создайте новый и отзовите прежний. Отозванный ключ не принимает новые запросы; уже принятые завершаются и оплачиваются.
Месячный бюджет ограничивает расходы ключа за календарный месяц по UTC, включая текущие резервы. Пустое поле — без ограничения, 0 запрещает расход.
Выберите модель, разрешённую вашему ключу.
Загружаем примеры…
Текст ответа — в choices[0].message.content, число токенов — в usage. Стоимость запроса видна в журнале запросов.
{
"choices": [{
"index": 0,
"message": {"role": "assistant", "content": "Привет! Чем помочь?"},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 8,
"total_tokens": 20
}
}
finish_reason: "length" — ответ достиг предела вывода, "content_filter" — сработала фильтрация. В обоих случаях текст или JSON могут быть оборваны.
Справочники SDK: Python и JavaScript / TypeScript.
Историю диалога хранит и передаёт ваше приложение. Artaill не сохраняет тексты запросов и ответов; правила обработки у поставщика модели могут отличаться — подробнее в политике конфиденциальности.
modelmessagesrole и content; допустимые роли зависят от модели.max_tokens или max_completion_tokensstreamtrue — ответ потоком SSE, по умолчанию false. Чтобы получить usage в потоке, добавьте stream_options: {"include_usage": true}.У моделей с рассуждениями в предел вывода могут входить токены рассуждений: при слишком маленьком пределе ответ может остаться без текста. Вход вместе с пределом вывода должен помещаться в контекст модели.
Неизвестный или не поддерживаемый моделью параметр отклоняется с ошибкой 400 до вызова модели; такой запрос не оплачивается.
Модели поддерживают разные наборы параметров; список для каждой — в JSON-каталоге. Если параметр не указан, действует настройка провайдера.
temperature, top_ppresence_penalty, frequency_penaltystopreasoning_effortseed, logit_biaslogprobs, top_logprobslogprobs: true включает вероятности токенов. top_logprobs — целое число от 0 до 20, только вместе с ним.n1.storefalse.Изображения принимают не все модели — это видно в каталоге. Поддержку response_format и tools показывает JSON-каталог.
Сообщение пользователя может быть массивом частей с текстом и изображениями. Изображение передаётся ссылкой HTTPS, доступной провайдеру, или data URL вида data:image/png;base64,….
{
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "Что изображено на фото?"},
{"type": "image_url", "image_url": {"url": "https://example.com/photo.jpg"}}
]
}]
}
До 8 изображений в запросе. В base64 принимаются PNG, JPEG, WebP и GIF, суммарно до 10 MiB до кодирования. В image_url можно задать detail: "auto", "low" или "high".
Добавьте в запрос response_format со схемой и опишите в сообщении, какие данные нужны. Например, краткий пересказ:
{
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "summary",
"strict": true,
"schema": {
"type": "object",
"properties": {"summary": {"type": "string"}},
"required": ["summary"],
"additionalProperties": false
}
}
}
}
JSON приходит строкой в message.content. Перед разбором проверьте finish_reason и отказ в message.refusal. Какие конструкции схемы поддерживаются, зависит от модели. Для JSON без схемы укажите {"type": "json_object"} и явно попросите JSON в сообщении.
Опишите функции в tools. Например, получение статуса заказа:
{
"tools": [{
"type": "function",
"function": {
"name": "get_order_status",
"description": "Узнать статус заказа по номеру",
"parameters": {
"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"],
"additionalProperties": false
}
}
}],
"tool_choice": "auto"
}
При finish_reason: "tool_calls" вызовы приходят в message.tool_calls; функции выполняет ваш код. В следующий запрос добавьте полученное сообщение assistant целиком и результат каждого вызова с его ID:
{"role": "tool", "tool_call_id": "ID из tool_calls", "content": "{\"status\":\"shipped\"}"}
tool_choice принимает "auto", "none", "required" или {"type":"function","function":{"name":"get_order_status"}}. parallel_tool_calls: false запрещает несколько вызовов в одном ответе. Эти параметры тоже должны поддерживаться моделью. Каждый запрос в цепочке вызовов оплачивается отдельно.
Пример — в первом запросе, вариант «Поток · SSE».
Успешный поток заканчивается строкой data: [DONE]. С include_usage перед ней приходит отдельное событие с choices: [] и usage — уже после finish_reason, поэтому читайте поток до конца. Если провайдер не сообщил полный отчёт о токенах, usage равен null.
Ошибка после начала потока приходит событием data: {"error": {...}}, затем соединение закрывается без [DONE]. HTTP-статус к этому моменту уже 200, поэтому успешное завершение определяет только [DONE].
Текст приходит в choices[0].delta.content, фрагменты вызовов функций — в delta.tool_calls: собирайте их по index и разбирайте function.arguments как JSON, когда вызов завершён. Строки, начинающиеся с :, — комментарии.
429 также возможен при общей нагрузке на сервис. Заголовок Retry-After, если он есть, указывает, через сколько секунд повторить запрос.
Ошибка до начала ответа приходит с HTTP-статусом и JSON-объектом error с полями code, type, message и param. Обрабатывайте ошибки по code: текст message может меняться.
insufficient_balance — не хватает средств на балансе; key_budget_exceeded — бюджета ключа; key_reservation_exceeded — резерв больше предела ключа на один запрос. Резерв считается по входу и пределу вывода, их уменьшение его снижает.model_not_allowed — модель не разрешена ключу; cross_origin_denied — запрос из браузера с другого сайта.request_already_accepted — запрос с этим Idempotency-Key уже принят. Ответ содержит его ID и ссылку на состояние.Retry-After.accounting_pending — расчёт ещё не завершён.Ответ на принятый запрос содержит заголовок X-Request-ID. По этому ID состояние и стоимость запроса видны в журнале и через GET /api/gateway/requests/{id} с тем же API-ключом. Текст ответа там не хранится.
Работа модели оплачивается и при ошибке или обрыве соединения. Без заголовка Idempotency-Key каждый POST — новый вызов модели, поэтому повторы SDK в примерах отключены. После сбоя сначала проверьте состояние запроса.
Idempotency-Key защищает от повторного выполнения: передайте уникальное значение для каждой операции, от 1 до 128 печатных ASCII-символов без пробелов. Значение действует 24 часа с момента принятия запроса, даже если тот завершился ошибкой. Повтор с тем же значением и API-ключом модель не вызывает: сервис вернёт 409 с request_id и status_url в JSON и заголовком Location. Тело запроса не сравнивается, прежний ответ не возвращается.
Цены указаны за миллион токенов, оплачивается фактическое число токенов. Цена за запрос, если она есть, добавляется к стоимости токенов. Чтение и запись кэша оплачиваются по своим тарифам, когда модель сообщает эти данные.
При принятии запроса фиксируются тариф и курс, а на балансе резервируются средства по размеру входа и пределу вывода. После расчёта неиспользованный резерв возвращается.
Предел резерва и месячный бюджет проверяются при принятии запроса и не ограничивают итоговую цену: она может превысить резерв. Если модель не сообщила полный отчёт о токенах, стоимость считается по оценке.
В метаданных запроса price_rub — полная цена, charged_rub — списано с баланса, held_rub — ещё удерживается. Пока accounting: "pending", нулевое списание не значит, что запрос бесплатный — дождитесь расчёта. Цена по оценке помечена estimated, основание — в basis.