openapi: 3.0.3 info: title: Sarex Backend API version: "1.1.12" description: | REST API сервиса **sarex-backend** — монолитное Django-приложение (проект `config`, бизнес-логика в пакете `sarex`) на Django REST Framework. Отдаётся через uWSGI (`config.wsgi:application`) на порту `8000`. Документ описывает основную поверхность публичного API под префиксом `/api/` и внутреннего API под префиксом `/internal/`. Маршрутизация собирается в `config/urls.py` и включаемых `sarex/*/api/urls.py`. Многие ресурсы зарегистрированы через DRF-роутеры (`SimpleRouter`/`DefaultRouter`), поэтому поддерживают стандартный набор действий (list/create/retrieve/update/ partial_update/destroy). Конкретные схемы запросов/ответов в коде не объявлены декларативно (используется `rest_framework.schemas.coreapi.AutoSchema`), поэтому тела здесь описаны обобщённо. ### Аутентификация Большинство эндпоинтов требуют аутентификации (DRF `DEFAULT_PERMISSION_CLASSES = [IsAuthenticated]`). Поддерживаются несколько механизмов (`DEFAULT_AUTHENTICATION_CLASSES`): Zitadel JWT, SimpleJWT (`Authorization: Bearer `, алгоритм `RS512`), Basic, Session, RemoteUser. Токены выпускаются эндпоинтами `/api/token…`. ### Пагинация По умолчанию используется `LimitOffsetPagination` (`PAGE_SIZE = 1000`). Списочные ответы содержат `count`, `next`, `previous`, `results`. ### Замечание о полноте Перечислены основные маршруты. Часть включаемых подмодулей (`sarex/pg/api/*`, `sarex/mar/*`, `sarex/base/api/commons`) представлена группами; детальные под-пути см. в соответствующих `urls.py`. servers: - url: https://api.sarex.io description: prod - url: https://stage-api.sarex.io description: stage - url: / description: contour (относительные пути) security: - bearerAuth: [] tags: - name: auth description: Аутентификация и JWT-токены - name: base description: Уведомления, workflows, модули, health - name: core description: Пользователи, компании, цели, миссии, медиа - name: client description: Клиентский дашборд и self-сервис - name: analytics description: Дашборды, метрики, виджеты - name: map description: Кадастр и заметки на карте - name: pg description: Облака точек, экспорт, измерения - name: internal description: Внутрикластерные вызовы - name: system description: Метрики и служебные эндпоинты paths: # --------------------------------------------------------------------------- # Auth / tokens # --------------------------------------------------------------------------- /api/login/: post: tags: [auth] summary: Вход пользователя (сессия) security: [] responses: "200": { $ref: "#/components/responses/Ok" } "401": { $ref: "#/components/responses/Unauthorized" } /api/logout/: post: tags: [auth] summary: Выход пользователя responses: "200": { $ref: "#/components/responses/Ok" } /api/app-settings/: get: tags: [auth] summary: Настройки приложения responses: "200": { $ref: "#/components/responses/Ok" } /api/token/: post: tags: [auth] summary: Получить пару access/refresh токенов security: [] requestBody: { $ref: "#/components/requestBodies/Generic" } responses: "200": { $ref: "#/components/responses/TokenPair" } "401": { $ref: "#/components/responses/Unauthorized" } /api/token/me: post: tags: [auth] summary: Токен для текущего пользователя responses: "200": { $ref: "#/components/responses/TokenPair" } /api/token/user/{pk}/: post: tags: [auth] summary: Токен для пользователя по id (из админки) parameters: [ { $ref: "#/components/parameters/PkPath" } ] responses: "200": { $ref: "#/components/responses/TokenPair" } /api/token/jwks: get: tags: [auth] summary: JWKS (набор публичных ключей) security: [] responses: "200": { $ref: "#/components/responses/Ok" } /api/token/refresh/: post: tags: [auth] summary: Обновить access-токен (ротация) security: [] requestBody: { $ref: "#/components/requestBodies/Generic" } responses: "200": { $ref: "#/components/responses/TokenPair" } /api/token/public/: get: tags: [auth] summary: Публичный ключ проверки JWT security: [] responses: "200": { $ref: "#/components/responses/Ok" } /api/auth/obtain/: post: tags: [auth] summary: Получить refresh-токен security: [] requestBody: { $ref: "#/components/requestBodies/Generic" } responses: "200": { $ref: "#/components/responses/TokenPair" } /api/auth/refresh/: post: tags: [auth] summary: Обновить access-токен security: [] requestBody: { $ref: "#/components/requestBodies/Generic" } responses: "200": { $ref: "#/components/responses/TokenPair" } # --------------------------------------------------------------------------- # System # --------------------------------------------------------------------------- /metrics: get: tags: [system] summary: Метрики Prometheus security: [] responses: "200": { $ref: "#/components/responses/Ok" } /api/health/: get: tags: [base] summary: Health check security: [] responses: "200": { $ref: "#/components/responses/Ok" } # --------------------------------------------------------------------------- # Base # --------------------------------------------------------------------------- /api/modules/: get: tags: [base] summary: Список доступных модулей responses: "200": { $ref: "#/components/responses/Ok" } /api/update/notifications/: post: tags: [base] summary: Массовое обновление уведомлений responses: "200": { $ref: "#/components/responses/Ok" } /api/workflows/: get: tags: [base] summary: Список workflow responses: "200": { $ref: "#/components/responses/List" } /api/workflows/{id}/: parameters: [ { $ref: "#/components/parameters/IdPath" } ] get: tags: [base] summary: Workflow по id responses: "200": { $ref: "#/components/responses/Ok" } /api/notifications/: get: tags: [base] summary: Список уведомлений responses: "200": { $ref: "#/components/responses/List" } /api/notifications/{id}/: parameters: [ { $ref: "#/components/parameters/IdPath" } ] get: tags: [base] summary: Уведомление по id responses: "200": { $ref: "#/components/responses/Ok" } /api/usernotifications/: get: tags: [base] summary: Пользовательские уведомления responses: "200": { $ref: "#/components/responses/List" } /api/commons/cs/: get: tags: [base] summary: Справочник систем координат responses: "200": { $ref: "#/components/responses/List" } # --------------------------------------------------------------------------- # Core — ресурсы DRF-роутера (CRUD) # --------------------------------------------------------------------------- /api/core/users/: get: tags: [core] summary: Список пользователей responses: { "200": { $ref: "#/components/responses/List" } } post: tags: [core] summary: Создать пользователя requestBody: { $ref: "#/components/requestBodies/Generic" } responses: { "201": { $ref: "#/components/responses/Ok" } } /api/core/users/{id}/: parameters: [ { $ref: "#/components/parameters/IdPath" } ] get: { tags: [core], summary: Пользователь по id, responses: { "200": { $ref: "#/components/responses/Ok" } } } put: { tags: [core], summary: Обновить пользователя, requestBody: { $ref: "#/components/requestBodies/Generic" }, responses: { "200": { $ref: "#/components/responses/Ok" } } } patch: { tags: [core], summary: Частично обновить пользователя, requestBody: { $ref: "#/components/requestBodies/Generic" }, responses: { "200": { $ref: "#/components/responses/Ok" } } } delete: { tags: [core], summary: Удалить пользователя, responses: { "204": { description: No Content } } } /api/core/users/introspect: get: tags: [core] summary: Интроспекция текущего пользователя responses: { "200": { $ref: "#/components/responses/Ok" } } /api/core/users/{pk}/introspect: parameters: [ { $ref: "#/components/parameters/PkPath" } ] get: tags: [core] summary: Интроспекция пользователя (админ) responses: { "200": { $ref: "#/components/responses/Ok" } } /api/core/users/bulk/notifications/: post: tags: [core] summary: Массовое обновление уведомлений пользователей responses: { "200": { $ref: "#/components/responses/Ok" } } /api/core/users_by_sa/: get: tags: [core] summary: Пользователи по сервисному аккаунту responses: { "200": { $ref: "#/components/responses/List" } } /api/core/v2/users/: get: tags: [core] summary: Упрощённый список пользователей (v2) responses: { "200": { $ref: "#/components/responses/List" } } /api/core/v3/users/: get: tags: [core] summary: Оптимизированный список пользователей (v3) responses: { "200": { $ref: "#/components/responses/List" } } /api/core/companies/: get: { tags: [core], summary: Список компаний, responses: { "200": { $ref: "#/components/responses/List" } } } post: { tags: [core], summary: Создать компанию, requestBody: { $ref: "#/components/requestBodies/Generic" }, responses: { "201": { $ref: "#/components/responses/Ok" } } } /api/core/companies/{id}/: parameters: [ { $ref: "#/components/parameters/IdPath" } ] get: { tags: [core], summary: Компания по id, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/core/surfaces/: get: { tags: [core], summary: Список поверхностей, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/mesh/: get: { tags: [core], summary: Список mesh, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/multiple-surface/: get: { tags: [core], summary: Множественные поверхности, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/state/: get: { tags: [core], summary: Состояние приложения, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/polygons/: get: { tags: [core], summary: Полигоны, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/media-notes/: get: { tags: [core], summary: Медиа-заметки, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/media-notes-comments/: get: { tags: [core], summary: Комментарии медиа-заметок, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/media-notes-attachments/: get: { tags: [core], summary: Вложения медиа-заметок, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/media-folders/: get: { tags: [core], summary: Папки медиа, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/target-links/: get: { tags: [core], summary: Ссылки на цели, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/materials/: get: { tags: [core], summary: Материалы, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/pointclouds/: get: { tags: [core], summary: Облака точек, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/orthophotos/: get: { tags: [core], summary: Ортофотопланы, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/videos/: get: { tags: [core], summary: Видео, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/photos/: get: { tags: [core], summary: Фото, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/panoramas/: get: { tags: [core], summary: Панорамы, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/color-presets/: get: { tags: [core], summary: Цветовые пресеты компании, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/missions/: get: { tags: [core], summary: Список миссий, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/missions/import/: get: { tags: [core], summary: Задачи импорта миссий, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/missions/import/create/: post: { tags: [core], summary: Создать задачу импорта миссии, responses: { "201": { $ref: "#/components/responses/Ok" } } } /api/core/targets/: get: { tags: [core], summary: Список целей, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/targets/v2/: get: { tags: [core], summary: Список целей (v2), responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/targets/v3/: get: { tags: [core], summary: Список целей (v3), responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/targets/tree/: get: { tags: [core], summary: Дерево целей, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/targets/pdm/: get: { tags: [core], summary: Цели PDM, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/targets/{id}/missions/: parameters: [ { $ref: "#/components/parameters/IdPath" } ] get: { tags: [core], summary: Миссии цели, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/export/: get: { tags: [core], summary: Экспорт данных, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/core/export/pointcloud/: post: { tags: [core], summary: Экспорт региона из облака точек, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/core/contour/export/: post: { tags: [core], summary: Экспорт контура, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/core/contour/exports/: get: { tags: [core], summary: Список экспортов контура, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/uploads/streaming/: post: { tags: [core], summary: Потоковая загрузка (создание), responses: { "201": { $ref: "#/components/responses/Ok" } } } /api/core/uploads/streaming/{pk}/: parameters: [ { $ref: "#/components/parameters/PkStrPath" } ] put: { tags: [core], summary: Догрузка чанка, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/core/storage-cleanup/: post: { tags: [core], summary: Очистка хранилища, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/core/celery/stats: get: { tags: [core], summary: Статистика Celery, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/core/celery/active: get: { tags: [core], summary: Активные задачи Celery, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/core/celery/scheduled: get: { tags: [core], summary: Запланированные задачи Celery, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/core/celery/{uuid}/details/: parameters: [ { name: uuid, in: path, required: true, schema: { type: string } } ] get: { tags: [core], summary: Детали задачи Celery, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/core/admin/users/: get: { tags: [core], summary: Админ — пользователи, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/admin/groups/: get: { tags: [core], summary: Админ — группы, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/admin/companies/: get: { tags: [core], summary: Админ — компании, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/admin/positions/: get: { tags: [core], summary: Админ — должности, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/admin/departments/: get: { tags: [core], summary: Админ — подразделения, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/admin/contractors/: get: { tags: [core], summary: Админ — подрядчики, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/admin/permissions/: get: { tags: [core], summary: Админ — права, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/service_accounts/: get: { tags: [core], summary: Сервисные аккаунты, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/service-accounts/personalized/: get: { tags: [core], summary: Персонализированный сервисный аккаунт, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/core/service-accounts/user/{user_id}/: parameters: [ { name: user_id, in: path, required: true, schema: { type: integer } } ] get: { tags: [core], summary: Сервисный аккаунт пользователя (v2), responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/core/c2s-comparisons/: post: { tags: [core], summary: Создать c2s-сравнение, responses: { "201": { $ref: "#/components/responses/Ok" } } } /api/core/permissions/: get: { tags: [core], summary: Права (только чтение), responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/units/: get: { tags: [core], summary: Единицы измерения, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/upload/media-file/: post: { tags: [core], summary: Загрузка медиа-файла, responses: { "201": { $ref: "#/components/responses/Ok" } } } /api/core/mrpa/list/: get: { tags: [core], summary: Список MRPA, responses: { "200": { $ref: "#/components/responses/List" } } } /api/core/mrpa/: post: { tags: [core], summary: Создать MRPA, responses: { "201": { $ref: "#/components/responses/Ok" } } } /api/core/mrpa/{pk}/: parameters: [ { name: pk, in: path, required: true, schema: { type: string, format: uuid } } ] get: { tags: [core], summary: MRPA по id, responses: { "200": { $ref: "#/components/responses/Ok" } } } # --------------------------------------------------------------------------- # Client # --------------------------------------------------------------------------- /api/client/dashboard/targets/: get: { tags: [client], summary: Дашборд — цели, responses: { "200": { $ref: "#/components/responses/List" } } } /api/client/dashboard/missions/: get: { tags: [client], summary: Дашборд — миссии, responses: { "200": { $ref: "#/components/responses/List" } } } /api/client/dashboard/webcams/: get: { tags: [client], summary: Дашборд — веб-камеры, responses: { "200": { $ref: "#/components/responses/List" } } } /api/client/settings/: get: { tags: [client], summary: Настройки пользователя, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/client/settings/user/{user_id}/: parameters: [ { name: user_id, in: path, required: true, schema: { type: integer } } ] get: { tags: [client], summary: Настройки пользователя по id, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/client/self/: get: { tags: [client], summary: Информация о себе, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/client/self/set_password/: post: { tags: [client], summary: Смена пароля, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/client/uploads/: get: { tags: [client], summary: Загрузки клиента, responses: { "200": { $ref: "#/components/responses/List" } } } /api/client/folders/: get: { tags: [client], summary: Папки загрузок клиента, responses: { "200": { $ref: "#/components/responses/List" } } } # --------------------------------------------------------------------------- # Analytics # --------------------------------------------------------------------------- /api/analytics/dashboards/: get: { tags: [analytics], summary: Дашборды, responses: { "200": { $ref: "#/components/responses/List" } } } /api/analytics/widgets/: get: { tags: [analytics], summary: Виджеты, responses: { "200": { $ref: "#/components/responses/List" } } } /api/analytics/metrics/: get: { tags: [analytics], summary: Метрики, responses: { "200": { $ref: "#/components/responses/List" } } } /api/analytics/expressions/: get: { tags: [analytics], summary: Выражения, responses: { "200": { $ref: "#/components/responses/List" } } } /api/analytics/folders/: get: { tags: [analytics], summary: Папки метрик, responses: { "200": { $ref: "#/components/responses/List" } } } /api/analytics/filters/: get: { tags: [analytics], summary: Фильтры, responses: { "200": { $ref: "#/components/responses/List" } } } /api/analytics/groups/: get: { tags: [analytics], summary: Группы, responses: { "200": { $ref: "#/components/responses/List" } } } /api/analytics/values/: get: { tags: [analytics], summary: Значения метрик, responses: { "200": { $ref: "#/components/responses/List" } } } /api/analytics/attributes/: get: { tags: [analytics], summary: Атрибуты, responses: { "200": { $ref: "#/components/responses/List" } } } /api/analytics/attachments/: get: { tags: [analytics], summary: Вложения дашбордов, responses: { "200": { $ref: "#/components/responses/List" } } } /api/analytics/reviews-service-feed/: post: { tags: [analytics], summary: Приём событий из сервиса reviews, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/analytics/remarks-service-feed/: post: { tags: [analytics], summary: Приём событий из сервиса remarks, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/analytics/tracking-service-feed/: post: { tags: [analytics], summary: Приём событий трекинга, responses: { "200": { $ref: "#/components/responses/Ok" } } } # --------------------------------------------------------------------------- # Map # --------------------------------------------------------------------------- /api/map/cadastre/point/: get: { tags: [map], summary: Данные кадастра по точке, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/map/cadastre/export/: post: { tags: [map], summary: Экспорт кадастровых данных, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/map/cadastre/wikimapia/redirect/: get: { tags: [map], summary: Редирект Wikimapia, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/map/notes/: get: { tags: [map], summary: Заметки на ортофото, responses: { "200": { $ref: "#/components/responses/List" } } } /api/map/notes/folders/: get: { tags: [map], summary: Папки заметок на ортофото, responses: { "200": { $ref: "#/components/responses/List" } } } /api/ds/telecom/cadastre/: get: { tags: [map], summary: Изображение кадастра (telecom), responses: { "200": { $ref: "#/components/responses/Ok" } } } # --------------------------------------------------------------------------- # PG (облака точек / экспорт / измерения) # --------------------------------------------------------------------------- /api/pg/pointclouds/: get: { tags: [pg], summary: Облака точек, responses: { "200": { $ref: "#/components/responses/List" } } } /api/pg/pointclouds/{pointcloud}/measurements/: parameters: [ { name: pointcloud, in: path, required: true, schema: { type: string } } ] get: { tags: [pg], summary: Измерения облака точек, responses: { "200": { $ref: "#/components/responses/List" } } } /api/pg/volume-dynamic/: get: { tags: [pg], summary: Динамика объёмов, responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/pg/orthomosaicexport/: get: { tags: [pg], summary: Экспорт ортомозаики (кастомный), responses: { "200": { $ref: "#/components/responses/List" } } } /api/pg/exports/pointcloud/: get: { tags: [pg], summary: Экспорты облаков точек, responses: { "200": { $ref: "#/components/responses/List" } } } /api/pg/exports/orthomosaic/: get: { tags: [pg], summary: Экспорты ортомозаики, responses: { "200": { $ref: "#/components/responses/List" } } } /api/pg/measurements/: get: { tags: [pg], summary: Измерения (подмодуль), responses: { "200": { $ref: "#/components/responses/List" } } } /api/pg/attachments/: get: { tags: [pg], summary: Вложения (подмодуль), responses: { "200": { $ref: "#/components/responses/List" } } } /api/pg/compare/: get: { tags: [pg], summary: Сравнение (подмодуль), responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/pg/export/: get: { tags: [pg], summary: Экспорт (подмодуль), responses: { "200": { $ref: "#/components/responses/Ok" } } } /api/pg/pdf-overlays/: get: { tags: [pg], summary: PDF-оверлеи (подмодуль), responses: { "200": { $ref: "#/components/responses/List" } } } /api/pg/projects/: get: { tags: [pg], summary: Проекты Metashape (при SERVER_USE_METASHAPE), responses: { "200": { $ref: "#/components/responses/List" } } } # --------------------------------------------------------------------------- # Internal # --------------------------------------------------------------------------- /internal/client/settings/{pk}/: parameters: [ { $ref: "#/components/parameters/PkPath" } ] get: tags: [internal] summary: Внутренние настройки клиента responses: { "200": { $ref: "#/components/responses/Ok" } } /internal/client/token/{pk}/: parameters: [ { $ref: "#/components/parameters/PkPath" } ] get: tags: [internal] summary: Внутренний токен клиента responses: { "200": { $ref: "#/components/responses/TokenPair" } } components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT parameters: IdPath: name: id in: path required: true schema: { type: integer } PkPath: name: pk in: path required: true schema: { type: integer } PkStrPath: name: pk in: path required: true schema: { type: string } requestBodies: Generic: required: true content: application/json: schema: type: object additionalProperties: true responses: Ok: description: Успешный ответ content: application/json: schema: type: object additionalProperties: true List: description: Списочный ответ с пагинацией (LimitOffset) content: application/json: schema: $ref: "#/components/schemas/PaginatedList" TokenPair: description: Пара токенов content: application/json: schema: $ref: "#/components/schemas/TokenPair" Unauthorized: description: Не аутентифицирован content: application/json: schema: $ref: "#/components/schemas/Error" schemas: PaginatedList: type: object properties: count: { type: integer } next: { type: string, nullable: true, format: uri } previous: { type: string, nullable: true, format: uri } results: type: array items: type: object additionalProperties: true TokenPair: type: object properties: access: { type: string } refresh: { type: string } Error: type: object properties: detail: { type: string }