Баланс, расходы и цены в кабинете показываются в рублях с двумя знаками после запятой: 1 000,00 ₽, 999,99 ₽, 0,01 ₽. Ненулевая стоимость меньше копейки обозначается менее 0,01 ₽ — это не бесплатный запрос. Округляется только отображение; стоимость запросов рассчитывается точно и не повышается до минимальной платы за запрос.

Суммы в API

Тариф относится к модели и операции. После принятия запроса его цена сохраняется при безопасном переключении маршрута. Для медиа сначала рассчитывается стоимость выбранных настроек; её подтверждение предшествует запуску. Неизвестный результат поставщика требует сверки: повторная платная отправка автоматически не выполняется.

GET /v1/balance требует право balance:read. Числовой формат действующего API сохраняется для совместимости подключённых приложений. Для пользовательского интерфейса преобразуйте ответ в рубли через функцию ниже. Не используйте округлённый текст вместо точного значения при проверке лимитов и списании.

Пример принимает бюджет в рублях, сохраняет точное значение для API и форматирует денежные суммы для показа:

function rublesToApiUnits(rubles) {
  if (!/^\d+(?:\.\d{1,6})?$/.test(rubles)) {
    throw new Error('Введите рубли строкой с точкой и не более шести знаков');
  }
  const [whole, fraction = ''] = rubles.split('.');
  const amount = BigInt(whole) * 1_000_000n
    + BigInt(fraction.padEnd(6, '0'));
  if (amount > BigInt(Number.MAX_SAFE_INTEGER)) {
    throw new Error('Сумма превышает допустимый предел API');
  }
  return Number(amount);
}

function formatRubles(apiAmount) {
  if (!Number.isSafeInteger(apiAmount) || apiAmount < 0) {
    throw new Error('Ожидается неотрицательная целая сумма API');
  }
  const amount = BigInt(apiAmount);
  if (amount > 0n && amount < 10_000n) return '<0,01 ₽';
  const cents = (amount + 5_000n) / 10_000n;
  return String(cents / 100n) + ',' + String(cents % 100n).padStart(2, '0') + ' ₽';
}

const budgetRub = '10.00';
const maxCostApi = rublesToApiUnits(budgetRub);
console.log(formatRubles(maxCostApi)); // 10,00 ₽
console.log(formatRubles(999750)); // 1,00 ₽
console.log(formatRubles(1)); // <0,01 ₽

Для показа используйте formatRubles, отправляйте исходное целое число. Не рассчитывайте платёж из форматированной строки. Код выше подходит для шага с JavaScript в Kvantora Flow.

Резерв и списание

Перед платным запросом сервис резервирует верхнюю оценку. После подтверждённого результата списывает фактическую сумму один раз и освобождает остаток. Вы платите только за полученный результат. Если модель не вернула результат и у поставщика нет подтверждения выполнения, резерв автоматически возвращается на баланс через 5 минут, для медиа с живым заданием поставщика — до 3 часов.

Для текста используйте POST /v1/chat/quote с тем же телом, которое готовите для /v1/chat/completions: model, messages, max_tokens и при необходимости max_cost_microrub. Ответ содержит estimated_cost_microrub, input_tokens_estimate, max_output_tokens, expires_at, reservation_created=false и estimation_only=true. Оценка входа приблизительная; фактические токены определяются после выполнения. Для моделей с рассуждениями оценка включает токены рассуждений: они тарифицируются как выходные токены по цене вывода модели. Оценка — это удержание, а не цена: списывается фактическая сумма, и она не превышает оценку, которую вы видели в quote. Quote не создаёт резерв, историю или вызов модели.

Оценка действует 30 секунд и не фиксирует цену до отправки. Запрос генерации заново проверяет текущую оценку и max_cost_microrub; при превышении предела возвращает HTTP 409 до платного вызова. Слишком маленький предел в самой оценке также даёт HTTP 409. Полный путь показан в быстром старте.

Для медиа и экспертных операций единица тарификации зависит от модели: запрос, изображение, страница, файл, документ, символы или длительность. Проверяйте unit и quantity в опубликованном тарифе. POST /v1/quotes рассчитывает стоимость выбранных параметров и возвращает estimated_cost_microrub, expires_at и reservation_created=false. Можно передать оценку без изменений в max_cost_microrub либо задать собственный предел через rublesToApiUnits(budgetRub). Если текущая цена выше предела, запрос не отправится. Операция без подтверждённого тарифа остаётся недоступной для запуска.

Оценка запроса медиа

В оценку передайте параметры будущей генерации и нужную operation. Этот запрос не создаёт задание и не резервирует деньги.

const parameters = {
  model: process.env.KVANTORA_MODEL_ID,
  prompt: 'Лесное озеро на рассвете',
  n: 1,
};
const response = await fetch(process.env.KVANTORA_BASE_URL + '/v1/quotes', {
  method: 'POST',
  redirect: 'error',
  headers: {
    Authorization: 'Bearer ' + process.env.KVANTORA_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ ...parameters, operation: 'image_generation' }),
});
if (!response.ok) throw new Error('Оценка не получена: HTTP ' + response.status);
const quote = await response.json();
console.log(formatRubles(quote.estimated_cost_microrub));

Функция formatRubles определена выше. Проверяйте expires_at перед отправкой. Для генерации передайте parameters и точное max_cost_microrub, но не добавляйте operation: её задаёт endpoint. Оценка не гарантирует доступность модели к моменту отправки.

История расходов

GET /v1/usage?days=30 требует usage:read. requests считает принятые запросы проекта; spent суммирует подтверждённые списания по времени их завершения. Резервы не входят в spent. Период начинается по календарным дням в billing_timezone организации и заканчивается as_of.

Команда, счета и документы в кабинете

В переключателе слева выберите «Добавить организацию» и укажите название компании или ИП. Она получит отдельный кабинет с нулевым балансом. Личный кабинет, другие компании, их деньги, ключи и история останутся на своих местах. Переключатель показывает баланс каждого доступного пространства; личное пространство можно открыть через пункт «Личный кабинет».

В выбранной компании откройте «Организация» и заполните реквизиты. Если поле не прошло проверку, рядом с ним появится причина, а введённые данные останутся в форме. ОГРН и ИНН — разные номера. После сохранения владелец или администратор может открыть «Документы» и выставить счёт на сумму от 1 000 до 10 000 000 ₽. Участники команды могут просматривать документы, но не выставлять счета.

Счёт открывается как печатная форма. Кнопка «PDF» вызывает окно печати браузера: выберите «Сохранить как PDF». Само выставление счёта не пополняет баланс. Оплатить счёт можно двумя способами. Кнопка «Оплатить картой или СБП» на странице счёта или в списке документов открывает защищённую страницу Robokassa: после оплаты баланс пополняется автоматически, а счёт отмечается оплаченным. Онлайн-оплату счёта запускают владелец, администратор и финансы организации. Банковский перевод по реквизитам счёта зачисляет администратор платформы после поступления денег на расчётный счёт; повторное подтверждение того же перевода деньги не зачисляет. Если один счёт оплатили обоими способами, на баланс зачисляются обе суммы, а счёт считается оплаченным один раз. ЭДО нужен только для обмена документами: оплатить счёт через оператора ЭДО нельзя.

Акты за завершённые месяцы с расходами формируются при открытии раздела «Документы». Период определяется временем проведения списания и расчётной часовой зоной организации. После первого акта смена этой часовой зоны недоступна: это защищает состав уже закрытых периодов. В расчёт входят списания за модели и автоматизации. Для поиска старых документов используйте «Назад» и «Далее». Оператор и ID участника ЭДО сохраняются в реквизитах; автоматической отправки подписанных документов через оператора ЭДО пока нет.

В корпоративном кабинете в разделе «Организация → Команда» владелец приглашает администраторов и участников; администратор приглашает только участников. Письмо приходит от Kvantora (accounts@kvantora.ai), содержит организацию, назначенную роль и срок действия ссылки. Принять приглашение можно в течение семи дней, войдя или зарегистрировавшись с почтой получателя. Повторное приглашение на ту же почту заменяет предыдущую ссылку.

Если сервис не подтвердил отправку письма, кабинет покажет предупреждение и ссылку для ручной передачи сотруднику. Подтверждение отправки сервисом не гарантирует попадание во «Входящие»: проверьте также папку «Спам». Если ссылка истекла или отозвана, попросите новое приглашение.