Карта API-маршрутов
Обновлён 14 апр. 2026 г., 17:16 · 0 комментариев
Карта API-маршрутов
Паспорт документа
- Статус документа: living document
- Актуально на: 2 апреля 2026 года
- Владелец: backend/platform-команда
- Пересмотр: при изменении endpoint'ов, auth-flow или API-контракта
- Область применения: обзорная карта живого backend API и точек входа OpenAPI/Swagger
- Связанные документы:
Base prefix:
/api/v1/
Авторизация и токены
Web-клиент использует httpOnly cookies. Дополнительно JwtAuthGuard умеет читать Bearer token из Authorization header, что используется для non-web клиентов и служебных сценариев.
| Cookie | Содержимое | TTL | Path |
|---|---|---|---|
qadam_at | Access JWT {sub, email, type, tokenType:'access'} | 15 мин | / |
qadam_rt | Refresh JWT {tokenType:'refresh', jti} | 7 дней | / |
JwtAuthGuard применён глобально (APP_GUARD). Сначала читает Bearer token из Authorization, если его нет — fallback на cookie qadam_at. Затем проверяет подпись и tokenType === 'access'. Маршруты с @Public() пропускают проверку.
Роли проверяются в контроллерах через assertSeller(user) / assertBuyer(user) и аналогичные проверки по типу пользователя, без отдельного role-guard слоя. При несоответствии бросается ForbiddenException.
Ротация токена: POST /auth/refresh читает qadam_rt из cookie или refreshToken из body, верифицирует его, проверяет jti, генерирует оба новых токена и для web-клиента заново устанавливает cookies.
qadam_rtтеперь intentionally доступна всему web runtime поpath=/, чтобы server-side proxy и server components могли читать refresh cookie при полной перезагрузке страницы. При выдаче новой пары токенов backend дополнительно чистит legacyqadam_rtсpath=/api/v1/auth, чтобы не оставлять дублирующую refresh-cookie после миграции.
OpenAPI и Swagger
Backend теперь публикует машиночитаемый и человекочитаемый API-контур:
| Назначение | URL | Доступ |
|---|---|---|
| Swagger UI | /api/docs | Внутренний инженерный доступ |
| OpenAPI JSON | /api/openapi.json | Внутренний инженерный доступ |
Именно OpenAPI JSON должен использоваться как источник истины для frontend codegen, contract review и дальнейшего выноса frontend в отдельный репозиторий. docs/architecture/api-routes.md остаётся обзорной картой маршрутов, но не заменяет машиночитаемый контракт.
Дополнительно в репозитории зафиксирован versioned artifact:
apps/api/openapi/openapi.json— канонический snapshot контракта для CI и frontend codegen;apps/web/src/shared/api/generated/openapi.d.ts— generated TypeScript contract для web;pnpm sync:api-contract— обновить artifact и generated types;pnpm check:api-contract— проверить drift между backend-кодом, artifact и generated types.
Health
| Метод | Path | Auth | Описание |
|---|---|---|---|
| GET | /health | Public | Быстрый health check API |
| GET | /health/live | Public | Liveness probe процесса API |
| GET | /health/ready | Public | Readiness probe с проверкой PostgreSQL и Redis |
| GET | /metrics | Public route, loopback-only runtime access | Prometheus-compatible runtime/process/http metrics |
GET /metricsпубликуется в OpenAPI как часть system API, но runtime сознательно режет его на403, если запрос пришёл не с loopback-адреса сервера. Это инженерный endpoint для локального scrape и operational диагностики, а не публичный маршрут для браузера.
Auth
| Метод | Path | Auth | Cookies | Описание |
|---|---|---|---|---|
| POST | /auth/register | Public | web: ← sets qadam_at + qadam_rt; mobile: ← returns both in body | Регистрация (email/phone, пароль, тип аккаунта) |
| POST | /auth/check-availability | Public | n/a | Проверка доступности email и/или телефона перед регистрацией |
| POST | /auth/register/buyer | Public | web: ← sets qadam_at + qadam_rt; mobile: ← returns both in body | Единая регистрация buyer с онбордингом |
| POST | /auth/register/seller | Public | web: ← sets qadam_at + qadam_rt; mobile: ← returns both in body | Единая регистрация seller с профилем, адресами и направлениями |
| POST | /auth/login | Public | web: ← sets qadam_at + qadam_rt; mobile: ← returns both in body | Вход по email/phone + пароль |
| GET | /auth/me | qadam_at или Bearer | → reads access token | Текущий пользователь |
| POST | /auth/refresh | Public | web: → reads qadam_rt, mobile: → reads refreshToken body | Ротация токенов |
| POST | /auth/logout | qadam_at или Bearer | web: ← clears both cookies | Выход, очистка сессии |
| POST | /auth/forgot-password | Public | n/a | Начать восстановление пароля |
| POST | /auth/verify-reset-code | Public | n/a | Проверить SMS-код для сброса пароля |
| POST | /auth/reset-password | Public | web: ← sets qadam_at + qadam_rt; mobile: ← returns both in body | Сбросить пароль и открыть сессию |
| POST | /auth/change-password | qadam_at или Bearer | → reads access token | Сменить пароль из авторизованного кабинета |
| POST | /auth/add-buyer-role | qadam_at или Bearer | → reads access token | Добавить buyer-профиль к seller/seller_staff аккаунту |
Buyer (роль: BUYER)
| Метод | Path | Auth | Описание |
|---|---|---|---|
| GET | /me/profile | qadam_at или Bearer | Получить профиль покупателя |
| POST | /me/profile | qadam_at или Bearer | Создать профиль |
| PATCH | /me/profile | qadam_at или Bearer | Обновить account-данные buyer-профиля |
| PUT | /me/profile | qadam_at или Bearer | Legacy alias для PATCH |
| GET | /me/children | qadam_at или Bearer | Получить список детей parent-buyer |
| POST | /me/children | qadam_at или Bearer | Добавить ребёнка |
| PATCH | /me/children/:studentId | qadam_at или Bearer | Обновить ребёнка |
| DELETE | /me/children/:studentId | qadam_at или Bearer | Удалить ребёнка |
| PATCH | /me/interests | qadam_at или Bearer | Полностью заменить интересы student-buyer |
| POST | /leads | qadam_at или Bearer | Оставить заявку на товар |
| GET | /me/leads | qadam_at или Bearer | Мои заявки |
| GET | /me/reviews | qadam_at или Bearer | Мои отзывы |
| POST | /me/reviews | qadam_at или Bearer | Написать отзыв |
Review flow больше не подразумевает немедленную публикацию: новые отзывы создаются в
PENDING,GET /me/reviewsпубликуетstatusиmoderationNote, а публичные страницы и агрегаты учитывают толькоPUBLISHED.
Seller (роль: SELLER)
| Метод | Path | Auth | Описание |
|---|---|---|---|
| GET | /seller/profile | qadam_at или Bearer | Профиль продавца |
| POST | /seller/profile | qadam_at или Bearer | Создать профиль |
| PATCH | /seller/profile | qadam_at или Bearer | Обновить профиль |
| PUT | /seller/profile | qadam_at или Bearer | Legacy alias для PATCH |
| GET | /seller/addresses | qadam_at или Bearer | Список адресов продавца |
| POST | /seller/addresses | qadam_at или Bearer | Добавить адрес продавца |
| PATCH | /seller/addresses/:addressId | qadam_at или Bearer | Обновить адрес продавца |
| DELETE | /seller/addresses/:addressId | qadam_at или Bearer | Удалить адрес продавца |
| PATCH | /seller/addresses/:addressId/set-primary | qadam_at или Bearer | Сделать адрес основным |
| GET | /seller/notification-settings | qadam_at или Bearer | Получить настройки уведомлений продавца |
| PATCH | /seller/notification-settings | qadam_at или Bearer | Обновить настройки уведомлений продавца |
| GET | /seller/telegram/connect-link | qadam_at или Bearer | Получить deep link для запуска seller Telegram onboarding flow |
| POST | /seller/telegram/verify | qadam_at или Bearer | Привязать Telegram по верификационному коду |
| DELETE | /seller/telegram | qadam_at или Bearer | Отвязать Telegram |
| GET | /seller/items | qadam_at или Bearer | Список своих товаров |
| GET | /seller/items/:id | qadam_at или Bearer | Товар по ID |
| POST | /seller/items | qadam_at или Bearer | Создать товар |
| PUT | /seller/items/:id | qadam_at или Bearer | Обновить товар |
| POST | /seller/items/:id/submit | qadam_at или Bearer | Отправить на модерацию |
| POST | /seller/items/:id/withdraw | qadam_at или Bearer | Отозвать pending-товар с модерации обратно в draft |
| POST | /seller/items/:id/archive | qadam_at или Bearer | Архивировать товар |
| DELETE | /seller/items/:id | qadam_at или Bearer | Удалить товар |
| GET | /seller/leads | qadam_at или Bearer | Заявки на мои товары; доступно owner и SELLER_STAFF |
| PUT | /seller/leads/:id/status | qadam_at или Bearer | Изменить статус заявки (CREATED / CONTACTED / ENROLLED / REJECTED); доступно owner и SELLER_STAFF |
| GET | /seller/reviews | qadam_at или Bearer | Отзывы по товарам продавца |
| PATCH | /seller/reviews/:id/reply | qadam_at или Bearer | Оставить или обновить ответ продавца на отзыв |
| POST | /seller/reviews/:id/complaint | qadam_at или Bearer | Подать жалобу на опубликованный отзыв и отправить его на повторную модерацию |
| GET | /seller/staff | qadam_at или Bearer | Список сотрудников |
| POST | /seller/staff | qadam_at или Bearer | Добавить сотрудника |
| PUT | /seller/staff/:id | qadam_at или Bearer | Обновить сотрудника |
| DELETE | /seller/staff/:id | qadam_at или Bearer | Удалить сотрудника |
Для
PATCH /seller/profilebackend возвращает специфичныеPHONE_TAKENиEMAIL_TAKEN, если contact phone/email конфликтуют с другим аккаунтом.GET /seller/telegram/connect-linkотдаёт готовый deep link с коротким signed token; frontend больше не должен собирать bot URL вручную.POST /seller/telegram/verifyиDELETE /seller/telegramвозвращают{ success, username }, гдеusernameможет бытьnull.
Seller item status-модель теперь включает
DRAFT,PENDING,ACTIVE,REJECTED.GET /seller/itemsиGET /seller/items/:idдополнительно публикуютlatestModerationRecord, чтобы frontend мог показать последнюю seller-visible причину/комментарий модерации.PUT /seller/items/:idбольше не разрешён дляPENDINGайтемов: seller должен сначала вызватьPOST /seller/items/:id/withdraw.
Seller review surface теперь публикуется отдельно:
GET /seller/reviewsотдаёт список отзывов по айтемам продавца со статусом,sellerReply,sellerReplyAt,canReply,canEditReplyиactiveComplaint.POST /seller/reviews/:id/complaintдоступен только дляPUBLISHED-отзывов, переводит отзыв вPENDING_MODERATIONи временно убирает его из public aggregates, аPATCH /seller/reviews/:id/replyразрешён только в течение 48 часов после последнего ответа продавца.
Seller notification baseline теперь публикует
GET/PATCH /seller/notification-settingsс полямиnotifyNewLeadTelegram,notifyNewLeadEmail,notifyStatusChangeTelegram,telegramConnected,telegramUsername,sellerEmail. После создания лидаLeadServiceсначала пытается Telegram-доставку продавцу, а при её отказе/невозможности и включённомnotifyNewLeadEmailпереходит на SMTP-capable email fallback; если SMTP не настроен на конкретном окружении, backend фиксируетSKIPPED, но не ломает создание лида.sellerEmailтеперь резолвится из seller profile email с fallback на account email. Для owner-facing status-change notificationsnotifyStatusChangeTelegramбольше не является пустым флагом: если статус меняет активныйSELLER_STAFF, backend шлёт owner-уведомление по выбранным статусам изSELLER_STATUS_CHANGE_NOTIFY_STATUSESи при недоступном Telegram так же переходит на email fallback.
Catalog (Public)
| Метод | Path | Auth | Описание |
|---|---|---|---|
| GET | /catalog/items | Public | Список опубликованных товаров с фильтрами |
| GET | /catalog/items/:slug | Public | Товар по slug (трекается событие view_item) |
| GET | /catalog/items/:slug/reviews | Public | Отзывы на товар |
| GET | /subjects | Public | Публичный alias справочника направлений |
| GET | /catalog/subjects | Public | Категории / предметы |
| GET | /catalog/locations | Public | Локации |
| GET | /sellers/:id | Public | Публичный профиль seller |
GET /sellers/:idтеперь публикует не только витринные поля seller и список опубликованных айтемов, но и явныйseoblock (title,description,canonicalUrl,openGraph,jsonLd) для SSR/metadata слоя. Профиль отдаётся только дляACTIVEseller-аккаунтов; несуществующий или непубличный seller должен давать404.
Admin (роль: ADMIN)
| Метод | Path | Auth | Описание |
|---|---|---|---|
| GET | /admin/stats | qadam_at или Bearer | Статистика дашборда |
| GET | /admin/leads | qadam_at или Bearer | Все заявки в системе |
| GET | /admin/sellers | qadam_at или Bearer | Пагинированный список seller-аккаунтов для admin-операций |
| PATCH | /admin/sellers/:sellerId/status | qadam_at или Bearer | Изменить account status seller-профиля |
| GET | /admin/moderation/items | qadam_at или Bearer | Товары на модерации |
| GET | /admin/moderation/items/:id | qadam_at или Bearer | Товар для проверки |
| POST | /admin/moderation/items/:id/approve | qadam_at или Bearer | Одобрить товар (опциональный комментарий) |
| POST | /admin/moderation/items/:id/reject | qadam_at или Bearer | Отклонить товар (причина обязательна) |
| GET | /admin/moderation/reviews | qadam_at или Bearer | Очередь отзывов на модерацию |
| GET | /admin/moderation/reviews/:id | qadam_at или Bearer | Отзыв для модерации |
| PATCH | /admin/moderation/reviews/:id | qadam_at или Bearer | Принять moderation decision по отзыву |
| POST | /catalog/subjects | qadam_at или Bearer | Создать категорию |
| PUT | /catalog/subjects/:id | qadam_at или Bearer | Обновить категорию |
| DELETE | /catalog/subjects/:id | qadam_at или Bearer | Удалить категорию |
| POST | /catalog/locations | qadam_at или Bearer | Создать локацию |
| PUT | /catalog/locations/:id | qadam_at или Bearer | Обновить локацию |
| DELETE | /catalog/locations/:id | qadam_at или Bearer | Удалить локацию |
GET /admin/sellersпринимает фильтрыsearch,status,sellerType,page,limitи возвращает seller summary сdisplayName,accountStatus, contact fields и item counters (totalItems,pendingItems,activeItems), чтобы admin мог работать со статусами без ручного знанияsellerId.
После
PATCH /admin/sellers/:sellerId/statusseller-facing защищённые маршруты больше не маскируют статус аккаунта под generic token error: backend отдаёт явные403 ACCOUNT_UNDER_REVIEWили403 ACCOUNT_BLOCKED, если seller пытается идти в защищённый контур со старым access token.
Review moderation теперь живёт на отдельном backend-срезе:
ReviewStatusвключаетPENDING,PUBLISHED,REJECTED,PENDING_MODERATION; admin принимает решение черезPATCH /admin/moderation/reviews/:id, catalog/public seller aggregates считают толькоPUBLISHED, а seller complaint flow переводит спорный отзыв обратно вPENDING_MODERATION.
Uploads
| Метод | Path | Auth | Описание |
|---|---|---|---|
| POST | /upload/image | qadam_at или Bearer | Загрузить JPG/PNG/WebP до 5 МБ и получить публичный URL |
| GET | /uploads/images/:fileName | Public | Публичная выдача уже загруженного изображения |
Текущий production уже переведён на S3-compatible storage
DigitalOcean Spaces, поэтому новые upload'ы обычно возвращают абсолютный публичный URL. Локальный/uploads/images/<fileName>остаётся compatibility/fallback-вариантом дляOBJECT_STORAGE_DRIVER=localи старых локальных файлов. Canonical transport contract для upload endpoint остаётся тем же:{ url: string }, гдеurlявляется готовым публичным URL.
Tracking
| Метод | Path | Auth | Описание |
|---|---|---|---|
| POST | /track | Public | Отправить событие трекинга. Если пользователь авторизован — привязывается к нему, иначе по IP. Cookie qadam_cid используется как client ID. |
Admin moderation endpoints теперь принимают решение только по
PENDINGайтемам. Если айтем уже ушёл вACTIVEилиREJECTED, backend возвращает конфликт статуса, аGET /admin/moderation/items/:idпубликуетlatestModerationRecordиmoderationHistory.