hubris

Management API

Управление аккаунтом по API — ключи, баланс, расход, транзакции. Для скриптов, сервисов поверх Hubris и агентов.

Management API позволяет управлять аккаунтом программно, без захода в личный кабинет: создавать и отзывать API-ключи, ставить лимиты, смотреть баланс, расход и историю операций.

Типовые сценарии:

  • Скрипты и мониторинг — проверить баланс перед ночным батчем, отправить уведомление «пора пополнить», отозвать утёкший ключ одной командой.
  • Свой сервис поверх Hubris — выдавать по отдельному ключу каждому своему клиенту, ставить лимит расхода в рублях (в день, неделю, месяц или на весь срок ключа), отключать неплательщиков и сверять расход по каждому ключу.
  • Агенты и автоматизации — агент своим же рабочим ключом узнаёт лимит, потраченное и баланс через GET /v1/key и сам решает, хватит ли на задачу.

Два типа ключей

Обычный ключManagement-ключ
Форматsk-gw-…sk-gw-mgmt-…
Вызов моделей (/v1/chat/completions и др.)❌ (403)
Управление ключами, баланс, транзакции❌ (403)
GET /v1/key (самоинтроспекция)
Как создаётсяВ кабинете или через POST /v1/keysТолько в кабинете на /management-keys

Разделение сделано намеренно: обычные ключи живут на серверах и в агентах — если такой ключ утёк, злоумышленник может только тратить (и упирается в лимит расхода ключа), но не может создавать ключи или читать историю платежей. Management-ключ храните как пароль: не передавайте в клиентский код, агентам и третьим лицам.

Если management-ключ скомпрометирован: отзовите его в кабинете на /management-keys, затем проверьте GET /v1/keys — не появились ли созданные без вас ключи (у них в кабинете видно время создания), и отзовите лишние.

Лимиты

ЛимитЗначение
Запросы к management-эндпоинтам60 в минуту на аккаунт
Создание ключей (POST /v1/keys)30 в час
Активных ключей на аккаунт500

Превышение — 429 с кодом rate_limit_exceeded (или key_quota_exceeded для потолка ключей).

Ключи — /v1/keys

Все эндпоинты этого раздела требуют management-ключ: Authorization: Bearer sk-gw-mgmt-…. Обычный ключ получит 403 management_key_required.

Список ключей

GEThttps://api.hubris.pw/v1/keys

Query-параметры: offset (по умолчанию 0), limit (1–100, по умолчанию 100). Возвращаются только активные обычные ключи — management-ключи и отозванные в список не попадают.

{
  "object": "list",
  "data": [
    {
      "id": "3f1c9b2e-…",
      "name": "Клиент А",
      "key_prefix": "sk-gw-ab12...cd34",
      "disabled": false,
      "limit_kopecks": 20000,
      "limit_period": "month",
      "spent_period_kopecks": 512,
      "period_reset_at": "2026-08-31T21:00:00.000Z",
      "daily_limit_kopecks": null,
      "spent_24h_kopecks": 512,
      "read_only": false,
      "allowed_ips": null,
      "privacy_mask_default": "inherit",
      "last_used_at": "2026-07-16T09:00:00.000Z",
      "created_at": "2026-07-01T12:00:00.000Z"
    }
  ],
  "has_more": false
}

Полное значение ключа не возвращается никогда — только маскированный key_prefix.

Защита от всплеска: spike_limit_kopecks, spike_window_minutes, spike_cooldown_minutes (см. описание); состояние — disabled_reason (manual — отключён вручную, spike — заморожен, null — включён) и disabled_until (когда включится сам). Замороженный ключ на любой запрос отвечает 401 key_frozen_spike.

Привязка к адресу: allowed_ips — адреса и подсети (CIDR), с которых ключ принимает запросы; null — с любого адреса. Запрос с чужого адреса получает 403 key_ip_not_allowed до обращения к модели (см. описание).

Поля лимита: limit_kopecks — лимит расхода в копейках (null — без лимита), limit_period — период сброса (day — календарные сутки по Москве, week — с понедельника, month — с 1-го числа, none — без сброса, лимит на весь расход ключа), spent_period_kopecks — потрачено в текущем периоде, period_reset_at — момент следующего сброса (null при none). Поля daily_limit_kopecks и spent_24h_kopecks устарели: первое равно limit_kopecks только при limit_period: "day" (иначе null), второе всегда равно spent_period_kopecks.

Создать ключ

POSThttps://api.hubris.pw/v1/keys
ПолеТипОписание
namestring (1–100)Название ключа — например, имя вашего клиента или сервиса.
limit_kopecksnumber | nullЛимит расхода в копейках за период limit_period, максимум 10 000 000 (100 000 ₽). Не указан или null — без лимита.
limit_period"day" | "week" | "month" | "none"Период сброса лимита; по умолчанию day. none — без сброса, лимит на весь расход ключа.
daily_limit_kopecksnumber | nullУстаревшее: то же, что limit_kopecks с limit_period: "day". Вместе с limit_kopecks не передавать — 400.
read_onlybooleanКлюч только для чтения: каталог моделей, баланс и статистика доступны, а всё, что тратит баланс, отвечает 403 key_read_only. По умолчанию false. Удобен для дашбордов и мониторинга — утечка такого ключа ничего не стоит.
allowed_ipsstring[] | nullПривязка к адресу: до 32 записей — IPv4/IPv6-адрес или подсеть (CIDR), например ["203.0.113.5", "198.51.100.0/24"]. Не указано, null или [] — с любого адреса. Невалидная запись — 400 invalid_allowed_ips с перечнем в сообщении, больше 32 — 400 too_many_allowed_ips.
privacy_mask_default"inherit" | "off" | "on" | "required"Режим маскирования данных для запросов этим ключом.

Ответ 201 — та же форма, что в списке, плюс поле key с полным значением ключа. Оно показывается один раз — сохраните сразу, повторно получить нельзя.

curl -s https://api.hubris.pw/v1/keys \-H "Authorization: Bearer $HUBRIS_MGMT_KEY" \-H "Content-Type: application/json" \-d '{"name": "Клиент А", "limit_kopecks": 20000, "limit_period": "month"}'
import os, requestsr = requests.post(  "https://api.hubris.pw/v1/keys",  headers={"Authorization": f"Bearer {os.environ['HUBRIS_MGMT_KEY']}"},  json={"name": "Клиент А", "limit_kopecks": 20000, "limit_period": "month"},  # 200 ₽ в месяц)created = r.json()client_key = created["key"]  # показывается только здесь — сохраните
const r = await fetch("https://api.hubris.pw/v1/keys", {method: "POST",headers: {  Authorization: `Bearer ${process.env.HUBRIS_MGMT_KEY}`,  "Content-Type": "application/json",},body: JSON.stringify({ name: "Клиент А", limit_kopecks: 20000, limit_period: "month" }),});const created = await r.json();const clientKey = created.key; // показывается только здесь — сохраните

Один ключ

GEThttps://api.hubris.pw/v1/keys/{id}

Та же форма, что элемент списка. Чужой, отозванный или management-ключ — 404 not_found.

Изменить ключ

PATCHhttps://api.hubris.pw/v1/keys/{id}

Частичное обновление — передайте хотя бы одно поле:

ПолеОписание
nameПереименовать.
disabledtrue — временно отключить (ключ получает 401 на любой запрос), false — включить обратно. Обратимо.
limit_kopecksНовый лимит расхода; null — снять лимит.
limit_periodНовый период сброса: day, week, month, none. Можно менять отдельно от суммы.
daily_limit_kopecksУстаревшее: то же, что limit_kopecks + limit_period: "day".
read_onlytrue — ключ только для чтения (запросы к моделям — 403 key_read_only), false — обычный. Обратимо.
allowed_ipsПривязка к адресу: новый список целиком (адреса и подсети CIDR); null или [] — снять привязку. Невалидный список — 400, остальные поля того же запроса не применяются.
spike_limit_kopecksЗащита от всплеска: порог расхода в копейках за окно; null — выключить.
spike_window_minutesОкно защиты: 1, 5, 15, 30 или 60. По умолчанию 15.
spike_cooldown_minutesПериод охлаждения: 15, 60, 360, 1440 — ключ включится сам через столько минут; null — до ручного включения.
privacy_mask_defaultРежим маскирования данных.

Ответ — обновлённый ключ. Типовой приём для сервиса поверх Hubris: клиент не оплатил период — {"disabled": true}, оплатил — {"disabled": false}.

Отозвать ключ

DELETEhttps://api.hubris.pw/v1/keys/{id}

Необратимо. Ответ {"id": "…", "deleted": true}; повторный вызов по уже отозванному ключу тоже вернёт 200 (идемпотентно). Для временной блокировки используйте PATCH с disabled: true.

Баланс — GET /v1/credits

GEThttps://api.hubris.pw/v1/credits

Требует management-ключ.

{
  "data": {
    "balance_kopecks": 152030,
    "bonus_balance_kopecks": 5000,
    "currency": "RUB"
  }
}

152030 копеек = 1520,30 ₽. Бонусный баланс — невыводимые кредиты (реферальные начисления и акции).

Текущий ключ — GET /v1/key

GEThttps://api.hubris.pw/v1/key

Самоинтроспекция: работает обычным ключом — management-ключ не нужен. Главная ручка для агентов: один запрос своим же рабочим ключом — и агент знает свой лимит, расход за сутки и баланс аккаунта.

{
  "data": {
    "name": "prod-bot",
    "key_prefix": "sk-gw-ab12...cd34",
    "key_type": "inference",
    "disabled": false,
    "limit_kopecks": 20000,
    "limit_period": "day",
    "spent_period_kopecks": 512,
    "period_reset_at": "2026-07-16T21:00:00.000Z",
    "daily_limit_kopecks": 20000,
    "spent_24h_kopecks": 512,
    "balance_kopecks": 152030,
    "created_at": "2026-07-01T12:00:00.000Z"
  }
}
curl -s https://api.hubris.pw/v1/key \-H "Authorization: Bearer $HUBRIS_API_KEY"
import os, requestsr = requests.get(  "https://api.hubris.pw/v1/key",  headers={"Authorization": f"Bearer {os.environ['HUBRIS_API_KEY']}"},)data = r.json()["data"]if data["balance_kopecks"] < 30_000:  # меньше 300 ₽  print("Пора пополнить баланс")
const r = await fetch("https://api.hubris.pw/v1/key", {headers: { Authorization: `Bearer ${process.env.HUBRIS_API_KEY}` },});const { data } = await r.json();if (data.balance_kopecks < 30_000) console.log("Пора пополнить баланс");

Транзакции — GET /v1/transactions

GEThttps://api.hubris.pw/v1/transactions

Требует management-ключ. Пополнения, списания, возвраты и бонусные операции, свежие сверху — удобно для сверки и бухгалтерии.

Query-параметры: offset, limit (1–100, по умолчанию 50), type (например, topup, usage, refund), from/to (ISO 8601).

{
  "object": "list",
  "data": [
    {
      "id": "9d2e4c11-…",
      "type": "topup",
      "status": "succeeded",
      "amount_kopecks": 100000,
      "balance_after_kopecks": 152030,
      "payment_method": "sbp",
      "created_at": "2026-07-15T10:00:00.000Z"
    }
  ],
  "has_more": true
}

Положительный amount_kopecks — зачисление, отрицательный — списание. payment_method (sbp / card / invoice) заполнен только у пополнений.

Расход по всем ключам — GET /v1/usage

Обычный вызов /v1/usage показывает расход только того ключа, которым сделан запрос. Management-ключом тот же эндпоинт видит весь аккаунт и получает два дополнительных параметра:

ПараметрОписание
key_idСузить до одного ключа (UUID из GET /v1/keys).
group_bykey — добавить массив by_key (расход каждого ключа), model — массив by_model.
# кто из клиентов сколько потратил за месяцcurl -s "https://api.hubris.pw/v1/usage?period=30d&group_by=key" \-H "Authorization: Bearer $HUBRIS_MGMT_KEY"
import os, requestsr = requests.get(  "https://api.hubris.pw/v1/usage",  params={"period": "30d", "group_by": "key"},  headers={"Authorization": f"Bearer {os.environ['HUBRIS_MGMT_KEY']}"},)for row in r.json()["by_key"]:  rub = int(row["cost_kopecks"]) / 100  print(f"{row['name']}: {row['requests']} запросов, {rub:.2f} ₽")
const r = await fetch("https://api.hubris.pw/v1/usage?period=30d&group_by=key",{ headers: { Authorization: `Bearer ${process.env.HUBRIS_MGMT_KEY}` } },);const { by_key } = await r.json();for (const row of by_key) {console.log(`${row.name}: ${row.requests} запросов, ${Number(row.cost_kopecks) / 100} ₽`);}

В by_key[]: key_id, key_prefix, name, requests, total_tokens, cost_kopecks (строка, копейки). В by_model[]: model, requests, prompt_tokens, completion_tokens, cost_kopecks.

HTTP-коды

КодКогда
400 invalid_requestНевалидное тело или параметры; key_id/group_by обычным ключом.
401 invalid_api_keyКлюч не передан, неверный, отозван или отключён.
403 management_key_requiredManagement-эндпоинт вызван обычным ключом.
403 inference_key_requiredМодельный эндпоинт вызван management-ключом.
404 not_foundКлюч не найден (или не ваш).
429 rate_limit_exceededПревышен лимит 60/мин или 30 созданий/час.
429 key_quota_exceededДостигнут потолок 500 активных ключей.

Формат ошибок стандартный: {"error": {"message", "type", "code"}} — см. ошибки.

Что дальше

Обновлено: