Основы API
Базовый адрес, форматы, коды ответов, ограничения
У сервера UnicoreCMS обычный REST-API на NestJS. Сайт и админка ходят в него теми же запросами, что доступны вашему коду; приватных каналов между фронтом и бэкендом нет.
Базовый адрес
https://api.example.comЭтот адрес лежит в .env как API_BASEURL. Корень (/) редиректит на сайт, чтобы в API случайно не заходили браузером.
Форматы: JSON на вход и на выход, а файлы загружайте как multipart/form-data.
Заголовки
| Заголовок | Зачем |
|---|---|
Authorization: Bearer <token> | Авторизация пользователя |
Authorization: Api-Key <secret> | Авторизация машинного клиента |
x-locale: en | Язык переводимого контента в ответе |
x-raw-content: 1 | Отдать оригиналы вместо переводов |
Timezone: Europe/Moscow | Таймзона клиента |
recaptcha: <token> | Токен reCAPTCHA, если она включена |
`x-locale` и `x-raw-content`
Первый переводит поля контента на лету: названия товаров, описания серверов, тексты новостей. Второй выключает подмену, и редактор правит оригинал, а не перевод. Без этих заголовков контент придёт на языке по умолчанию.
Коды ответов
| Код | Что означает |
|---|---|
200, 201 | Всё хорошо |
400 | Валидация не прошла, в теле список проблем по полям |
401 | Нет токена или он протух |
403 | Токен есть, прав не хватает |
404 | Записи нет |
429 | Слишком часто |
500 | Что-то сломалось на сервере |
Тело ошибки — стандартное для Nest:
{
"statusCode": 400,
"message": ["username must be a valid username"],
"error": "Bad Request"
}Лишние поля вырезаются молча
У валидации включён whitelist: true, поэтому поля, которых нет в DTO, пропадают из запроса без ошибки. Если что-то «не сохраняется», первым делом проверьте, что имя поля точно совпадает.
Ограничение частоты
Лимиты стоят там, где опасен перебор: на всей ветке /auth/* и на активации подарочных кодов.
Базовый лимит — 10 запросов за 2 минуты с адреса. На отдельных ручках жёстче:
| Ручка | Лимит |
|---|---|
| Регистрация | 5 в час |
| Подтверждение почты | 10 за 10 минут |
| Повторная отправка кода | 3 за 10 минут |
| Сброс пароля | 5 в час |
Машинные клиенты (плагин, лаунчер, дашборд) под лимиты не попадают: проверка смотрит на права kernel.unicore.connect, kernel.unicore.provider и admin.dashboard.
Лимиты считаются по IP
А IP сервер берёт с учётом переменной TRUST_PROXY. Если её не настроить, все запросы придут как будто с одного адреса, и лимит выключит сайт сразу для всех.
Пагинация
Списочные ручки используют nestjs-paginate:
GET /store/products?page=1&limit=20&sortBy=price:DESC&search=мечОтвет:
{
"data": [],
"meta": { "itemsPerPage": 20, "totalItems": 143, "currentPage": 1, "totalPages": 8 },
"links": {}
}Что открыто без авторизации
Публичные ручки отдают то, что и так видит на сайте гость:
| Метод | Путь | Что отдаёт |
|---|---|---|
GET | /config/public | Публичные настройки сайта |
GET | /servers · /servers/:id | Серверы |
GET | /servers/online | Текущий онлайн |
GET | /news · /news/:id | Новости |
GET | /pages · /pages/:id · /pages/rules | Статические страницы |
GET | /donates/groups/server/:id | Привилегии сервера |
GET | /locales · /locales/:code/messages | Языки и словарь интерфейса |
GET | /players/banlist | Баны |
GET | /players/playtime | Топ по времени в игре |
GET | /players/votes-list | Топ голосующих |
GET | /users/public/username/:username | Публичный профиль |
POST | /auth/login · /auth/register · /auth/refresh | Вход и регистрация |
Всё остальное требует токена.
Каталог магазина закрыт для гостей
Витрина живёт на ручках /store/products/protected/*, и без входа они не работают: цены и доступность зависят от прав игрока и его серверов. Особых прав не нужно, достаточно войти в аккаунт.
Swagger
Вне production на /docs поднимается Swagger со всеми ручками. На боевом его выключили намеренно, чтобы не публиковать карту API вместе с админскими методами.
Чтобы посмотреть локально:
pnpm --filter unicore-server run dev
# http://127.0.0.1:5000/docs