1159 lines
41 KiB
YAML
1159 lines
41 KiB
YAML
openapi: 3.0.3
|
||
|
||
info:
|
||
title: BIM Backend v2 API
|
||
version: "2.0.0"
|
||
description: |
|
||
REST API сервиса **bim-backend-v2** (`platform/bim-backend-v2`) — работа с
|
||
BIM-моделями, их элементами, свойствами, моделями статусов и метаданными.
|
||
|
||
Сервис написан на Go. HTTP-сервер собирается в
|
||
`internal/app/http/httpserver.go` (роутер `gorilla/mux` поверх
|
||
`pkg/gotools/rest`). Роутинг состоит из трёх групп:
|
||
|
||
- публичный API v1 — префикс `/api/v1` (`internal/controller/http/v1`);
|
||
- публичный API v2 — префикс `/api/v2`, работа с BIM v3
|
||
(`internal/controller/http/v2`);
|
||
- внутренний API v1 — префикс `/internal/v1`
|
||
(`internal/controller/http/v1/bim_internal` и часть роутов `bim`),
|
||
предназначен для вызовов внутри кластера (через ingress не публикуется,
|
||
доступ ограничивается Istio `AuthorizationPolicy` по namespace).
|
||
|
||
Health-check доступен по `GET /ping` (без префикса и без аутентификации),
|
||
профилировщик `net/http/pprof` — на отдельном порту `:8081`.
|
||
|
||
### Аутентификация
|
||
Публичные эндпоинты (`/api/v1/*`, `/api/v2/*`) требуют JWT. Токен
|
||
передаётся заголовком `Authorization: Bearer <jwt>` либо query-параметром
|
||
`auth_jwt` (`pkg/gotools/auth.JWTToCtx`). Затем `pkg/auth`
|
||
(`JWTUserExtractorFromCtx`) извлекает `user_id`:
|
||
|
||
1. если передан заголовок `Identity` — id берётся из Zitadel-токена
|
||
(claim `urn:zitadel:iam:user:metadata`, поле `user_id`, base64url);
|
||
2. иначе — из числового claim `user_id` основного JWT.
|
||
|
||
Подпись токена приложением **не проверяется** (проверка выполняется на
|
||
уровне Istio по claim `token_type=access`). При отсутствии/непарсинге
|
||
токена возвращается `401` с пустым телом.
|
||
|
||
Изменение моделей статусов дополнительно требует прав администратора
|
||
(проверка через Django, см. `ENDPOINTS.md`); при их отсутствии — `403`.
|
||
|
||
Внутренние эндпоинты (`/internal/v1/*`) аутентификации на уровне
|
||
приложения не требуют — доступ ограничен сетевым слоем (Istio, namespace).
|
||
|
||
### Идентификаторы
|
||
Все path-параметры (`bim_id`, `project_id`, `company_id`, `sarex_id` и т.п.)
|
||
парсятся как `uint64`; неверный формат → `400`.
|
||
|
||
### Формат ошибок
|
||
Ошибки из обработчиков возвращаются как `{ "error": "<сообщение>" }`
|
||
(`pkg/gotools/httperror`). Исключения: `401` от middleware (пустое тело),
|
||
а также `404`/`405` от роутера (текст `404 route not found` /
|
||
`405 method not allowed`).
|
||
|
||
servers:
|
||
- url: https://api.sarex.io/bimv2
|
||
description: production (через api-gateway, префикс api_host_prefix)
|
||
- url: https://stage-api.sarex.io/bimv2
|
||
description: stage
|
||
- url: http://localhost:5555
|
||
description: локальный запуск
|
||
|
||
tags:
|
||
- name: bim-v1
|
||
description: BIM, элементы, свойства, статусы (API v1)
|
||
- name: metadata
|
||
description: Метаданные BIM (API v1)
|
||
- name: company-status-model
|
||
description: Модели статусов компании (API v1)
|
||
- name: internal-v1
|
||
description: Внутренние эндпоинты (только внутри кластера)
|
||
- name: bim-v2
|
||
description: BIM v3 (API v2)
|
||
- name: service
|
||
description: Служебные эндпоинты
|
||
|
||
security:
|
||
- bearerAuth: []
|
||
|
||
paths:
|
||
/ping:
|
||
get:
|
||
tags: [service]
|
||
summary: Health-check
|
||
security: []
|
||
responses:
|
||
"200":
|
||
description: Сервис работоспособен
|
||
|
||
/api/v1/projects/{project_id}/bims:
|
||
get:
|
||
tags: [bim-v1]
|
||
summary: Список BIM проекта
|
||
parameters:
|
||
- $ref: '#/components/parameters/ProjectId'
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
bims:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/Bim' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims:
|
||
get:
|
||
tags: [bim-v1]
|
||
summary: Список BIM по набору id
|
||
parameters:
|
||
- name: bim_id
|
||
in: query
|
||
required: true
|
||
description: Список id BIM через запятую (напр. `1,2,3`)
|
||
schema: { type: string }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/Bim' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}:
|
||
get:
|
||
tags: [bim-v1]
|
||
summary: BIM по id
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/Bim' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"404": { $ref: '#/components/responses/NotFound' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/sarexid/{sarex_id}:
|
||
get:
|
||
tags: [bim-v1]
|
||
summary: Элементы BIM по sarex_id (из пути)
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
- name: sarex_id
|
||
in: path
|
||
required: true
|
||
description: Список sarex_id через запятую
|
||
schema: { type: string }
|
||
- $ref: '#/components/parameters/WithHierarchy'
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/BIMElementsResult' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/sarexid:
|
||
post:
|
||
tags: [bim-v1]
|
||
summary: Элементы BIM по sarex_id (из тела)
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
- $ref: '#/components/parameters/WithHierarchy'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/GetBimElementsRequest' }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/BIMElementsResult' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/changes:
|
||
get:
|
||
tags: [bim-v1]
|
||
summary: История изменений статусов элементов BIM
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
- { name: offset, in: query, required: false, schema: { type: integer, format: int64, default: 0 } }
|
||
- { name: limit, in: query, required: false, schema: { type: integer, format: int64, default: 20 } }
|
||
- { name: status_type, in: query, required: false, description: 'Типы статусов через запятую', schema: { type: string } }
|
||
- { name: sarex_ids, in: query, required: false, description: 'sarex_id через запятую', schema: { type: string } }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/PaginatedChangesResponse' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
post:
|
||
tags: [bim-v1]
|
||
summary: Установить статус элементам BIM
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
- $ref: '#/components/parameters/WithHierarchy'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/SetStatusBodyRequest' }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/SetStatusResponse' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/elements:
|
||
get:
|
||
tags: [bim-v1]
|
||
summary: Дерево элементов BIM
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
- { name: depth, in: query, required: false, schema: { type: integer, format: int64, default: 5 } }
|
||
- { name: root, in: query, required: false, schema: { type: integer, format: int64 } }
|
||
- name: statuses
|
||
in: query
|
||
required: false
|
||
description: 'Повторяемый параметр вида `type:value`'
|
||
schema: { type: array, items: { type: string } }
|
||
- { name: format, in: query, required: false, schema: { type: string, enum: [full, tiny], default: full } }
|
||
responses:
|
||
"200":
|
||
description: 'При `format=full` элементы полные, при `format=tiny` — усечённые'
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
results:
|
||
type: array
|
||
items:
|
||
oneOf:
|
||
- { $ref: '#/components/schemas/BIMElement' }
|
||
- { $ref: '#/components/schemas/BIMElementTiny' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
post:
|
||
tags: [bim-v1]
|
||
summary: Отфильтрованные элементы BIM
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/GetFilteredElementsRequest' }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/BIMElementsResult' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"404": { $ref: '#/components/responses/NotFound' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/statuses_color:
|
||
get:
|
||
tags: [bim-v1]
|
||
summary: Цвета статусов BIM
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
responses:
|
||
"200":
|
||
description: 'Ключ — имя модели статусов'
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
additionalProperties:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/StatusColorRequest' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"404": { $ref: '#/components/responses/NotFound' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/status_models:
|
||
get:
|
||
tags: [bim-v1]
|
||
summary: Модели статусов BIM
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/StatusCategory' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"404": { $ref: '#/components/responses/NotFound' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/status_model:
|
||
post:
|
||
tags: [bim-v1]
|
||
summary: Создать модель статусов BIM (требует прав администратора)
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/StatusCategory' }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/OkResponse' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"403": { $ref: '#/components/responses/Forbidden' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/delete_status_model:
|
||
delete:
|
||
tags: [bim-v1]
|
||
summary: Удалить модель статусов BIM (требует прав администратора)
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
- name: status_type
|
||
in: query
|
||
required: true
|
||
description: 'Имя модели статусов. Значение по умолчанию (`building`) удалить нельзя'
|
||
schema: { type: string }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/OkResponse' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"403": { $ref: '#/components/responses/Forbidden' }
|
||
"404": { $ref: '#/components/responses/NotFound' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/filter_fields:
|
||
get:
|
||
tags: [bim-v1]
|
||
summary: Поля для фильтрации элементов BIM
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
responses:
|
||
"200":
|
||
description: 'Категория → свойство → дескриптор фильтра (multiselector/slider/checkbox)'
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
additionalProperties:
|
||
type: object
|
||
additionalProperties:
|
||
oneOf:
|
||
- { $ref: '#/components/schemas/StringsType' }
|
||
- { $ref: '#/components/schemas/MinMaxType' }
|
||
- { $ref: '#/components/schemas/BooleansType' }
|
||
"404": { $ref: '#/components/responses/NotFound' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/properties:
|
||
get:
|
||
tags: [bim-v1]
|
||
summary: Свойства всех элементов BIM
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
responses:
|
||
"200":
|
||
description: 'sarex_id → категория → свойство → значение. Пустой объект, если таблица свойств отсутствует'
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
additionalProperties:
|
||
type: object
|
||
additionalProperties:
|
||
type: object
|
||
additionalProperties: true
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/elements/{sarex_id}/properties:
|
||
get:
|
||
tags: [bim-v1]
|
||
summary: Свойства одного элемента BIM
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
- { name: sarex_id, in: path, required: true, schema: { type: integer, format: int64 } }
|
||
responses:
|
||
"200":
|
||
description: 'категория → свойство → значение'
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
additionalProperties:
|
||
type: object
|
||
additionalProperties: true
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"404": { $ref: '#/components/responses/NotFound' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/statuses:
|
||
get:
|
||
tags: [bim-v1]
|
||
summary: Статусы элементов BIM
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
- name: statuses
|
||
in: query
|
||
required: false
|
||
description: 'Повторяемый параметр вида `type:value`'
|
||
schema: { type: array, items: { type: string } }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
results:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/BIMElementStatuses' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/filter_by_statuses:
|
||
get:
|
||
tags: [bim-v1]
|
||
summary: sarex_id элементов, сгруппированные по статусам
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
- name: statuses
|
||
in: query
|
||
required: false
|
||
description: 'Повторяемый параметр вида `type:value`'
|
||
schema: { type: array, items: { type: string } }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/FilterElementsByStatusResponse' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/csv_properties:
|
||
post:
|
||
tags: [bim-v1]
|
||
summary: CSV-отчёт по свойствам элементов BIM
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/GetCSVPropertiesReportRequest' }
|
||
responses:
|
||
"200":
|
||
description: 'CSV-файл (разделитель `;`). Заголовки Content-Disposition: attachment; filename=<uuid>.csv'
|
||
content:
|
||
text/csv:
|
||
schema: { type: string, format: binary }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"404": { $ref: '#/components/responses/NotFound' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/metadata:
|
||
get:
|
||
tags: [metadata]
|
||
summary: Метаданные BIM
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/GetMetadataResponse' }
|
||
"404": { $ref: '#/components/responses/NotFound' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/bims/{bim_id}/metadata/transform:
|
||
patch:
|
||
tags: [metadata]
|
||
summary: Обновить матрицу трансформации BIM
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/SetMetadataTransformRequest' }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/OkResponse' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v1/companies/{company_id}/status_model:
|
||
post:
|
||
tags: [company-status-model]
|
||
summary: Создать модель статусов компании (требует прав администратора)
|
||
parameters:
|
||
- $ref: '#/components/parameters/CompanyId'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/StatusCategory' }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
result: { $ref: '#/components/schemas/CompanyStatusModel' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"403": { $ref: '#/components/responses/Forbidden' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
get:
|
||
tags: [company-status-model]
|
||
summary: Модель статусов компании
|
||
parameters:
|
||
- $ref: '#/components/parameters/CompanyId'
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
result: { $ref: '#/components/schemas/CompanyStatusModel' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"404": { $ref: '#/components/responses/NotFound' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
delete:
|
||
tags: [company-status-model]
|
||
summary: Удалить модель статусов компании (требует прав администратора)
|
||
parameters:
|
||
- $ref: '#/components/parameters/CompanyId'
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/OkResponse' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"403": { $ref: '#/components/responses/Forbidden' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/internal/v1/bims/{bim_id}/sarexid:
|
||
post:
|
||
tags: [internal-v1]
|
||
summary: Элементы BIM по sarex_id (внутренний, без аутентификации приложения)
|
||
security: []
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
- $ref: '#/components/parameters/WithHierarchy'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/GetBimElementsRequest' }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/BIMElementsResult' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/internal/v1/projects/{project_id}/bims:
|
||
post:
|
||
tags: [internal-v1]
|
||
summary: Создать BIM в проекте (внутренний)
|
||
security: []
|
||
parameters:
|
||
- $ref: '#/components/parameters/ProjectId'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/CreateBimRequest' }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/Bim' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/internal/v1/bims/{bim_id}/filter_elements_by_status:
|
||
post:
|
||
tags: [internal-v1]
|
||
summary: Отфильтровать sarex_id по статусам (внутренний)
|
||
security: []
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/GetFilteredSarexIDsByStatusRequest' }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
sarex_ids:
|
||
type: array
|
||
items: { type: integer, format: int64 }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"404": { $ref: '#/components/responses/NotFound' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/internal/v1/bims/guid_sarex_id:
|
||
get:
|
||
tags: [internal-v1]
|
||
summary: Сопоставление GUID → sarex_id (внутренний)
|
||
security: []
|
||
parameters:
|
||
- name: bim_ids
|
||
in: query
|
||
required: true
|
||
description: 'Список id BIM через запятую'
|
||
schema: { type: string }
|
||
responses:
|
||
"200":
|
||
description: 'Ключ — GUID элемента'
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
additionalProperties: { $ref: '#/components/schemas/BimIDSarexID' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"404": { $ref: '#/components/responses/NotFound' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v2/bims:
|
||
get:
|
||
tags: [bim-v2]
|
||
summary: Список BIM v3
|
||
parameters:
|
||
- { name: company_id, in: query, required: false, schema: { type: integer, format: int64 } }
|
||
- { name: bundle_id, in: query, required: false, schema: { type: string, format: uuid } }
|
||
- { name: document_id, in: query, required: false, schema: { type: integer, format: int64 } }
|
||
- { name: bim_type, in: query, required: false, schema: { type: integer, format: int64 } }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/BIMV3' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v2/bims/{bim_id}:
|
||
get:
|
||
tags: [bim-v2]
|
||
summary: BIM v3 по id
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/BIMV3' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"404": { $ref: '#/components/responses/NotFound' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v2/bims/{bim_id}/elements:
|
||
post:
|
||
tags: [bim-v2]
|
||
summary: Список элементов BIM v3 (с фильтрами по атрибутам)
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
requestBody:
|
||
required: false
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/ListBIMElementsRequest' }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/BIMV3Element' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
/api/v2/bims/{bim_id}/elements/{sarex_id}:
|
||
get:
|
||
tags: [bim-v2]
|
||
summary: Элемент(ы) BIM v3 по sarex_id
|
||
parameters:
|
||
- $ref: '#/components/parameters/BimId'
|
||
- { name: sarex_id, in: path, required: true, schema: { type: integer, format: int64 } }
|
||
responses:
|
||
"200":
|
||
description: OK
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/BIMV3Element' }
|
||
"400": { $ref: '#/components/responses/BadRequest' }
|
||
"500": { $ref: '#/components/responses/InternalError' }
|
||
|
||
components:
|
||
securitySchemes:
|
||
bearerAuth:
|
||
type: http
|
||
scheme: bearer
|
||
bearerFormat: JWT
|
||
description: |
|
||
`Authorization: Bearer <jwt>` (или query-параметр `auth_jwt`). Дополнительно
|
||
может передаваться заголовок `Identity` для Zitadel-токена.
|
||
|
||
parameters:
|
||
BimId:
|
||
name: bim_id
|
||
in: path
|
||
required: true
|
||
schema: { type: integer, format: int64 }
|
||
ProjectId:
|
||
name: project_id
|
||
in: path
|
||
required: true
|
||
schema: { type: integer, format: int64 }
|
||
CompanyId:
|
||
name: company_id
|
||
in: path
|
||
required: true
|
||
schema: { type: integer, format: int64 }
|
||
WithHierarchy:
|
||
name: with_hierarchy
|
||
in: query
|
||
required: false
|
||
schema: { type: boolean, default: false }
|
||
|
||
responses:
|
||
BadRequest:
|
||
description: Некорректный запрос
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/Error' }
|
||
NotFound:
|
||
description: Не найдено
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/Error' }
|
||
Forbidden:
|
||
description: Недостаточно прав (нужны права администратора)
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/Error' }
|
||
InternalError:
|
||
description: Внутренняя ошибка сервера
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/Error' }
|
||
|
||
schemas:
|
||
Error:
|
||
type: object
|
||
properties:
|
||
error: { type: string }
|
||
required: [error]
|
||
|
||
OkResponse:
|
||
type: object
|
||
properties:
|
||
ok: { type: boolean, example: true }
|
||
|
||
Bim:
|
||
type: object
|
||
properties:
|
||
id: { type: integer, format: int64 }
|
||
project_id: { type: integer, format: int64 }
|
||
document_id: { type: integer, format: int64 }
|
||
created_at: { type: string, format: date-time }
|
||
status: { type: string, description: 'BimStatusType, напр. Pending' }
|
||
transform: { type: array, items: { type: number, format: double } }
|
||
status_model:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/StatusCategory' }
|
||
properties_names: { type: array, items: { type: string } }
|
||
category_properties:
|
||
type: object
|
||
additionalProperties:
|
||
type: object
|
||
additionalProperties: { type: integer, format: int64 }
|
||
data_types: { type: array, items: { type: string } }
|
||
categories_names: { type: array, items: { type: string } }
|
||
company_id: { type: integer, format: int64, nullable: true }
|
||
|
||
StatusCategory:
|
||
type: object
|
||
required: [name, verbose_name, initial_status, statuses]
|
||
properties:
|
||
name: { type: string }
|
||
verbose_name: { type: string }
|
||
initial_status: { type: string }
|
||
statuses:
|
||
type: array
|
||
minItems: 1
|
||
items: { $ref: '#/components/schemas/Statuses' }
|
||
|
||
Statuses:
|
||
type: object
|
||
required: [verbose_name, color, permissions, name, allowed_transitions]
|
||
properties:
|
||
verbose_name: { type: string }
|
||
color: { type: integer, description: '0..16777215 (RGB)' }
|
||
permissions: { type: array, items: { type: string } }
|
||
name: { type: string }
|
||
allowed_transitions: { type: array, items: { type: string } }
|
||
|
||
StatusColorRequest:
|
||
type: object
|
||
properties:
|
||
name: { type: string }
|
||
color: { type: integer }
|
||
|
||
BIMElement:
|
||
type: object
|
||
description: 'Кастомная сериализация; hierarchy разворачивается в массив uint64'
|
||
properties:
|
||
sarex_id: { type: integer, format: int64 }
|
||
name: { type: string }
|
||
hierarchy: { type: array, items: { type: integer, format: int64 } }
|
||
updated_at: { type: string, format: date-time, nullable: true }
|
||
bim_id: { type: integer, format: int64 }
|
||
statuses:
|
||
type: object
|
||
additionalProperties: { type: string }
|
||
is_leaf: { type: boolean, nullable: true }
|
||
extras_from_converter:
|
||
type: object
|
||
additionalProperties: true
|
||
nullable: true
|
||
bboxMax: { type: array, items: { type: number, format: double } }
|
||
bboxMin: { type: array, items: { type: number, format: double } }
|
||
color: { type: integer, nullable: true }
|
||
|
||
BIMElementTiny:
|
||
type: object
|
||
properties:
|
||
sarex_id: { type: integer, format: int64 }
|
||
parent_id: { type: integer, format: int64, nullable: true }
|
||
|
||
BIMElementStatuses:
|
||
type: object
|
||
properties:
|
||
sarex_id: { type: integer, format: int64 }
|
||
statuses:
|
||
type: object
|
||
additionalProperties: { type: string }
|
||
|
||
BIMElementsResult:
|
||
type: object
|
||
properties:
|
||
results:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/BIMElement' }
|
||
|
||
StringsType:
|
||
type: object
|
||
properties:
|
||
values: { type: array, items: { type: string, nullable: true } }
|
||
type: { type: string, enum: [multiselector, slider, checkbox] }
|
||
|
||
MinMaxType:
|
||
type: object
|
||
properties:
|
||
min: { type: number, format: double, nullable: true }
|
||
max: { type: number, format: double, nullable: true }
|
||
has_null: { type: boolean }
|
||
type: { type: string, enum: [multiselector, slider, checkbox] }
|
||
|
||
BooleansType:
|
||
type: object
|
||
properties:
|
||
values: { type: array, items: { type: boolean, nullable: true } }
|
||
type: { type: string, enum: [multiselector, slider, checkbox] }
|
||
|
||
FilterFieldRequestStruct:
|
||
type: object
|
||
required: [category_name, property_name]
|
||
properties:
|
||
category_name: { type: string }
|
||
property_name: { type: string }
|
||
values: { type: array, items: {} }
|
||
min: { type: number, format: double, nullable: true }
|
||
max: { type: number, format: double, nullable: true }
|
||
|
||
StatusFiltersRequestStruct:
|
||
type: object
|
||
properties:
|
||
group: { type: string }
|
||
values: { type: array, items: { type: string } }
|
||
|
||
FiltersResponse:
|
||
type: object
|
||
properties:
|
||
properties_filters:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/FilterFieldRequestStruct' }
|
||
status_filters:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/StatusFiltersRequestStruct' }
|
||
|
||
GetBimElementsRequest:
|
||
type: object
|
||
required: [sarex_ids]
|
||
properties:
|
||
sarex_ids:
|
||
type: array
|
||
minItems: 1
|
||
items: { type: integer, format: int64 }
|
||
|
||
GetFilteredElementsRequest:
|
||
type: object
|
||
required: [filters]
|
||
properties:
|
||
filters: { $ref: '#/components/schemas/FiltersResponse' }
|
||
|
||
SetStatusBodyRequest:
|
||
type: object
|
||
required: [sarex_ids, new_status_type, new_status_value]
|
||
properties:
|
||
sarex_ids:
|
||
type: array
|
||
items: { type: integer, format: int64 }
|
||
new_status_type: { type: string }
|
||
new_status_value: { type: string }
|
||
|
||
SetStatusResponse:
|
||
type: object
|
||
properties:
|
||
count: { type: integer, format: int64 }
|
||
|
||
PaginatedChangesResponse:
|
||
type: object
|
||
properties:
|
||
data:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/ChangedBimElementDTO' }
|
||
total: { type: integer, format: int64 }
|
||
count: { type: integer, format: int64 }
|
||
offset: { type: integer, format: int64 }
|
||
limit: { type: integer, format: int64 }
|
||
|
||
ChangedBimElementDTO:
|
||
type: object
|
||
properties:
|
||
bim_id: { type: integer, format: int64 }
|
||
sarex_id: { type: integer, format: int64 }
|
||
created_at: { type: string, format: date-time }
|
||
number: { type: integer, format: int64 }
|
||
author: { type: integer, format: int64 }
|
||
new_status:
|
||
type: object
|
||
additionalProperties: { type: string }
|
||
old_statuses:
|
||
type: object
|
||
additionalProperties: { type: string }
|
||
|
||
FilterElementsByStatusResponse:
|
||
type: object
|
||
properties:
|
||
results:
|
||
type: object
|
||
additionalProperties:
|
||
type: object
|
||
additionalProperties: { $ref: '#/components/schemas/ElementsResponse' }
|
||
|
||
ElementsResponse:
|
||
type: object
|
||
properties:
|
||
sarex_ids:
|
||
type: array
|
||
items: { type: integer, format: int64 }
|
||
|
||
GetCSVPropertiesReportRequest:
|
||
type: object
|
||
required: [filters]
|
||
properties:
|
||
filters:
|
||
type: object
|
||
properties:
|
||
properties_filters:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/FilterFieldRequestStruct' }
|
||
statuses_filters:
|
||
type: object
|
||
additionalProperties:
|
||
type: array
|
||
items: { type: string }
|
||
element_ids:
|
||
type: array
|
||
items: { type: integer, format: int64 }
|
||
reported_category_property:
|
||
type: object
|
||
additionalProperties:
|
||
type: array
|
||
items: { type: string }
|
||
reported_statuses:
|
||
type: array
|
||
items: { type: string }
|
||
|
||
GetMetadataResponse:
|
||
type: object
|
||
properties:
|
||
elements:
|
||
type: object
|
||
additionalProperties: { $ref: '#/components/schemas/MetaElement' }
|
||
bim: { type: integer, format: int64 }
|
||
created_at: { type: string, format: date-time }
|
||
global_transformation_matrix:
|
||
type: array
|
||
items: { type: number, format: double }
|
||
|
||
MetaElement:
|
||
type: object
|
||
properties:
|
||
name: { type: string }
|
||
hierarchy: { type: array, items: { type: integer, format: int64 } }
|
||
bboxMax: { type: array, items: { type: number, format: double } }
|
||
bboxMin: { type: array, items: { type: number, format: double } }
|
||
children: { type: array, items: { type: integer, format: int64 } }
|
||
color: { type: integer, nullable: true }
|
||
|
||
SetMetadataTransformRequest:
|
||
type: object
|
||
required: [transform]
|
||
properties:
|
||
transform:
|
||
type: array
|
||
minItems: 16
|
||
maxItems: 16
|
||
items: { type: number, format: double }
|
||
|
||
CompanyStatusModel:
|
||
type: object
|
||
properties:
|
||
id: { type: integer, format: int64 }
|
||
updated_at: { type: string, format: date-time, nullable: true }
|
||
status_model: { $ref: '#/components/schemas/StatusCategory' }
|
||
|
||
CreateBimRequest:
|
||
type: object
|
||
required: [document_id]
|
||
properties:
|
||
document_id: { type: integer, format: int64 }
|
||
|
||
GetFilteredSarexIDsByStatusRequest:
|
||
type: object
|
||
properties:
|
||
sarex_ids:
|
||
type: array
|
||
items: { type: integer, format: int64 }
|
||
status_filters:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/StatusFiltersRequestStruct' }
|
||
|
||
BimIDSarexID:
|
||
type: object
|
||
properties:
|
||
bim_id: { type: integer, format: int64 }
|
||
document_id: { type: integer, format: int64 }
|
||
sarex_id: { type: integer, format: int64 }
|
||
path: { type: string }
|
||
|
||
BIMV3:
|
||
type: object
|
||
properties:
|
||
id: { type: integer, format: int64 }
|
||
created_at: { type: string, format: date-time }
|
||
company_id: { type: integer, format: int64 }
|
||
bundle_id: { type: string, format: uuid }
|
||
document_id: { type: integer, format: int64 }
|
||
bim_type: { type: integer, description: '0 — BIM, 1 — Comparison' }
|
||
transform: { type: array, items: { type: number, format: double } }
|
||
reference_bundle_id: { type: string, format: uuid, nullable: true }
|
||
compared_to_bundle_id: { type: string, format: uuid, nullable: true }
|
||
|
||
BIMV3Element:
|
||
type: object
|
||
description: 'Кастомная сериализация; hierarchy разворачивается в массив uint64'
|
||
properties:
|
||
id: { type: integer, format: int64 }
|
||
bim_id: { type: integer, format: int64 }
|
||
sarex_id: { type: integer, format: int64 }
|
||
name: { type: string }
|
||
hierarchy: { type: array, items: { type: integer, format: int64 } }
|
||
is_leaf: { type: boolean }
|
||
bboxMin: { type: array, items: { type: number, format: double } }
|
||
bboxMax: { type: array, items: { type: number, format: double } }
|
||
attributes:
|
||
type: object
|
||
additionalProperties: true
|
||
|
||
ListBIMElementsRequest:
|
||
type: object
|
||
properties:
|
||
attributes_filters:
|
||
type: array
|
||
items: { $ref: '#/components/schemas/ListBIMElementsAttributesFilter' }
|
||
|
||
ListBIMElementsAttributesFilter:
|
||
type: object
|
||
required: [id, values]
|
||
properties:
|
||
id: { type: integer, format: int64 }
|
||
values:
|
||
type: array
|
||
minItems: 1
|
||
items: {}
|