Геймификация и рейтинг
Система баллов и рейтинг (лидерборд). Студенты и кураторы видят рейтинг с проекцией по роли; админы настраивают правила начисления баллов (значения по умолчанию и переопределения для конкретных объектов) и могут вручную корректировать баллы. Баллы передаются строкой (NUMERIC(10,2)) во избежание потери точности.
- GET
/api/v1/t/ratingРейтинг (лидерборд) - GET
/api/v1/t/admin/gamification/rulesСписок правил начисления - PUT
/api/v1/t/admin/gamification/rules/defaults/:source_typeПравило по умолчанию для типа источника - PUT
/api/v1/t/admin/gamification/rules/overrides/:source_type/:target_idПереопределение правила для объекта - DELETE
/api/v1/t/admin/gamification/rules/overrides/:source_type/:target_idУдалить переопределение правила - POST
/api/v1/t/admin/rating/adjustmentsРучная корректировка баллов - GET
/api/v1/t/admin/rating/students/:id/summaryСводка рейтинга студента - GET
/api/v1/t/admin/rating/students/:id/eventsИстория начислений студента
/api/v1/t/ratingРейтинг (лидерборд)
Возвращает таблицу лидеров с проекцией по роли вызывающего: студент видит свой ранг и баллы, имена других студентов анонимизируются (имя + инициал фамилии); куратор без права manage_groups видит только своих студентов и без полей caller_*; админ/суперадмин видят полную таблицу с полными именами.
Параметр limit по умолчанию 10 и жёстко ограничен сверху значением 100. source_types — список через запятую из значений lesson, module, course, quiz, assignment, exam, manual. Поля caller_rank/caller_points отсутствуют для куратора; time_window присутствует только при заданных from/to.
Query-параметры
| Параметр | Тип | Описание |
|---|---|---|
group_idопц. | uuid | Фильтр рейтинга по группе (когорте). |
source_typesопц. | string | Список типов источников баллов через запятую: lesson, module, course, quiz, assignment, exam, manual.Пример: quiz,exam |
fromопц. | string | Начало временного окна (включительно).Пример: 2026-05-01T00:00:00Z |
toопц. | string | Конец временного окна.Пример: 2026-05-28T00:00:00Z |
limitопц. | integer | Размер выборки (по умолчанию 10, максимум 100).Пример: 10 |
Пример запроса
curl "https://api.edumentor.kz/api/v1/t/rating?limit=10&source_types=quiz,exam" \
-H "Authorization: Bearer <token>" \
-H "X-Tenant-Subdomain: acme"Пример ответа
{
"success": true,
"data": {
"entries": [
{ "rank": 1, "student_id": "1a2b3c4d-...", "display_name": "Айгерим Н.", "points": "420.00" },
{ "rank": 2, "student_id": "2b3c4d5e-...", "display_name": "Данияр К.", "points": "390.50" }
],
"total_students": 84,
"caller_rank": 7,
"caller_points": "215.00",
"time_window": null
}
}Ошибки
| Код | error | Когда |
|---|---|---|
| 400 | invalid group_id | Параметр group_id не является валидным UUID. |
| 401 | unauthorized | Токен отсутствует, истёк или недействителен. |
| 403 | PAYMENT_REQUIRED | Биллинг школы приостановлен или истёк. |
| 404 | group_not_found | Указанная группа не найдена в текущей школе. |
/api/v1/t/admin/gamification/rulesСписок правил начисления
Возвращает все активные правила школы — значения по умолчанию и переопределения — в плоском виде, сгруппированные по типу источника. Доступно только админу/суперадмину.
Пример запроса
curl https://api.edumentor.kz/api/v1/t/admin/gamification/rules \
-H "Authorization: Bearer <token>" \
-H "X-Tenant-Subdomain: acme"Пример ответа
{
"success": true,
"data": {
"rules": [
{
"default_id": "8f3b1c2a-...",
"tenant_id": "0a1b2c3d-...",
"source_type": "quiz",
"enabled": true,
"points": "10.00",
"calc_mode": "fixed",
"threshold_source": null,
"threshold_value": null,
"award_only_if_passed": true,
"repeat_behavior": "overwrite_if_higher"
}
]
}
}Ошибки
| Код | error | Когда |
|---|---|---|
| 401 | unauthorized | Токен отсутствует, истёк или недействителен. |
| 403 | forbidden | Доступно только для роли admin/superadmin. |
/api/v1/t/admin/gamification/rules/defaults/:source_typeПравило по умолчанию для типа источника
Создаёт или обновляет правило по умолчанию для типа источника баллов. Поля частичные: null/отсутствие поля означает «не менять». Доступно только админу/суперадмину.
Для source_type = assignment действуют ограничения: при calc_mode = above_threshold обязателен threshold_value, а threshold_source = passing_score для задания недопустим.
Параметры пути
| Параметр | Тип | Описание |
|---|---|---|
source_typeобяз. | string | Тип источника баллов. Один из: lesson, module, course, quiz, assignment, exam, manual.Пример: quiz |
Тело запроса
| Параметр | Тип | Описание |
|---|---|---|
enabledопц. | boolean | Включено ли начисление. |
pointsопц. | string | Количество баллов (строка-десятичная дробь NUMERIC(10,2)).Пример: 10.00 |
calc_modeопц. | string | Режим расчёта: fixed, raw или above_threshold.Пример: fixed |
threshold_sourceопц. | string | Источник порога: passing_score или rule_specified. |
threshold_valueопц. | string | Значение порога (строка-десятичная дробь). |
award_only_if_passedопц. | boolean | Начислять баллы только при успешной сдаче. |
repeat_behaviorопц. | string | Поведение при повторе: ignore, award_each, overwrite, overwrite_if_higher. |
Пример запроса
curl -X PUT https://api.edumentor.kz/api/v1/t/admin/gamification/rules/defaults/quiz \
-H "Authorization: Bearer <token>" \
-H "X-Tenant-Subdomain: acme" \
-H "Content-Type: application/json" \
-d '{
"enabled": true,
"points": "10.00",
"calc_mode": "fixed",
"award_only_if_passed": true,
"repeat_behavior": "overwrite_if_higher"
}'Пример ответа
{
"success": true,
"data": { "updated": true }
}Ошибки
| Код | error | Когда |
|---|---|---|
| 400 | invalid_request_body | Тело запроса не прошло валидацию (например, недопустимый calc_mode). |
| 400 | invalid_calc_mode | Недопустимый режим расчёта баллов. |
| 400 | assignment_no_passing_score | Для задания нельзя использовать threshold_source = passing_score. |
| 400 | assignment_passed_requires_threshold | Для задания при above_threshold обязателен threshold_value. |
| 401 | unauthorized | Токен отсутствует, истёк или недействителен. |
| 403 | forbidden | Доступно только для роли admin/superadmin. |
/api/v1/t/admin/gamification/rules/overrides/:source_type/:target_idПереопределение правила для объекта
Создаёт или обновляет переопределение правила для конкретного объекта (например, конкретного теста или курса). Незаданные поля наследуются от правила по умолчанию. Доступно только админу/суперадмину.
Параметры пути
| Параметр | Тип | Описание |
|---|---|---|
source_typeобяз. | string | Тип источника: lesson, module, course, quiz, assignment, exam, manual.Пример: quiz |
target_idобяз. | uuid | Идентификатор объекта, для которого задаётся переопределение. |
Тело запроса
| Параметр | Тип | Описание |
|---|---|---|
enabledопц. | boolean | Включено ли начисление. |
pointsопц. | string | Количество баллов (строка-десятичная дробь).Пример: 25.00 |
calc_modeопц. | string | Режим расчёта: fixed, raw или above_threshold. |
threshold_sourceопц. | string | Источник порога: passing_score или rule_specified. |
threshold_valueопц. | string | Значение порога (строка-десятичная дробь). |
award_only_if_passedопц. | boolean | Начислять баллы только при успешной сдаче. |
repeat_behaviorопц. | string | Поведение при повторе: ignore, award_each, overwrite, overwrite_if_higher. |
Пример запроса
curl -X PUT https://api.edumentor.kz/api/v1/t/admin/gamification/rules/overrides/quiz/8f3b1c2a-1d2e-4a5b-9c6d-7e8f9a0b1c2d \
-H "Authorization: Bearer <token>" \
-H "X-Tenant-Subdomain: acme" \
-H "Content-Type: application/json" \
-d '{ "enabled": true, "points": "25.00" }'Пример ответа
{
"success": true,
"data": { "updated": true }
}Ошибки
| Код | error | Когда |
|---|---|---|
| 400 | invalid_target_id | target_id не является валидным UUID. |
| 400 | invalid_request_body | Тело запроса не прошло валидацию. |
| 400 | invalid_calc_mode | Недопустимый режим расчёта баллов. |
| 400 | assignment_no_passing_score | Для задания нельзя использовать threshold_source = passing_score. |
| 400 | assignment_passed_requires_threshold | Для задания при above_threshold обязателен threshold_value. |
| 401 | unauthorized | Токен отсутствует, истёк или недействителен. |
| 403 | forbidden | Доступно только для роли admin/superadmin. |
/api/v1/t/admin/gamification/rules/overrides/:source_type/:target_idУдалить переопределение правила
Мягко удаляет переопределение для конкретного объекта, возвращая объект к правилу по умолчанию школы. Доступно только админу/суперадмину.
Параметры пути
| Параметр | Тип | Описание |
|---|---|---|
source_typeобяз. | string | Тип источника: lesson, module, course, quiz, assignment, exam, manual.Пример: quiz |
target_idобяз. | uuid | Идентификатор объекта переопределения. |
Пример запроса
curl -X DELETE https://api.edumentor.kz/api/v1/t/admin/gamification/rules/overrides/quiz/8f3b1c2a-1d2e-4a5b-9c6d-7e8f9a0b1c2d \
-H "Authorization: Bearer <token>" \
-H "X-Tenant-Subdomain: acme"Пример ответа
{
"success": true,
"data": { "deleted": true }
}Ошибки
| Код | error | Когда |
|---|---|---|
| 400 | invalid_target_id | target_id не является валидным UUID. |
| 401 | unauthorized | Токен отсутствует, истёк или недействителен. |
| 403 | forbidden | Доступно только для роли admin/superadmin. |
| 404 | rule_not_found | Переопределение для данного объекта не найдено. |
/api/v1/t/admin/rating/adjustmentsРучная корректировка баллов
Вручную начисляет или списывает баллы студенту. points — знаковая числовая строка (отрицательное значение = списание). reason обязателен для аудита. Опциональный idempotency_key предотвращает двойную запись при повторе. Доступно только админу/суперадмину; записывается событие аудита.
Тело запроса
| Параметр | Тип | Описание |
|---|---|---|
student_idобяз. | uuid | Идентификатор студента. |
pointsобяз. | string | Знаковая величина в баллах; отрицательное значение — списание.Пример: -15.00 |
reasonобяз. | string | Причина корректировки (1–2000 символов) — попадает в журнал аудита. |
idempotency_keyопц. | string | Ключ идемпотентности для защиты от двойной записи при повторе. |
Пример запроса
curl -X POST https://api.edumentor.kz/api/v1/t/admin/rating/adjustments \
-H "Authorization: Bearer <token>" \
-H "X-Tenant-Subdomain: acme" \
-H "Content-Type: application/json" \
-d '{
"student_id": "1a2b3c4d-1d2e-4a5b-9c6d-7e8f9a0b1c2d",
"points": "25.00",
"reason": "Активность на вебинаре"
}'Пример ответа
{
"success": true,
"data": { "event_id": "9f8e7d6c-1d2e-4a5b-9c6d-7e8f9a0b1c2d" }
}Ошибки
| Код | error | Когда |
|---|---|---|
| 400 | invalid_request_body | Тело запроса не прошло валидацию (например, пустой reason). |
| 401 | unauthorized | Токен отсутствует, истёк или недействителен. |
| 403 | forbidden | Доступно только для роли admin/superadmin. |
| 404 | student_not_found | Студент не найден в текущей школе. |
/api/v1/t/admin/rating/students/:id/summaryСводка рейтинга студента
Возвращает сводку по баллам студента: ранг и сумму баллов в школе, общее число студентов и ранги по группам. Несмотря на префикс /admin/, эндпоинт доступен также куратору (в рамках его студентов) и студенту (только свои данные). Любой запрос вне области видимости, к чужому студенту, к другой школе или к несуществующему студенту даёт одинаковый ответ 404 student_not_found (защита от утечки фактом существования).
Параметры пути
| Параметр | Тип | Описание |
|---|---|---|
idобяз. | uuid | Идентификатор студента. |
Пример запроса
curl https://api.edumentor.kz/api/v1/t/admin/rating/students/1a2b3c4d-1d2e-4a5b-9c6d-7e8f9a0b1c2d/summary \
-H "Authorization: Bearer <token>" \
-H "X-Tenant-Subdomain: acme"Пример ответа
{
"success": true,
"data": {
"school_rank": 7,
"school_total": "215.00",
"school_total_students": 84,
"group_ranks": [
{
"group_id": "3c4d5e6f-...",
"group_name": "Поток-2026",
"rank": 3,
"total_points": "215.00",
"total_students": 24
}
]
}
}Ошибки
| Код | error | Когда |
|---|---|---|
| 400 | invalid_id | Идентификатор студента не является валидным UUID. |
| 401 | unauthorized | Токен отсутствует, истёк или недействителен. |
| 403 | PAYMENT_REQUIRED | Биллинг школы приостановлен или истёк. |
| 404 | student_not_found | Студент не найден либо недоступен текущему пользователю (единый отпечаток ответа). |
/api/v1/t/admin/rating/students/:id/eventsИстория начислений студента
Возвращает ленту событий начисления/списания баллов студента с пагинацией и фильтрами. Те же правила видимости и тот же отпечаток 404, что и у сводки. Поддерживает фильтры по типу источника, временному окну, знаку и поиску по причине.
sign — один из positive, negative, all. limit по умолчанию 50 и ограничен сверху 100; offset по умолчанию 0. from/to — RFC3339, полуоткрытый интервал.
Параметры пути
| Параметр | Тип | Описание |
|---|---|---|
idобяз. | uuid | Идентификатор студента. |
Query-параметры
| Параметр | Тип | Описание |
|---|---|---|
source_typeопц. | string | Список типов источников через запятую: lesson, module, course, quiz, assignment, exam, manual.Пример: quiz,manual |
fromопц. | string | Начало временного окна (RFC3339, включительно).Пример: 2026-05-01T00:00:00Z |
toопц. | string | Конец временного окна (RFC3339, исключительно). |
signопц. | string | Фильтр по знаку баллов: positive, negative или all.Пример: all |
reason_searchопц. | string | Поиск по подстроке в причине (ILIKE). |
limitопц. | integer | Размер страницы (по умолчанию 50, максимум 100).Пример: 50 |
offsetопц. | integer | Смещение для пагинации (по умолчанию 0).Пример: 0 |
Пример запроса
curl "https://api.edumentor.kz/api/v1/t/admin/rating/students/1a2b3c4d-1d2e-4a5b-9c6d-7e8f9a0b1c2d/events?sign=all&limit=50" \
-H "Authorization: Bearer <token>" \
-H "X-Tenant-Subdomain: acme"Пример ответа
{
"success": true,
"data": {
"events": [
{
"id": "9f8e7d6c-...",
"awarded_at": "2026-05-20T14:00:00Z",
"source_type": "quiz",
"target_id": "8f3b1c2a-...",
"target_label": "Тест: Основы Go",
"points": "10.00",
"rule_id": "0a1b2c3d-...",
"reason": null,
"actor_user_id": null,
"actor_display_name": null
}
],
"total": 23,
"limit": 50,
"offset": 0
}
}Ошибки
| Код | error | Когда |
|---|---|---|
| 400 | invalid_id | Идентификатор студента не является валидным UUID. |
| 400 | invalid_time | Параметр from/to не соответствует формату RFC3339. |
| 400 | invalid_sign | Значение sign не входит в набор positive/negative/all. |
| 401 | unauthorized | Токен отсутствует, истёк или недействителен. |
| 403 | PAYMENT_REQUIRED | Биллинг школы приостановлен или истёк. |
| 404 | student_not_found | Студент не найден либо недоступен текущему пользователю (единый отпечаток ответа). |