Объём приходит,
сумма — нет
Ваш сервис шлёт только объём: сколько токенов, запросов или минут. Genesis принимает события пачками, не пишет повторы и списывает период без двойных списаний.
События · usage поток
повтор transaction_id не запишется дваждыСписание периода
Возможности
Пачки до тысячи
POST /internal/usage/events принимает до 1000 событий за раз. Одинаковые transaction_id в пачке схлопываются ещё до вставки.
Идемпотентно в базе
Уникальность держит unique(app_id, transaction_id) и insertOrIgnore — две параллельные доставки не запишут событие дважды.
Без денег в событии
Запрос с полем amount, cost, price или currency отклоняется. Второй счетовод — расхождение, которое никто не сведёт.
Агрегат за период
GET /internal/usage/summary отдаёт объём по метрикам, а с plan_key — сразу расчёт по тарифу.
Списание разницей
Период считается целиком, с кошелька снимается разница с уже списанным. Новые события не списывают старое второй раз.
Исход после таймаута
Строка прогона пишется до вызова кошелька. Неизвестный исход повторяется тем же ключом идемпотентности.
Четыре шага
Отправьте событие
transaction_id, метрика и объём. Без сумм.
Genesis запишет его один раз
Повтор той же доставки молча пропускается.
Посмотрите агрегат
Объём и расчёт за период по нужному тарифу.
Спишите
POST /internal/usage/charge снимает с кошелька только разницу.
Маршруты
POST /internal/usage/events
X-Internal-Secret: ••••••
{ "events": [
{ "transaction_id": "req_77f2",
"metric": "offer-acme-gpt-tokens-128-input",
"value": 1820 },
{ "transaction_id": "req_77f2-o",
"metric": "offer-acme-gpt-tokens-128-output",
"value": 480 }
] } Коротко о главном
Что, если событие придёт дважды?
Ничего. Повтор с тем же transaction_id не записывается второй раз — это держит уникальный индекс, а не проверка перед вставкой.
Что, если кошелёк не ответил?
Строка прогона уже записана без transaction_key. Следующий прогон сначала повторяет её тем же ключом — второго списания не будет.
Как выбирается тариф?
Тот, кто считает, передаёт plan_key на каждом вызове. Выбор потребителя лежит в customers.meta_data.plan_key.