Возможности
ВОЗМОЖНОСТИ

Мониторинг расходов

Программный учёт трат через GET /v1/usage — отслеживание расхода по ключу, бюджет-алёрты, отчёты.

Hubris отдаёт расход по API-ключу через GET /v1/usage — отдельные запросы и агрегированные суммы. Используется для автоматического мониторинга: алёрты по порогам, отчёты, экспорт в свою аналитику.

Endpoint-референс — на GET /v1/usage. Этот гид — про практические паттерны.

Базовый запрос

curl -s -H "Authorization: Bearer $HUBRIS_API_KEY" \
  https://api.hubris.pw/v1/usage

По умолчанию — расход за последние 24 часа по тому ключу, которым сделан запрос. Ответ:

{
  "object": "usage",
  "period": { "from": "2026-05-21T00:00Z", "to": "2026-05-22T00:00Z" },
  "scope": { "key_id": "...", "key_prefix": "sk-gw-758f...d4e3" },
  "totals": {
    "requests": 142,
    "prompt_tokens": 18500,
    "completion_tokens": 3200,
    "total_tokens": 21700,
    "cost_rub": 187.45,
    "cost_kopecks": "18745"
  },
  "granularity": null,
  "buckets": null
}

Важно: виден расход только этого ключа, а не всего аккаунта. Это намеренно — скомпрометированный ключ не должен раскрывать общий бюджет.

Паттерн 1: ежедневный отчёт

Cron-задача, которая раз в день берёт суммарный расход за вчера и шлёт письмо/слак/телеграм:

import os
import requests
from datetime import datetime, timedelta, timezone

key = os.environ["HUBRIS_API_KEY"]

yesterday = datetime.now(timezone.utc) - timedelta(days=1)
day_start = yesterday.replace(hour=0, minute=0, second=0, microsecond=0)
day_end   = day_start + timedelta(days=1)

resp = requests.get(
    "https://api.hubris.pw/v1/usage",
    params={"from": day_start.isoformat(), "to": day_end.isoformat()},
    headers={"Authorization": f"Bearer {key}"},
).json()

totals = resp["totals"]
print(f"Вчера: {totals['requests']} запросов, {totals['cost_rub']} ₽")

# Отправить в Slack, если расход за день выше нормы:
if float(totals["cost_rub"]) > 500:
    notify_slack(f"⚠️ Вчера ушло {totals['cost_rub']} ₽")

Паттерн 2: бюджет-алёрт после каждого запроса

Если у вас агент, который может за сессию «уйти в космос» — проверяйте расход после каждого запроса и останавливайтесь при превышении лимита:

DAILY_BUDGET_RUB = 1000

def check_budget():
    resp = requests.get(
        "https://api.hubris.pw/v1/usage",
        params={"period": "today"},
        headers={"Authorization": f"Bearer {key}"},
    ).json()
    return float(resp["totals"]["cost_rub"])

# В цикле агента
while task_not_done:
    if check_budget() > DAILY_BUDGET_RUB:
        raise BudgetExceeded(f"Превышен дневной лимит {DAILY_BUDGET_RUB} ₽")

    response = run_step()
    process(response)

В большинстве сценариев лучше использовать встроенный дневной лимит ключа (см. /keys) — он гарантированно прерывает на стороне сервера и возвращает 429 daily_limit_exceeded. Бюджет в коде — мягкая защита поверх него, для случаев когда нужен ранний алёрт «потратили 80% бюджета — переключаемся на дешёвую модель».

Паттерн 3: график по дням

Для дашборда — берите данные с почасовой/посуточной разбивкой:

curl -s -H "Authorization: Bearer $HUBRIS_API_KEY" \
  "https://api.hubris.pw/v1/usage?period=30d&granularity=day"

В ответе появится массив buckets:

{
  "totals": { "cost_rub": 5432.10, ... },
  "granularity": "day",
  "buckets": [
    { "bucket": "2026-04-22T00:00:00Z", "cost_rub": 180.30, "requests": 142 },
    { "bucket": "2026-04-23T00:00:00Z", "cost_rub": 213.45, "requests": 167 },
    { "bucket": "2026-04-24T00:00:00Z", "cost_rub": 0, "requests": 0 }
  ]
}

Дни без запросов всё равно присутствуют (с cost_rub: 0) — удобно для линейного графика без пропусков.

Паттерн 4: разделение по проектам

Один аккаунт — несколько ключей под разные проекты. Дашборд /usage агрегирует общий расход; API даёт расход только запрашиваемого ключа.

Чтобы получить разбивку по проектам — храните ключи (или их key_id) на стороне ваших систем и запрашивайте /v1/usage каждым ключом отдельно:

PROJECT_KEYS = {
    "production": os.environ["HUBRIS_KEY_PROD"],
    "staging":    os.environ["HUBRIS_KEY_STG"],
    "research":   os.environ["HUBRIS_KEY_RES"],
}

for project, key in PROJECT_KEYS.items():
    resp = requests.get(
        "https://api.hubris.pw/v1/usage",
        params={"period": "7d"},
        headers={"Authorization": f"Bearer {key}"},
    ).json()
    print(f"{project}: {resp['totals']['cost_rub']} ₽ / {resp['totals']['requests']} req")

TypeScript

type UsageResp = {
  totals: {
    requests: number;
    prompt_tokens: number;
    completion_tokens: number;
    cost_rub: number;
    cost_kopecks: string;
  };
  buckets: Array<{
    bucket: string;
    cost_rub: number;
    cost_kopecks: string;
    requests: number;
  }> | null;
};

async function fetchUsage(period = '7d', granularity?: 'hour' | 'day') {
  const url = new URL('https://api.hubris.pw/v1/usage');
  url.searchParams.set('period', period);
  if (granularity) url.searchParams.set('granularity', granularity);

  const resp = await fetch(url, {
    headers: { Authorization: `Bearer ${process.env.HUBRIS_API_KEY}` },
  });
  return (await resp.json()) as UsageResp;
}

const week = await fetchUsage('7d', 'day');
console.log(`За 7 дней: ${week.totals.cost_rub} ₽`);
for (const day of week.buckets ?? []) {
  console.log(`  ${day.bucket}: ${day.cost_rub} ₽`);
}

Точность сумм при больших расходах

cost_kopecks приходит как строка — чтобы при сериализации в JavaScript не терялась точность на больших суммах. Если вам важна копейка-в-копейку точность (бухучёт, биллинг клиентов поверх Hubris) — парсите cost_kopecks через BigInt, не через Number:

const kopecks = BigInt(resp.totals.cost_kopecks);
const rubFormatted = (Number(kopecks) / 100).toFixed(2);

Поле cost_rub — это уже cost_kopecks / 100, удобно для отображения, но не для арифметики.

Часовые пояса

Время в API — UTC. Если нужно «расход за сегодня по Москве» — конвертируйте границы суток у себя и передавайте явные from / to (ISO 8601 UTC):

from datetime import datetime, timezone, timedelta

MSK = timezone(timedelta(hours=3))

now_msk = datetime.now(MSK)
day_start_msk = now_msk.replace(hour=0, minute=0, second=0, microsecond=0)
day_end_msk = day_start_msk + timedelta(days=1)

resp = requests.get(
    "https://api.hubris.pw/v1/usage",
    params={
        "from": day_start_msk.astimezone(timezone.utc).isoformat(),
        "to":   day_end_msk.astimezone(timezone.utc).isoformat(),
    },
    headers={"Authorization": f"Bearer {key}"},
).json()

Дашбордная альтернатива

Если ручной мониторинг — overkill, на странице /usage дашборда есть готовые фильтры по модели, ключу и статусу, графики по дням и CSV-экспорт. Многие сценарии решаются прямо в UI без написания кода.

Что важно знать

  • Кешируйте. Не дёргайте /v1/usage чаще, чем раз в минуту — для большинства сценариев достаточно раз в 5–10 минут. Избыточные запросы влияют только на ваш rate-budget.
  • Расход обновляется в течение нескольких секунд после успешного списания. Свежий запрос → пара секунд → его стоимость в /v1/usage.
  • Запросы на free-модели добавляются к requests, но не к cost_rub. Если у вас активны бесплатные модели, число запросов в дашборде будет выше, чем «сколько денег ушло».
  • Только успешные запросы входят в totals. Запросы с ошибками (4xx/5xx) не списываются и не попадают в счётчик расхода.

Что дальше

  • GET /v1/usage — полная схема параметров и ответа.
  • Управление ключами — настроить дневной лимит на уровне ключа.
  • Биллинг — как формируется стоимость токенов.
  • /usage — дашборд расходов с фильтрами и CSV-экспортом.

Обновлено:

Мониторинг расходов · Hubris