Обновлено: 22.08.2026
Программа лояльности
Начисление и списание баллов, статусы и персональные условия. Уровни и правила перехода настраиваются в админ-панели клуба — через API можно только читать конфигурацию и менять баланс.
Обзор методов
| Метод | Путь | Описание |
|---|---|---|
GET | /loyalty/{user_id} | Статус и баланс |
GET | /loyalty/tiers | Уровни программы |
POST | /loyalty/{user_id}/accrue | Начислить баллы |
POST | /loyalty/{user_id}/redeem | Списать баллы |
GET | /loyalty/{user_id}/history | История начислений и списаний |
POST | /loyalty/{user_id}/adjust | Ручная корректировка баланса |
Статус и баланс
GET /loyalty/{user_id}Текущий уровень программы лояльности и количество баллов пользователя.
Параметры
| Параметр | Где | Тип | Обязателен | Описание |
|---|---|---|---|---|
user_id | путь | string | да | Идентификатор пользователя. |
curl https://api.virazh.io/v1/loyalty/usr_8f21c \
-H "Authorization: Bearer sk_test_51H..."{
"user_id": "usr_8f21c",
"status": "silver",
"points": 1240,
"next_status": "gold",
"points_to_next": 760
}Поля ответа
| Поле | Тип | Описание |
|---|---|---|
status | string | Текущий уровень: silver, gold, platinum. |
points | integer | Текущий баланс баллов. |
next_status | string | null | Следующий уровень, если есть. |
points_to_next | integer | null | Сколько баллов не хватает до next_status. |
Уровни программы
GET /loyalty/tiersСписок уровней лояльности клуба с условиями перехода и процентом начисления — пригодится, чтобы отрисовать прогресс в своём приложении.
curl https://api.virazh.io/v1/loyalty/tiers \
-H "Authorization: Bearer sk_test_51H..."{
"tiers": [
{ "name": "silver", "min_points": 0, "accrual_rate": 0.05 },
{ "name": "gold", "min_points": 2000, "accrual_rate": 0.08 },
{ "name": "platinum", "min_points": 6000, "accrual_rate": 0.12 }
]
}Поля ответа
| Поле | Тип | Описание |
|---|---|---|
tiers | array<Tier> | Уровни по возрастанию min_points, с полями name, min_points, accrual_rate. |
Начислить баллы
POST /loyalty/{user_id}/accrueНачисляет баллы за событие — покупку, посещение, активность. Источник начисления передаётся в поле reason для последующей аналитики.
Параметры
| Параметр | Где | Тип | Обязателен | Описание |
|---|---|---|---|---|
user_id | путь | string | да | Идентификатор пользователя. |
amount | тело | integer | да | Количество баллов к начислению, целое положительное число. |
reason | тело | string | да | Код источника: ticket_purchase, shop_order, training_attended и т.д. |
curl https://api.virazh.io/v1/loyalty/usr_8f21c/accrue \
-X POST \
-H "Authorization: Bearer sk_test_51H..." \
-H "Content-Type: application/json" \
-d '{
"amount": 150,
"reason": "ticket_purchase"
}'{
"user_id": "usr_8f21c",
"accrued": 150,
"balance": 1390
}Поля ответа
| Поле | Тип | Описание |
|---|---|---|
accrued | integer | Сколько баллов начислено этим запросом. |
balance | integer | Баланс после начисления. |
Списать баллы
POST /loyalty/{user_id}/redeemСписывает баллы в счёт оплаты или бонуса. Возвращает ошибку insufficient_points, если баланса не хватает.
Параметры
| Параметр | Где | Тип | Обязателен | Описание |
|---|---|---|---|---|
user_id | путь | string | да | Идентификатор пользователя. |
amount | тело | integer | да | Количество баллов к списанию. |
reason | тело | string | да | Код назначения списания: shop_order, ticket_discount и т.д. |
curl https://api.virazh.io/v1/loyalty/usr_8f21c/redeem \
-X POST \
-H "Authorization: Bearer sk_test_51H..." \
-H "Content-Type: application/json" \
-d '{ "amount": 500, "reason": "shop_order" }'{
"user_id": "usr_8f21c",
"redeemed": 500,
"balance": 890
}Поля ответа
| Поле | Тип | Описание |
|---|---|---|
redeemed | integer | Сколько баллов списано. |
balance | integer | Баланс после списания. |
История начислений и списаний
GET /loyalty/{user_id}/historyПостраничный журнал операций по баллам с указанием причины и итогового баланса на момент операции — источник для раздела «История баллов» в личном кабинете.
Параметры
| Параметр | Где | Тип | Обязателен | Описание |
|---|---|---|---|---|
user_id | путь | string | да | Идентификатор пользователя. |
limit | query | integer | нет | Размер страницы, до 100. По умолчанию — 20. |
curl "https://api.virazh.io/v1/loyalty/usr_8f21c/history?limit=20" \
-H "Authorization: Bearer sk_test_51H..."{
"user_id": "usr_8f21c",
"data": [
{ "type": "accrual", "amount": 150, "reason": "ticket_purchase", "at": "2026-08-20T18:03:00Z", "balance_after": 1390 },
{ "type": "redemption", "amount": -500, "reason": "shop_order", "at": "2026-08-18T09:12:00Z", "balance_after": 890 }
],
"has_more": false
}Поля ответа
| Поле | Тип | Описание |
|---|---|---|
data | array<LedgerEntry> | Операции с полями type (accrual | redemption), amount, reason, at, balance_after. |
has_more | boolean | Есть ли следующая страница. |
Ручная корректировка баланса
POST /loyalty/{user_id}/adjustНачисляет или списывает баллы вручную, в обход стандартных правил — для компенсаций и разбора спорных ситуаций. Требует scope loyalty:admin, действие фиксируется в аудит-логе.
Параметры
| Параметр | Где | Тип | Обязателен | Описание |
|---|---|---|---|---|
user_id | путь | string | да | Идентификатор пользователя. |
amount | тело | integer | да | Величина корректировки — положительная (начисление) или отрицательная (списание). |
reason | тело | string | да | Код причины, например support_compensation. |
comment | тело | string | нет | Свободный комментарий для аудит-лога. |
curl https://api.virazh.io/v1/loyalty/usr_8f21c/adjust \
-X POST \
-H "Authorization: Bearer sk_test_51H..." \
-H "Content-Type: application/json" \
-d '{ "amount": 200, "reason": "support_compensation", "comment": "Задержка рейса на выезд" }'{
"user_id": "usr_8f21c",
"adjusted": 200,
"balance": 1090,
"audit_log_id": "adj_3391"
}Поля ответа
| Поле | Тип | Описание |
|---|---|---|
adjusted | integer | Величина применённой корректировки. |
balance | integer | Баланс после корректировки. |
audit_log_id | string | Идентификатор записи в аудит-логе. |
Полезно знать
- Начисление и списание — отдельные операции: система не позволяет уйти в отрицательный баланс,
redeemвернётinsufficient_points, если баллов не хватает. - Уровни (
/loyalty/tiers) настраиваются в админ-панели клуба и могут отличаться у разных клубов — не хардкодьте названия уровней в своём приложении. - Начисление идемпотентно по паре
user_id + reasonв пределах 24 часов — повторный вызов с тем жеreasonдля того же заказа не задвоит баллы. - Ручная корректировка (
/loyalty/{user_id}/adjust) требует scopeloyalty:adminи всегда пишется в аудит-лог с указанной причиной — используйте её только для компенсаций, не как замену обычному начислению.




