Перейти к содержанию

Кредиты

Кредит — внутренняя валюта сервиса. Цена эффекта (cost) указана в кредитах; при генерации они резервируются и списываются, при сбое — возвращаются. Кредиты начисляются бонусами (приветственные при регистрации), через админку и покупкой пакетов за деньги (см. Оплата).

Баланс

curl "$BASE_URL/v1/credits/balance" -H "Authorization: Bearer $TOKEN"
# {"balance": 1120, "plan_credits": 500, "plan_expires_at": "2026-11-05T14:00:00Z"}

Тот же balance отдаёт и GET /v1/me — для общего профиля отдельный запрос не нужен.

  • balance - сколько можно потратить, всё вместе.
  • plan_credits - какая часть этого числа пришла по подписке и сгорит вместе с её периодом. Это доля balance, а не второй кошелёк: складывать их не нужно.
  • plan_expires_at - когда эта доля сгорит. null, если подписки нет.

У того, кто не подписан, plan_credits равен 0, и показывать нечего. Тратятся кредиты плана первыми, поэтому купленный пакет не расходуется, пока есть чему сгореть.

Кредит один, типов у него нет. Баланс — одно число: неважно, куплены кредиты, подарены при регистрации или заработаны на своём эффекте, тратятся они одинаково. Единственное различие - срок: кредиты плана живут до конца оплаченного периода, все остальные не сгорают никогда. Правило про заработок авторов от этого не зависит: автору капает процент только с генераций тех, кто хоть раз покупал кредиты (см. свои эффекты). Проверяется это по истории платежей, а не по происхождению конкретного кредита.

История операций (ledger)

Каждое движение кредитов — отдельная запись в журнале:

curl "$BASE_URL/v1/credits/transactions?limit=20&offset=0" \
  -H "Authorization: Bearer $TOKEN"
{
  "items": [
    { "id": "…", "amount": -5, "kind": "reserve", "reference": "<generation_id>", "created_at": "…" },
    { "id": "…", "amount": 5,  "kind": "refund",  "reference": "<generation_id>", "created_at": "…" },
    { "id": "…", "amount": 50, "kind": "welcome", "reference": null,              "created_at": "…" }
  ],
  "total": 3, "limit": 20, "offset": 0
}
  • amount — знаковое: списание отрицательное, начисление положительное.
  • kind — тип операции: welcome (приветственные при регистрации), purchase (покупка пакета за деньги, см. Оплата), purchase_revoke (отзыв купленного при возврате денег), reserve (списание под генерацию), refund (возврат при сбое), referral_bonus / referral_earned (реферальные бонусы, см. Реферальная программа), effect_earned (доля автора за чужую генерацию его эффектом, см. Свои эффекты), effect_revoked (отзыв этой доли, если кредиты за ту генерацию вернули пользователю), plan_expired (сгорел остаток кредитов плана: период закончился или подписка закрыта). Период подписки приходит той же записью purchase, что и пакет.
  • reference — связанная сущность (обычно generation_id; у effect_earned — id эффекта), либо null.

Одна операция — одна запись. Списание под генерацию всегда одна строка reserve, возврат — одна строка refund с тем же reference.

Как это связано с генерацией

создание генерации   →  reserve  (баланс − cost)
успех                →  (доп. записи нет — резерв и есть итоговое списание)
сбой / таймаут       →  refund   (баланс + cost)

Списание происходит сразу при создании генерации одной записью reserve. При успехе ничего не дописывается: зарезервированное и есть итоговая стоимость. При сбое/таймауте сумма возвращается записью refund (сама генерация остаётся в статусе failed — отдельного статуса «возвращено» нет).

Резерв атомарный: если на балансе меньше cost, генерация не создаётся — 402 insufficient_credits. Подробнее о статусах — Генерация и realtime.

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