openapi: 3.0.3 info: title: Documentations API version: "1.0" description: | REST-API сервиса документаций (`documentation-api`, бинарник `cmd/api`, образ `documentations`, deployment `documentations-api` в неймспейсе `documentations`). Спецификация реконструирована из исходного кода маршрутов (`cmd/api/routes_api.go`, `cmd/api/routes_internal.go`) и middleware (`cmd/api/bootstrap.go`, `pkg/midleware/*`). В репозитории **нет сгенерированного swagger/openapi**, поэтому схемы тел запросов/ответов приведены обобщённо (в коде они не описаны декларативно). Пути, методы и параметры пути — достоверные, из роутера `gorilla/mux`. ## Базовые пути - Публичный API: `/api/v1` (описан ниже). - Внутренний API: `/internal/v1` (сервис-к-сервису, облегчённая авторизация; здесь не детализируется — см. `cmd/api/routes_internal.go`). - Потоковая отдача/приём файлов вынесены в **отдельный сервис `filestream`** (`cmd/filestreamer`, образ `documentations-api-files`): `/api/v1/bundles/...`, `/api/v1/documents/...`, `/api/v1/pages/...`, `/api/v1/documents/folders`, `/api/v1/bundles_mrpas/...`, `/api/v1/public_link_mrpas/...`. - Health-check: `GET /ping` (предоставляется каркасом роутера `rest`). - Профилирование: `GET /debug/pprof/...` (net/http/pprof). ## Аутентификация Основной способ — JWT в заголовке `Authorization: Bearer `, проверяемый по RSA-публичному ключу (`PUBLIC_KEY`, PEM/PKIX). Из claims извлекаются `company_ids` и `service_accounts`. Опционально включается проверка через Zitadel (`USE_ZITADEL`), а также разбор заголовка `Identity`. Часть ручек (пути `/public/...`, `/public_link_mrpas/...` и запросы с `download_type=temporary`) авторизуются по HMAC-JWT публичных ссылок (`DOCUMENT_PUBLIC_LINK_JWT_SECRET`). В сервисе filestream ссылки скачивания дополнительно подписываются (`signature` + `expires_at` в query, секрет `SIGNATURE_SECRET_KEY`). ## Формат ошибок Ответы оборачиваются middleware `rest.JSONResponse`; ошибки возвращаются в JSON. Нестандартный код `523` (`StatusOriginIsUnreachable`, `network/consts.go`) используется, когда исходный сервис недоступен. ## Пагинация Единого декларативного механизма пагинации в роутере нет; списки, где она нужна, принимают параметры фильтрации в теле POST-запроса (напр. `/documents/metadata`, `/documents/batch`). Эндпоинт `/documents/metadata` дополнительно ограничивается rate-limit (`METADATA_RATE_LIMIT_*`). servers: - url: https://api.sarex.io/documentations/api/v1 description: production - url: https://api.preprod.sarex.io/documentations/api/v1 description: preprod - url: https://stage-api.sarex.io/documentations/api/v1 description: stage security: - bearerAuth: [] tags: - name: disks - name: documents - name: bundles - name: uploads - name: permissions - name: workspaces - name: dashboards - name: workflows - name: pages - name: marks - name: public-links - name: related-documents - name: changelogs - name: favorite-documents - name: name-templates - name: misc paths: /conversion: post: tags: [misc] summary: Запустить конвертацию документа responses: "200": { $ref: "#/components/responses/Ok" } /disks: get: tags: [disks] summary: Список дисков (доступных пользователю) responses: "200": { $ref: "#/components/responses/Ok" } post: tags: [disks] summary: Создать диск (требуются права администратора) responses: "200": { $ref: "#/components/responses/Ok" } "403": { $ref: "#/components/responses/Forbidden" } /disks/{disk_id}: delete: tags: [disks] summary: Удалить диск (требуются права администратора) parameters: [{ $ref: "#/components/parameters/DiskId" }] responses: "200": { $ref: "#/components/responses/Ok" } "403": { $ref: "#/components/responses/Forbidden" } /disks/{disk_id}/documents: get: tags: [disks, documents] summary: Документы диска parameters: [{ $ref: "#/components/parameters/DiskId" }] responses: "200": { $ref: "#/components/responses/Ok" } post: tags: [disks, documents] summary: Документы диска по списку id parameters: [{ $ref: "#/components/parameters/DiskId" }] responses: "200": { $ref: "#/components/responses/Ok" } /disks/{disk_id}/projects: get: tags: [disks] summary: Проекты диска parameters: [{ $ref: "#/components/parameters/DiskId" }] responses: "200": { $ref: "#/components/responses/Ok" } /disks/{disk_id}/service_accounts: get: tags: [disks, permissions] summary: Сервисные аккаунты диска parameters: [{ $ref: "#/components/parameters/DiskId" }] responses: "200": { $ref: "#/components/responses/Ok" } /disks/{disk_id}/size_migration: get: tags: [misc] summary: Миграция размеров (служебное) parameters: [{ $ref: "#/components/parameters/DiskId" }] responses: "200": { $ref: "#/components/responses/Ok" } /disks/{disk_id}/delete_documents_from_ws_migration: get: tags: [misc] summary: Удаление документов при миграции воркспейса (служебное) parameters: [{ $ref: "#/components/parameters/DiskId" }] responses: "200": { $ref: "#/components/responses/Ok" } /documents: post: tags: [documents] summary: Создать документ/папку responses: "200": { $ref: "#/components/responses/Ok" } delete: tags: [documents] summary: Массовое удаление документов responses: "200": { $ref: "#/components/responses/Ok" } /documents/create_report: post: tags: [documents] summary: Сформировать отчёт по метаданным документов responses: "200": { $ref: "#/components/responses/Ok" } /documents/metadata: post: tags: [documents] summary: Список метаданных документов (rate-limited) responses: "200": { $ref: "#/components/responses/Ok" } "429": { $ref: "#/components/responses/TooManyRequests" } /documents/batch: post: tags: [documents] summary: Пакетное получение документов responses: "200": { $ref: "#/components/responses/Ok" } /documents/flows: post: tags: [documents] summary: Документы в трансмиттале/ревью responses: "200": { $ref: "#/components/responses/Ok" } /documents/public_link: post: tags: [public-links] summary: Создать публичную ссылку на документ responses: "200": { $ref: "#/components/responses/Ok" } /public/documents/public_link/{id}: get: tags: [public-links] summary: Прочитать публичную ссылку (публичный доступ по HMAC-JWT) security: [] parameters: [{ $ref: "#/components/parameters/StrId" }] responses: "200": { $ref: "#/components/responses/Ok" } /documents/public_link/{id}: patch: tags: [public-links] summary: Обновить публичную ссылку parameters: [{ $ref: "#/components/parameters/StrId" }] responses: "200": { $ref: "#/components/responses/Ok" } delete: tags: [public-links] summary: Удалить публичную ссылку parameters: [{ $ref: "#/components/parameters/StrId" }] responses: "200": { $ref: "#/components/responses/Ok" } /documents/{document_id}/update-path: patch: tags: [documents] summary: Сменить родителя документа parameters: [{ $ref: "#/components/parameters/DocumentId" }] responses: "200": { $ref: "#/components/responses/Ok" } /documents/update-path: patch: tags: [documents] summary: Массовая смена родителя документов responses: "200": { $ref: "#/components/responses/Ok" } /documents/super_create: post: tags: [documents] summary: Создание документа суперпользователем (требуются права администратора) responses: "200": { $ref: "#/components/responses/Ok" } "403": { $ref: "#/components/responses/Forbidden" } /documents/types: get: tags: [documents] summary: Справочник типов документов responses: "200": { $ref: "#/components/responses/Ok" } /documents/get_folders_download_url: get: tags: [documents] summary: Ссылка на скачивание папок (подписанная) responses: "200": { $ref: "#/components/responses/Ok" } /download_url/documents: get: tags: [documents] summary: Ссылка на скачивание документа responses: "200": { $ref: "#/components/responses/Ok" } /documents/{document_id}/name_template: get: tags: [documents, name-templates] summary: Шаблон имени документа parameters: [{ $ref: "#/components/parameters/DocumentId" }] responses: "200": { $ref: "#/components/responses/Ok" } /documents/{document_id}: get: tags: [documents] summary: Документ по id parameters: [{ $ref: "#/components/parameters/DocumentId" }] responses: "200": { $ref: "#/components/responses/Ok" } "404": { $ref: "#/components/responses/NotFound" } patch: tags: [documents] summary: Переименовать/изменить документ (числовой id) parameters: [{ $ref: "#/components/parameters/DocumentIdNum" }] responses: "200": { $ref: "#/components/responses/Ok" } delete: tags: [documents] summary: Удалить документ (числовой id) parameters: [{ $ref: "#/components/parameters/DocumentIdNum" }] responses: "200": { $ref: "#/components/responses/Ok" } /documents/{document_id}/bundles: get: tags: [documents, bundles] summary: Бандлы документа parameters: [{ $ref: "#/components/parameters/DocumentId" }] responses: "200": { $ref: "#/components/responses/Ok" } /documents/{document_id}/add_bundle: post: tags: [documents, bundles] summary: Привязать бандл к документу parameters: [{ $ref: "#/components/parameters/DocumentId" }] responses: "200": { $ref: "#/components/responses/Ok" } /documents/{document_id}/move_bundles: patch: tags: [documents, bundles] summary: Переместить бандлы parameters: [{ $ref: "#/components/parameters/DocumentId" }] responses: "200": { $ref: "#/components/responses/Ok" } /documents/{document_id}/ancestors: get: tags: [documents] summary: Предки документа parameters: [{ $ref: "#/components/parameters/DocumentId" }] responses: "200": { $ref: "#/components/responses/Ok" } /documents/filetypes_by_extension: post: tags: [documents] summary: Определить тип файла по расширению responses: "200": { $ref: "#/components/responses/Ok" } /documents/copy: post: tags: [documents] summary: Копировать документы (долгая операция, таймаут 120 мин) responses: "200": { $ref: "#/components/responses/Ok" } /documents/copy_structure: post: tags: [documents] summary: Копировать структуру папок responses: "200": { $ref: "#/components/responses/Ok" } /documents/bin: delete: tags: [documents] summary: Окончательно удалить документы из корзины responses: "200": { $ref: "#/components/responses/Ok" } /documents/bin/restore: patch: tags: [documents] summary: Восстановить документы из корзины responses: "200": { $ref: "#/components/responses/Ok" } /documents/{document_ids}/company: get: tags: [documents] summary: Компания документов parameters: - name: document_ids in: path required: true schema: { type: string } responses: "200": { $ref: "#/components/responses/Ok" } /documents/{document_id}/permissions: get: tags: [permissions] summary: Права доступа документа parameters: [{ $ref: "#/components/parameters/DocumentId" }] responses: "200": { $ref: "#/components/responses/Ok" } post: tags: [permissions] summary: Выдать права на документ parameters: [{ $ref: "#/components/parameters/DocumentId" }] responses: "200": { $ref: "#/components/responses/Ok" } /documents/{document_id}/download: get: tags: [documents] summary: Скачать документ (отдаётся сервисом filestream) parameters: [{ $ref: "#/components/parameters/DocumentId" }] responses: "200": { $ref: "#/components/responses/Ok" } /permissions: get: tags: [permissions] summary: Справочник прав доступа responses: "200": { $ref: "#/components/responses/Ok" } /bundles: post: tags: [bundles] summary: Создать бандл responses: "200": { $ref: "#/components/responses/Ok" } /bundles/{bundle_id}: get: tags: [bundles] summary: Бандл по id parameters: [{ $ref: "#/components/parameters/BundleId" }] responses: "200": { $ref: "#/components/responses/Ok" } patch: tags: [bundles] summary: Изменить бандл parameters: [{ $ref: "#/components/parameters/BundleId" }] responses: "200": { $ref: "#/components/responses/Ok" } delete: tags: [bundles] summary: Удалить бандл parameters: [{ $ref: "#/components/parameters/BundleId" }] responses: "200": { $ref: "#/components/responses/Ok" } /bundles/{bundle_id}/download: get: tags: [bundles] summary: Скачать бандл parameters: [{ $ref: "#/components/parameters/BundleId" }] responses: "200": { $ref: "#/components/responses/Ok" } /bundles/{bundle_id}/{bundle_key}/download: get: tags: [bundles] summary: Скачать файл бандла по ключу parameters: - { $ref: "#/components/parameters/BundleId" } - { $ref: "#/components/parameters/BundleKey" } responses: "200": { $ref: "#/components/responses/Ok" } /bundles/{bundle_id}/{bundle_key}/upload_single: post: tags: [bundles, uploads] summary: Загрузить файл целиком (single upload) parameters: - { $ref: "#/components/parameters/BundleId" } - { $ref: "#/components/parameters/BundleKey" } responses: "200": { $ref: "#/components/responses/Ok" } /bundles/{bundle_id}/{bundle_key}/upload_multipart: post: tags: [bundles, uploads] summary: Начать multipart-загрузку файла бандла parameters: - { $ref: "#/components/parameters/BundleId" } - { $ref: "#/components/parameters/BundleKey" } responses: "200": { $ref: "#/components/responses/Ok" } /bundles/{bundle_id}/upload_finish: post: tags: [bundles, uploads] summary: Завершить загрузку бандла parameters: [{ $ref: "#/components/parameters/BundleId" }] responses: "200": { $ref: "#/components/responses/Ok" } /bundles/{bundle_id}/marks: put: tags: [marks] summary: Добавить штампы/QR/подписи в бандл parameters: [{ $ref: "#/components/parameters/BundleId" }] responses: "200": { $ref: "#/components/responses/Ok" } /bundles/{bundle_id}/sign: post: tags: [bundles, marks] summary: Подписать бандл parameters: [{ $ref: "#/components/parameters/BundleId" }] responses: "200": { $ref: "#/components/responses/Ok" } /bundles/{bundle_id}/restart: post: tags: [bundles, workflows] summary: Перезапустить workflow бандла parameters: [{ $ref: "#/components/parameters/BundleId" }] responses: "200": { $ref: "#/components/responses/Ok" } /bundles/{bundle_id}/cancel_qr: patch: tags: [marks] summary: Отменить QR-код parameters: [{ $ref: "#/components/parameters/BundleId" }] responses: "200": { $ref: "#/components/responses/Ok" } /bundles/{bundle_id}/comment: patch: tags: [bundles] summary: Обновить комментарий бандла parameters: [{ $ref: "#/components/parameters/BundleId" }] responses: "200": { $ref: "#/components/responses/Ok" } /bundles/{bundle_id}/presigned_url: get: tags: [bundles] summary: Presigned URL бандла parameters: [{ $ref: "#/components/parameters/BundleId" }] responses: "200": { $ref: "#/components/responses/Ok" } /bundles/{bundle_id}/mrpas: get: tags: [bundles] summary: MRPA бандла parameters: [{ $ref: "#/components/parameters/BundleId" }] responses: "200": { $ref: "#/components/responses/Ok" } /bundles/{bundle_id}/copy: post: tags: [bundles] summary: Копировать бандл parameters: [{ $ref: "#/components/parameters/BundleId" }] responses: "200": { $ref: "#/components/responses/Ok" } /bundle/version: get: tags: [bundles] summary: Версии бандла responses: "200": { $ref: "#/components/responses/Ok" } /uploads/multipart/{upload_id}/complete: post: tags: [uploads] summary: Завершить multipart-загрузку parameters: [{ $ref: "#/components/parameters/UploadId" }] responses: "200": { $ref: "#/components/responses/Ok" } /uploads/multipart/{upload_id}/abort: post: tags: [uploads] summary: Прервать multipart-загрузку parameters: [{ $ref: "#/components/parameters/UploadId" }] responses: "200": { $ref: "#/components/responses/Ok" } /uploads/multipart/{upload_id}/{part_num}: post: tags: [uploads] summary: Загрузить часть (part) файла parameters: - { $ref: "#/components/parameters/UploadId" } - name: part_num in: path required: true schema: { type: integer } responses: "200": { $ref: "#/components/responses/Ok" } /workspaces: post: tags: [workspaces] summary: Создать воркспейс responses: "200": { $ref: "#/components/responses/Ok" } /workspaces/{ws_id}: get: tags: [workspaces] summary: Документ воркспейса parameters: - name: ws_id in: path required: true schema: { type: string } responses: "200": { $ref: "#/components/responses/Ok" } /dashboards: post: tags: [dashboards] summary: Создать дашборд responses: "200": { $ref: "#/components/responses/Ok" } /dashboards/{db_id}: get: tags: [dashboards] summary: Документ дашборда parameters: - name: db_id in: path required: true schema: { type: string } responses: "200": { $ref: "#/components/responses/Ok" } /workflows/{workflow_id}: get: tags: [workflows] summary: Workflow по id parameters: - name: workflow_id in: path required: true schema: { type: string } responses: "200": { $ref: "#/components/responses/Ok" } /pages: post: tags: [pages] summary: Создать страницу responses: "200": { $ref: "#/components/responses/Ok" } /pages/{data_source}/{page_key}/download: get: tags: [pages] summary: Скачать страницу parameters: - name: data_source in: path required: true schema: { type: string } - name: page_key in: path required: true schema: { type: string } responses: "200": { $ref: "#/components/responses/Ok" } /public/qr/{public_uuid}/document_info: get: tags: [marks] summary: Публичная информация о документе по QR security: [] parameters: - name: public_uuid in: path required: true schema: { type: string, format: uuid } responses: "200": { $ref: "#/components/responses/Ok" } /related_documents: post: tags: [related-documents] summary: Создать связь документов responses: "200": { $ref: "#/components/responses/Ok" } get: tags: [related-documents] summary: Получить связанные документы responses: "200": { $ref: "#/components/responses/Ok" } /related_documents/bulk_delete: post: tags: [related-documents] summary: Массово удалить связи документов responses: "200": { $ref: "#/components/responses/Ok" } /templates/{bundle_id}: get: tags: [misc] summary: Шаблон по бандлу parameters: [{ $ref: "#/components/parameters/BundleId" }] responses: "200": { $ref: "#/components/responses/Ok" } /changelogs/create: post: tags: [changelogs] summary: Создать changelog responses: "200": { $ref: "#/components/responses/Ok" } /changelogs/{changelog_id}: patch: tags: [changelogs] summary: Обновить changelog parameters: - name: changelog_id in: path required: true schema: { type: string } responses: "200": { $ref: "#/components/responses/Ok" } /links: post: tags: [misc] summary: Создать ссылку responses: "200": { $ref: "#/components/responses/Ok" } /favorite_documents: post: tags: [favorite-documents] summary: Добавить документ в избранное responses: "200": { $ref: "#/components/responses/Ok" } get: tags: [favorite-documents] summary: Список избранных документов responses: "200": { $ref: "#/components/responses/Ok" } /favorite_documents/{document_id}: delete: tags: [favorite-documents] summary: Убрать документ из избранного parameters: [{ $ref: "#/components/parameters/DocumentId" }] responses: "200": { $ref: "#/components/responses/Ok" } /name_templates/create: post: tags: [name-templates] summary: Создать шаблон имени responses: "200": { $ref: "#/components/responses/Ok" } /name_templates/{document_id}: get: tags: [name-templates] summary: Шаблон имени по документу parameters: [{ $ref: "#/components/parameters/DocumentId" }] responses: "200": { $ref: "#/components/responses/Ok" } patch: tags: [name-templates] summary: Обновить шаблон имени parameters: [{ $ref: "#/components/parameters/DocumentId" }] responses: "200": { $ref: "#/components/responses/Ok" } delete: tags: [name-templates] summary: Удалить шаблон имени parameters: [{ $ref: "#/components/parameters/DocumentId" }] responses: "200": { $ref: "#/components/responses/Ok" } components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT description: >- JWT, подписанный ключом, соответствующим `PUBLIC_KEY` (RSA/PKIX). Для публичных ссылок используется HMAC-JWT (`DOCUMENT_PUBLIC_LINK_JWT_SECRET`). parameters: DiskId: name: disk_id in: path required: true schema: { type: string } DocumentId: name: document_id in: path required: true schema: { type: string } DocumentIdNum: name: document_id in: path required: true description: Числовой идентификатор документа (маршрут ограничен regex `[0-9]+`) schema: { type: integer } BundleId: name: bundle_id in: path required: true schema: { type: string, format: uuid } BundleKey: name: bundle_key in: path required: true schema: { type: string } UploadId: name: upload_id in: path required: true schema: { type: string } StrId: name: id in: path required: true schema: { type: string } responses: Ok: description: Успешный ответ (тело зависит от ручки; в JSON) content: application/json: schema: { type: object, additionalProperties: true } Forbidden: description: Недостаточно прав content: application/json: schema: { $ref: "#/components/schemas/Error" } NotFound: description: Ресурс не найден content: application/json: schema: { $ref: "#/components/schemas/Error" } TooManyRequests: description: Превышен лимит запросов (rate limit) content: application/json: schema: { $ref: "#/components/schemas/Error" } schemas: Error: type: object properties: error: type: string message: type: string additionalProperties: true