openapi: 3.0.0
info:
  title: Sochi API
  version: 1.0.0
  description: 'API платформы управления событиями Sochi.

    Регистрация по email с токенами активации. Поддержка политики конфиденциальности
    и согласия на обработку персональных данных.

    Email-уведомления на русском языке (язык по заголовку Accept-Language). Аутентификация
    на основе сессий.

    Автоматическая активация аккаунта при заполненных согласиях. Автоматическое создание
    сессии при установке пароля.

    '
  contact:
    name: Sochi Events
  externalDocs:
    url: https://eval.su/docs-api
    description: Интерактивная документация API
servers:
- url: https://eval.su/api/v1
  description: Сервер API
security:
- bearerAuth: []
tags:
- name: health
  description: Проверка работоспособности и готовности API
- name: auth
  description: Регистрация, вход, активация, смена пароля, Telegram
- name: companies
  description: Управление компаниями и сотрудниками
- name: business
  description: Текущий бизнес пользователя
- name: files
  description: Загрузка и управление файлами
- name: holidays
  description: Данные о выходных и праздниках
- name: categories
  description: Категории компаний
- name: public
  description: Публичные данные без авторизации (события, места, компании)
- name: dadata
  description: Подсказки адресов через Dadata
- name: events
  description: События и мастер-классы
- name: event-slots
  description: Временные слоты событий
- name: schedules
  description: Расписания для генерации слотов
- name: calendar
  description: Экспорт в календарь (iCal, Google, Outlook)
- name: orders
  description: Заказы и бронирования
- name: registration
  description: Публичная запись на события
- name: ai-assistant
  description: ИИ-помощник для создания событий
paths:
  /companies:
    post:
      tags:
      - companies
      x-maturity: production
      summary: Создать компанию
      description: 'Создать новую компанию (организатора событий).

        Пользователь станет владельцем.

        '
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCompanyRequest'
            example:
              name: Сочи Мастер-классы
              description: {}
      responses:
        '201':
          description: Компания создана
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Company'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    get:
      tags:
      - companies
      summary: Список компаний
      description: Компании текущего пользователя (где он владелец или сотрудник)
      responses:
        '200':
          description: Список компаний
          content:
            application/json:
              schema:
                type: object
                properties:
                  companies:
                    type: array
                    items:
                      $ref: '#/components/schemas/Company'
              example:
                companies:
                - company_id: 660e8400-e29b-41d4-a716-446655440001
                  name: Моя компания
                  code: my-company
                  logo: null
                  role: owner
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /companies/{id}:
    get:
      tags:
      - companies
      x-maturity: production
      summary: Получить компанию
      description: Получить компанию по ID
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: Данные компании
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Company'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Компания не найдена
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    patch:
      tags:
      - companies
      x-maturity: production
      summary: Обновить компанию
      description: Обновить данные компании
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateCompanyRequest'
      responses:
        '200':
          description: Компания обновлена
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Company'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Компания не найдена
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /companies/{id}/switch:
    post:
      tags:
      - companies
      summary: Переключить компанию
      description: Переключить текущую компанию пользователя
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '204':
          description: Компания переключена
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Компания не найдена
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /companies/{id}/users:
    post:
      tags:
      - companies
      x-maturity: production
      summary: Добавить пользователя
      description: Добавить пользователя в компанию по email. Если пользователя нет,
        создаётся новый с токеном активации и отправляется приглашение.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: ID компании
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddUserRequest'
            example:
              email: user@example.com
      responses:
        '204':
          description: Пользователь добавлен (или отправлено приглашение)
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Компания не найдена
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '500':
          description: Внутренняя ошибка сервера
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    get:
      tags:
      - companies
      x-maturity: production
      summary: Пользователи компании
      description: Список пользователей компании с правами доступа
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: ID компании
      responses:
        '200':
          description: Список пользователей компании
          content:
            application/json:
              schema:
                type: object
                properties:
                  users:
                    type: array
                    items:
                      $ref: '#/components/schemas/CompanyUser'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Компания не найдена
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /companies/{id}/users/{userId}/permissions:
    put:
      tags:
      - companies
      x-maturity: production
      summary: Обновить права пользователя
      description: Обновить права пользователя в компании. Права владельца изменить
        нельзя.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: ID компании
      - name: userId
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: ID пользователя
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUserPermissionsRequest'
      responses:
        '204':
          description: Права обновлены
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '403':
          description: Запрещено — нельзя редактировать права владельца
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Компания или пользователь не найдены
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /companies/{id}/users/{userId}:
    delete:
      tags:
      - companies
      summary: Удалить пользователя
      description: Удалить пользователя из компании. Владельца удалить нельзя.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: ID компании
      - name: userId
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: ID пользователя
      responses:
        '204':
          description: Пользователь удалён
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '403':
          description: Запрещено — нельзя удалить владельца
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Компания или пользователь не найдены
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /companies/{id}/transfer-ownership:
    post:
      tags:
      - companies
      x-maturity: production
      summary: Передать владение компанией
      description: Передать владение компанией. Может только текущий владелец.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: ID компании
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TransferOwnershipRequest'
      responses:
        '204':
          description: Владение передано
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '403':
          description: Запрещено — только владелец может передать владение
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Компания или пользователь не найдены
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /business:
    get:
      tags:
      - companies
      x-maturity: production
      summary: Текущий бизнес
      description: Текущий бизнес пользователя с полными данными
      responses:
        '200':
          description: Текущий бизнес
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Company'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Компания не выбрана
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    patch:
      tags:
      - companies
      x-maturity: production
      summary: Обновить бизнес
      description: Обновить данные текущего бизнеса
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateCompanyRequest'
      responses:
        '200':
          description: Бизнес обновлён
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Company'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Компания не выбрана
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /ai-assistant/parse:
    post:
      tags:
      - ai-assistant
      x-maturity: production
      summary: Разбор текста события
      description: 'Извлечь данные события из произвольного текста с помощью ИИ.

        Принимает описание (анонс, афиша) и возвращает структурированные поля (название,
        дата, цена и т.д.).

        При неполных данных — список вопросов для уточнения.

        '
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - text
              properties:
                text:
                  type: string
                session_id:
                  type: string
      responses:
        '200':
          description: Извлечённые данные события
          content:
            application/json:
              schema:
                type: object
                properties:
                  session_id:
                    type: string
                  is_complete:
                    type: boolean
                  event_data:
                    type: object
                  missing_fields:
                    type: array
                  questions:
                    type: array
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /ai-assistant/create-event:
    post:
      tags:
      - ai-assistant
      x-maturity: production
      summary: Создать событие из сессии ИИ
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - session_id
              properties:
                session_id:
                  type: string
      responses:
        '200':
          description: Событие и слот созданы
          content:
            application/json:
              schema:
                type: object
                properties:
                  event:
                    type: object
                  slot:
                    type: object
                  edit_url:
                    type: string
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /ai-assistant/session/{id}:
    get:
      tags:
      - ai-assistant
      x-maturity: production
      summary: Сессия ИИ-ассистента
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Данные сессии
          content:
            application/json:
              schema:
                type: object
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /company-categories:
    get:
      tags:
      - categories
      x-maturity: production
      summary: Категории компаний
      description: 'Список категорий для компаний (организаторов).

        Используется при создании/редактировании компании и для фильтрации.

        '
      security: []
      responses:
        '200':
          description: Список категорий
          content:
            application/json:
              schema:
                type: object
                required:
                - categories
                properties:
                  categories:
                    type: array
                    items:
                      type: object
                      properties:
                        category_id:
                          type: string
                          format: uuid
                        name:
                          type: string
              example:
                categories:
                - category_id: 990e8400-e29b-41d4-a716-446655440000
                  name: Образование
  /health:
    get:
      tags:
      - health
      x-maturity: production
      summary: Проверка работоспособности
      description: Проверка, что API запущен
      security: []
      responses:
        '200':
          description: API работает
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
  /ready:
    get:
      tags:
      - health
      x-maturity: production
      summary: Проверка готовности
      description: 'Проверка готовности к обработке запросов (БД, Redis).

        Возвращает 503, если зависимости недоступны.

        '
      security: []
      responses:
        '200':
          description: API готов к приёму трафика
        '503':
          description: API не готов (БД или Redis недоступны)
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /companies/{id}/orders:
    get:
      tags:
      - orders
      x-maturity: production
      summary: Заказы компании
      description: Список заказов (бронирований) компании с фильтрами.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: page
        in: query
        schema:
          type: integer
      - name: page_size
        in: query
        schema:
          type: integer
      - name: status
        in: query
        schema:
          type: string
      - name: sort_by
        in: query
        schema:
          type: string
      - name: sort_order
        in: query
        schema:
          type: string
      - name: active
        in: query
        schema:
          type: boolean
      responses:
        '200':
          description: Список заказов
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderListResponse'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '403':
          description: Доступ запрещён
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /companies/{id}/orders/{orderId}:
    get:
      tags:
      - orders
      x-maturity: production
      summary: Получить заказ
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: orderId
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: Данные заказа
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Заказ не найден
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /companies/{id}/orders/{orderId}/status:
    patch:
      tags:
      - orders
      x-maturity: production
      summary: Обновить статус заказа
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: orderId
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
              - status
              properties:
                status:
                  type: string
                  description: Новый статус заказа
            example:
              status: confirmed
      responses:
        '200':
          description: Заказ обновлён
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Заказ не найден
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /holidays/data:
    get:
      tags:
      - holidays
      x-maturity: production
      summary: Данные о праздниках
      description: 'Выходные и праздничные дни за текущий и следующий год.

        Используется для генерации слотов событий (исключение выходных).

        '
      security: []
      responses:
        '200':
          description: Данные о праздниках
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_year:
                    type: object
                    properties:
                      year:
                        type: integer
                        example: 2026
                      data:
                        type: object
                        description: Карта дат и типов (holiday, weekend)
                      loaded_at:
                        type: string
                        format: date-time
                  next_year:
                    type: object
                    properties:
                      year:
                        type: integer
                      data:
                        type: object
                      loaded_at:
                        type: string
  /files/upload:
    post:
      tags:
      - files
      x-maturity: production
      summary: Загрузить файл
      description: 'Загрузка файла через multipart/form-data.

        Поле `file` — бинарные данные. Опционально `entity_type`, `entity_id` для
        привязки к сущности.

        '
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                entity_type:
                  type: string
                entity_id:
                  type: string
                  format: uuid
      responses:
        '200':
          description: Файл загружен
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/File'
        '400':
          description: Неверный файл или превышен лимит хранилища
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /files/upload-from-url:
    post:
      tags:
      - files
      x-maturity: production
      summary: Загрузить файл from URL
      description: Загрузить файл по URL
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - url
              properties:
                url:
                  type: string
                  format: uri
                  example: https://example.com/logo.png
                entity_type:
                  type: string
                entity_id:
                  type: string
                  format: uuid
      responses:
        '200':
          description: Файл загружен
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/File'
        '400':
          description: Неверный URL или файл
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /files/upload-from-clipboard:
    post:
      tags:
      - files
      x-maturity: production
      summary: Загрузить из буфера
      description: Загрузить base64-данные (например, из вставки из буфера обмена)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - data
              - mime_type
              properties:
                data:
                  type: string
                  description: Данные в base64
                mime_type:
                  type: string
                entity_type:
                  type: string
                entity_id:
                  type: string
                  format: uuid
      responses:
        '200':
          description: Файл загружен
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/File'
        '400':
          description: Неверные данные
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /files/{id}:
    get:
      tags:
      - files
      x-maturity: production
      summary: Метаданные файла
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: Метаданные файла
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/File'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Файл не найден
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    delete:
      tags:
      - files
      x-maturity: production
      summary: Удалить файл
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '204':
          description: Файл удалён
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Файл не найден
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /files/{id}/download:
    get:
      tags:
      - files
      x-maturity: production
      summary: Скачать файл
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: Содержимое файла
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Файл не найден
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /files/{id}/description:
    patch:
      tags:
      - files
      x-maturity: production
      summary: Обновить описание файла
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                description:
                  type: string
      responses:
        '204':
          description: Описание обновлено
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Файл не найден
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /files/order:
    patch:
      tags:
      - files
      x-maturity: production
      summary: Обновить порядок файлов
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - file_ids
              properties:
                file_ids:
                  type: array
                  items:
                    type: string
                    format: uuid
      responses:
        '204':
          description: Порядок обновлён
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /files/storage-info:
    get:
      tags:
      - files
      x-maturity: production
      summary: Информация о хранилище
      description: Использование хранилища пользователя
      responses:
        '200':
          description: Информация о хранилище
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StorageInfo'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/login:
    post:
      tags:
      - auth
      x-maturity: production
      summary: Вход пользователя
      description: 'Аутентификация пользователя по email и паролю.


        **Процесс:**

        1. Пользователь ищется по email (без учёта регистра)

        2. Проверяется статус активации аккаунта (должен быть активирован)

        3. Пароль проверяется через bcrypt

        4. Создаётся сессия (срок действия 30 дней)

        5. Возвращается AuthResponse с токеном сессии


        **Требования:**

        - Аккаунт должен быть активирован (is_activated = true)

        - Пароль должен быть верным

        '
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LoginRequest'
            example:
              email: user@example.com
              password: password123
      responses:
        '200':
          description: Успешный вход
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
        '401':
          description: Неверные учётные данные
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '403':
          description: Аккаунт не активирован
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/register:
    post:
      tags:
      - auth
      x-maturity: production
      summary: Регистрация пользователя
      description: 'Регистрация нового пользователя по email. Обязателен только email.
        Пользователь получит письмо активации.


        **Процесс:**

        1. Создаётся пользователь с токеном активации (срок 24 часа)

        2. Если указан пароль, он хешируется и сохраняется

        3. Если указаны согласия, они сохраняются с отметками времени

        4. Отправляется письмо активации (язык по заголовку Accept-Language, по умолчанию
        ru)

        5. Пользователь должен активировать аккаунт по ссылке из письма


        **Согласия:**

        - Если согласия указаны при регистрации, они сохраняются сразу

        - Если не указаны, запрос будет при активации

        '
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegisterRequest'
            example:
              email: user@example.com
              password: password123
              first_name: Иван
              privacy_policy_accepted: true
              personal_data_consent_accepted: true
      responses:
        '201':
          description: Пользователь создан, письмо активации отправлено
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Регистрация успешна. Пожалуйста, проверьте email для
                      активации аккаунта.
        '400':
          description: Ошибка валидации (неверный формат email или короткий пароль)
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '409':
          description: Пользователь уже существует
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/activation-info:
    get:
      tags:
      - auth
      summary: Информация об активации
      description: 'Получить информацию о пользователе и статус согласий по токену
        активации.

        Используется для проверки заполненных согласий перед показом чекбоксов на
        странице активации.

        '
      security: []
      parameters:
      - name: token
        in: query
        required: true
        schema:
          type: string
        description: Токен активации из письма
      responses:
        '200':
          description: Информация об активации
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActivationInfoResponse'
        '400':
          description: Неверный или истёкший токен
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/activate:
    post:
      tags:
      - auth
      x-maturity: production
      summary: Активация аккаунта
      description: 'Активация аккаунта по токену из письма.


        **Процесс:**

        1. Токен проверяется (существует и не истёк)

        2. Аккаунт активируется (is_activated = true, токен очищается)

        3. Если согласия указаны и ещё не сохранены — сохраняются

        4. Если указан пароль — хешируется и сохраняется

        5. **Сессия всегда создаётся** после успешной активации — пользователь автоматически
        авторизуется

        6. Возвращается AuthResponse с токеном сессии — редирект в профиль


        **Согласия:**

        - Сохраняются только если ещё не заполнены

        - Если уже заполнены — переданные значения игнорируются


        **Пароль:**

        - Если указан в запросе — хешируется и сохраняется

        - Можно установить позже в профиле

        '
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ActivateRequest'
            example:
              token: abc123def456...
              password: mypassword123
              privacy_policy_accepted: true
              personal_data_consent_accepted: true
      responses:
        '200':
          description: 'Аккаунт активирован. Сессия создана, пользователь авторизован.

            Возвращается AuthResponse с токеном — редирект в профиль.

            '
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
        '400':
          description: Неверный или истёкший токен
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '401':
          description: Не авторизован — нельзя активировать чужой аккаунт
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации (короткий пароль и т.д.)
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/logout:
    post:
      tags:
      - auth
      x-maturity: production
      summary: Выход
      description: Выход и деактивация текущей сессии
      responses:
        '204':
          description: Успешный выход
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/me:
    get:
      tags:
      - auth
      x-maturity: production
      summary: Текущий пользователь
      description: Информация о текущем аутентифицированном пользователе
      responses:
        '200':
          description: Информация о текущем пользователе
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
              example:
                user_id: 550e8400-e29b-41d4-a716-446655440000
                email: user@example.com
                first_name: Иван
                phone: null
                avatar: null
                current_company_id: 660e8400-e29b-41d4-a716-446655440001
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/sessions:
    get:
      tags:
      - auth
      summary: Сессии пользователя
      description: Получить все активные сессии текущего пользователя
      responses:
        '200':
          description: Список активных сессий
          content:
            application/json:
              schema:
                type: object
                properties:
                  sessions:
                    type: array
                    items:
                      $ref: '#/components/schemas/Session'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/sessions/{id}:
    delete:
      tags:
      - auth
      x-maturity: production
      summary: Завершить сессию
      description: Завершить конкретную сессию. Пользователь может завершать только
        свои сессии.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: Session ID
      responses:
        '204':
          description: Сессия завершена
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '403':
          description: Запрещено — нельзя завершить чужую сессию
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Сессия не найдена
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/password-reset/validate:
    get:
      tags:
      - auth
      x-maturity: production
      summary: Validate password reset token and auto-authorize
      description: 'Проверка токена сброса пароля из ссылки. При валидном токене пользователь
        автоматически авторизуется (создаётся сессия) и может сменить пароль через
        `/auth/change-password`.


        **Процесс:**

        1. Токен проверяется (существует и не истёк)

        2. Аккаунт активируется, если ещё не активирован

        3. **Создаётся сессия** — пользователь авторизован

        4. Возвращается AuthResponse с токеном — можно сменить пароль


        **Использование:**

        - Пользователь переходит по ссылке из письма

        - Фронтенд вызывает эндпоинт с токеном

        - Пользователь автоматически входит

        '
      security: []
      parameters:
      - name: token
        in: query
        required: true
        schema:
          type: string
        description: Токен сброса пароля из письма
      responses:
        '200':
          description: 'Токен действителен. Сессия создана, пользователь авторизован.

            Возвращается AuthResponse с токеном — можно сменить пароль.

            '
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
        '400':
          description: Неверный или истёкший токен
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/password-reset/request:
    post:
      tags:
      - auth
      x-maturity: production
      summary: Запросить сброс пароля
      description: Отправить письмо сброса пароля
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RequestPasswordResetRequest'
      responses:
        '200':
          description: Письмо отправлено (или пользователь не найден)
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/password-reset/confirm:
    post:
      tags:
      - auth
      x-maturity: production
      summary: Подтвердить сброс пароля
      description: Установить новый пароль по токену из письма. Создаётся сессия.
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ResetPasswordRequest'
      responses:
        '200':
          description: Пароль сброшен, сессия создана
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
        '400':
          description: Неверный или истёкший токен
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/telegram:
    post:
      tags:
      - auth
      x-maturity: production
      summary: Авторизация Telegram WebApp
      description: Авторизация через Telegram Mini App (init_data из бота)
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TelegramAuthRequest'
      responses:
        '200':
          description: Авторизован
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TelegramAuthResponse'
        '401':
          description: Неверные данные Telegram
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/telegram-widget:
    post:
      tags:
      - auth
      x-maturity: production
      summary: Авторизация виджета Telegram
      description: Авторизация через виджет Telegram (auth_data из callback)
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TelegramWidgetAuthRequest'
      responses:
        '200':
          description: Авторизован
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TelegramAuthResponse'
        '401':
          description: Неверные данные Telegram
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/profile:
    patch:
      tags:
      - auth
      x-maturity: production
      summary: Обновить профиль
      description: Обновить профиль текущего пользователя
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateProfileRequest'
      responses:
        '204':
          description: Профиль обновлён
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Пользователь не найден
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/change-email/request:
    post:
      tags:
      - auth
      x-maturity: production
      summary: Запросить смену email
      description: Запросить смену email, код подтверждения отправится на новый email
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RequestEmailChangeRequest'
      responses:
        '204':
          description: Письмо подтверждения отправлено
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '409':
          description: Email уже используется
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/change-email/confirm:
    post:
      tags:
      - auth
      x-maturity: production
      summary: Подтвердить смену email по коду
      description: Подтвердить смену email кодом из письма
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConfirmEmailChangeByCodeRequest'
      responses:
        '204':
          description: Email изменён
        '401':
          description: Неверный или истёкший код
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/change-email/verify:
    post:
      tags:
      - auth
      x-maturity: production
      summary: Подтвердить смену email по токену
      description: Подтвердить смену email по токену из ссылки
      security: []
      parameters:
      - name: token
        in: query
        required: true
        schema:
          type: string
        description: Токен из ссылки в письме
      requestBody:
        content:
          application/json:
            schema:
              type: object
      responses:
        '204':
          description: Email изменён
        '401':
          description: Неверный или истёкший токен
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/link-telegram:
    post:
      tags:
      - auth
      x-maturity: production
      summary: Привязать Telegram
      description: Привязать Telegram к текущему пользователю
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LinkTelegramRequest'
      responses:
        '200':
          description: Telegram привязан
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '409':
          description: Telegram уже привязан к другому пользователю
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/link-telegram-widget:
    post:
      tags:
      - auth
      x-maturity: production
      summary: Привязать Telegram через виджет
      description: Привязать Telegram через виджет auth_data
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LinkTelegramWidgetRequest'
      responses:
        '200':
          description: Telegram привязан
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '409':
          description: Telegram уже привязан к другому пользователю
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /auth/change-password:
    post:
      tags:
      - auth
      summary: Сменить пароль
      description: Сменить пароль. Пользователь может менять только свой пароль.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChangePasswordRequest'
      responses:
        '204':
          description: Пароль успешно изменён
        '401':
          description: Требуется аутентификация or invalid old password
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '422':
          description: Ошибка валидации
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /public/events:
    get:
      tags:
      - public
      x-maturity: production
      summary: Список публичных событий
      description: 'Список опубликованных событий с пагинацией и фильтрами.

        Поддерживает фильтрацию по категории, месту, поиску по названию/описанию.

        '
      security: []
      parameters:
      - name: published
        in: query
        schema:
          type: boolean
          default: true
        description: Только опубликованные (по умолчанию true)
      - name: category_id
        in: query
        schema:
          type: string
          format: uuid
        description: Фильтр по категории события
      - name: place_id
        in: query
        schema:
          type: string
          format: uuid
        description: Фильтр по месту проведения
      - name: search
        in: query
        schema:
          type: string
        description: Поиск по названию и описанию
      - name: page
        in: query
        schema:
          type: integer
          default: 1
      - name: page_size
        in: query
        schema:
          type: integer
          default: 20
      responses:
        '200':
          description: Список событий
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventListResponse'
              example:
                events:
                - event_id: 770e8400-e29b-41d4-a716-446655440002
                  published: true
                  nearest_time: '2026-02-15T10:00:00Z'
                total_count: 42
  /public/events/{id}:
    get:
      tags:
      - public
      x-maturity: production
      summary: Публичное событие по ID
      description: 'Получить полные данные опубликованного события.

        Включает описание, места, слоты, категорию, превью.

        '
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: ID события
        example: 770e8400-e29b-41d4-a716-446655440002
      security: []
      responses:
        '200':
          description: Данные события
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Event'
        '404':
          description: Событие не найдено или не опубликовано
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /public/events/{id}/slots:
    get:
      tags:
      - public
      x-maturity: production
      summary: Публичные слоты события
      description: 'Список временных слотов опубликованного события.

        Используется для выбора даты/времени записи на событие.

        '
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: ID события
        example: 770e8400-e29b-41d4-a716-446655440002
      security: []
      responses:
        '200':
          description: Список слотов (время, вместимость, занято)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventSlotListResponse'
              example:
                slots:
                - event_slot_id: 880e8400-e29b-41d4-a716-446655440003
                  starts_at: '2026-02-15T10:00:00Z'
                  ends_at: '2026-02-15T12:00:00Z'
                  capacity: 10
                  participant_count: 3
                total_count: 5
        '404':
          description: Событие не найдено
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /dadata/suggest/address:
    post:
      tags:
      - dadata
      x-maturity: production
      summary: Подсказки адресов
      description: 'Подсказки адресов через Dadata API.

        Используется для автодополнения при вводе адреса (создание события, места).

        Можно ограничить область поиска параметром `locations`.

        '
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - query
              properties:
                query:
                  type: string
                  description: Строка поиска (начало адреса)
                  example: Сочи, Курорт
                count:
                  type: integer
                  description: Максимум подсказок (по умолчанию ~10)
                locations:
                  type: array
                  description: Ограничение области поиска
      responses:
        '200':
          description: Массив подсказок адресов
          content:
            application/json:
              schema:
                type: array
  /public/files/{id}/download:
    get:
      tags:
      - public
      x-maturity: production
      summary: Скачать публичный файл
      description: 'Скачать файл без авторизации.

        Используется для публичных файлов: логотипы компаний, превью событий, изображения
        в афишах.

        '
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: ID файла (file_id)
        example: 550e8400-e29b-41d4-a716-446655440000
      security: []
      responses:
        '200':
          description: Содержимое файла (бинарные данные)
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
          headers:
            Content-Disposition:
              description: Имя файла при сохранении
              schema:
                type: string
        '404':
          description: Файл не найден или не публичный
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
              example:
                type: about:blank
                title: Not Found
                status: 404
                detail: Файл не найден
  /events:
    post:
      tags:
      - events
      x-maturity: production
      summary: Создать событие
      description: Создать новое событие (мастер-класс, тренинг) в текущей компании.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateEventRequest'
      responses:
        '201':
          description: Событие создано
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Event'
        '400':
          description: Неверный запрос
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    get:
      tags:
      - events
      x-maturity: production
      summary: Список событий
      description: События текущей компании с фильтрами и пагинацией.
      parameters:
      - name: page
        in: query
        schema:
          type: integer
      - name: page_size
        in: query
        schema:
          type: integer
      - name: published
        in: query
        schema:
          type: boolean
      - name: category_id
        in: query
        schema:
          type: string
          format: uuid
      - name: search
        in: query
        schema:
          type: string
      - name: sort_by
        in: query
        schema:
          type: string
      - name: sort_order
        in: query
        schema:
          type: string
      responses:
        '200':
          description: Список событий
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventListResponse'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}:
    get:
      tags:
      - events
      x-maturity: production
      summary: Получить событие
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: Данные события
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Event'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '403':
          description: Доступ запрещён
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Событие не найдено
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    patch:
      tags:
      - events
      x-maturity: production
      summary: Обновить событие
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateEventRequest'
      responses:
        '200':
          description: Событие обновлено
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Event'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Событие не найдено
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    delete:
      tags:
      - events
      x-maturity: production
      summary: Удалить событие
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '204':
          description: Событие удалено
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Событие не найдено
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}/slots:
    post:
      tags:
      - event-slots
      x-maturity: production
      summary: Создать событие slot
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateEventSlotRequest'
      responses:
        '201':
          description: Слот создан
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventSlot'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    get:
      tags:
      - event-slots
      x-maturity: production
      summary: Список слотов
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: date_from
        in: query
        schema:
          type: string
          format: date
      - name: date_to
        in: query
        schema:
          type: string
          format: date
      - name: has_space
        in: query
        schema:
          type: boolean
      responses:
        '200':
          description: Список слотов
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventSlotListResponse'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}/slots/batch:
    post:
      tags:
      - event-slots
      x-maturity: production
      summary: Создать событие slots batch
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateEventSlotsBatchRequest'
      responses:
        '201':
          description: Слоты созданы
          content:
            application/json:
              schema:
                type: object
                properties:
                  slots:
                    type: array
                  count:
                    type: integer
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}/slots/quick:
    post:
      tags:
      - event-slots
      x-maturity: production
      summary: Создать событие slot (quick)
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                date:
                  type: string
                  format: date
                start_time:
                  type: string
                end_time:
                  type: string
                capacity:
                  type: integer
      responses:
        '201':
          description: Слот создан
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventSlot'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}/slots/upcoming:
    get:
      tags:
      - event-slots
      x-maturity: production
      summary: Ближайшие слоты
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: limit
        in: query
        schema:
          type: integer
      responses:
        '200':
          description: Ближайшие слоты
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventSlotListResponse'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}/slots/{slotId}:
    get:
      tags:
      - event-slots
      x-maturity: production
      summary: Получить слот
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: slotId
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: Данные слота
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventSlot'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    patch:
      tags:
      - event-slots
      x-maturity: production
      summary: Обновить слот
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: slotId
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateEventSlotRequest'
      responses:
        '200':
          description: Слот обновлён
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventSlot'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    delete:
      tags:
      - event-slots
      x-maturity: production
      summary: Удалить слот
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: slotId
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '204':
          description: Слот удалён
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}/schedules:
    post:
      tags:
      - schedules
      x-maturity: production
      summary: Создать расписание
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateScheduleRequest'
      responses:
        '201':
          description: Расписание создано
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Schedule'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    get:
      tags:
      - schedules
      x-maturity: production
      summary: Список расписаний
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: Список расписаний
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ScheduleListResponse'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}/schedules/{scheduleId}:
    get:
      tags:
      - schedules
      x-maturity: production
      summary: Получить расписание
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: scheduleId
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: Данные расписания
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Schedule'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    patch:
      tags:
      - schedules
      x-maturity: production
      summary: Обновить расписание
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: scheduleId
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateScheduleRequest'
      responses:
        '200':
          description: Расписание обновлено
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Schedule'
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
    delete:
      tags:
      - schedules
      x-maturity: production
      summary: Удалить расписание
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: scheduleId
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '204':
          description: Расписание удалено
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}/schedules/{scheduleId}/generate:
    post:
      tags:
      - schedules
      x-maturity: production
      summary: Сгенерировать слоты из расписания
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: scheduleId
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                date_from:
                  type: string
                  format: date
                date_to:
                  type: string
                  format: date
      responses:
        '200':
          description: Слоты сгенерированы
          content:
            application/json:
              schema:
                type: object
                properties:
                  slots:
                    type: array
                  count:
                    type: integer
        '401':
          description: Требуется аутентификация
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}/export/ical:
    get:
      tags:
      - calendar
      x-maturity: production
      summary: Экспорт события в iCal
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      security: []
      responses:
        '200':
          description: Файл iCal
          content:
            text/calendar:
              schema:
                type: string
        '404':
          description: Событие не найдено
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}/export/links:
    get:
      tags:
      - calendar
      x-maturity: production
      summary: Ссылки экспорта события
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      security: []
      responses:
        '200':
          description: Ссылки экспорта (Google, Outlook, iCal)
          content:
            application/json:
              schema:
                type: object
        '404':
          description: Событие не найдено
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}/slots/{slotId}/export/ical:
    get:
      tags:
      - calendar
      x-maturity: production
      summary: Экспорт слота в iCal
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: slotId
        in: path
        required: true
        schema:
          type: string
          format: uuid
      security: []
      responses:
        '200':
          description: Файл iCal
          content:
            text/calendar:
              schema:
                type: string
        '404':
          description: Слот не найден
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}/slots/{slotId}/export/google:
    get:
      tags:
      - calendar
      x-maturity: production
      summary: URL Google Calendar
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: slotId
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: redirect
        in: query
        schema:
          type: boolean
      security: []
      responses:
        '200':
          description: URL добавления в Google Calendar
          content:
            application/json:
              schema:
                type: object
                properties:
                  url:
                    type: string
        '404':
          description: Слот не найден
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}/slots/{slotId}/export/outlook:
    get:
      tags:
      - calendar
      x-maturity: production
      summary: URL Outlook
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: slotId
        in: path
        required: true
        schema:
          type: string
          format: uuid
      security: []
      responses:
        '200':
          description: URL добавления в Outlook
          content:
            application/json:
              schema:
                type: object
                properties:
                  url:
                    type: string
        '404':
          description: Слот не найден
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}/slots/{slotId}/export/links:
    get:
      tags:
      - calendar
      x-maturity: production
      summary: Все ссылки экспорта слота
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: slotId
        in: path
        required: true
        schema:
          type: string
          format: uuid
      security: []
      responses:
        '200':
          description: Все ссылки календаря
          content:
            application/json:
              schema:
                type: object
        '404':
          description: Слот не найден
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /companies/{id}/events/export/ical:
    get:
      tags:
      - calendar
      x-maturity: production
      summary: Экспорт событий компании в iCal
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      security: []
      responses:
        '200':
          description: Файл iCal со всеми событиями компании
          content:
            text/calendar:
              schema:
                type: string
        '404':
          description: Компания не найдена
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /public/places:
    get:
      tags:
      - public
      x-maturity: production
      summary: Список мест
      description: 'Список всех мест с количеством опубликованных событий (event_count).

        Места — точки проведения событий (адреса из Nominatim/OpenStreetMap).

        Используется для фильтрации событий по месту, отображения на карте, выпадающего
        списка.

        '
      security: []
      responses:
        '200':
          description: Список мест с количеством событий
          content:
            application/json:
              schema:
                type: object
                required:
                - places
                properties:
                  places:
                    type: array
                    items:
                      $ref: '#/components/schemas/Place'
              example:
                places:
                - place_id: 550e8400-e29b-41d4-a716-446655440000
                  osm_type: relation
                  osm_id: 12345
                  display_name: Сочи, Краснодарский край, Россия
                  lat: 43.5854723
                  lon: 39.7230629
                  event_count: 5
                - place_id: 660e8400-e29b-41d4-a716-446655440001
                  osm_type: way
                  osm_id: 67890
                  display_name: Красная Поляна, Адлерский район, Сочи
                  lat: 43.6803
                  lon: 40.2777
                  event_count: 3
  /public/places/{id}:
    get:
      tags:
      - public
      x-maturity: production
      summary: Место с событиями
      description: 'Получить место по ID и список опубликованных событий в этом месте.

        Используется для страницы места с календарём предстоящих событий.

        '
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: ID места (place_id)
        example: 550e8400-e29b-41d4-a716-446655440000
      security: []
      responses:
        '200':
          description: Место и его события
          content:
            application/json:
              schema:
                type: object
                required:
                - place
                - events
                properties:
                  place:
                    $ref: '#/components/schemas/Place'
                  events:
                    type: array
                    items:
                      $ref: '#/components/schemas/Event'
              example:
                place:
                  place_id: 550e8400-e29b-41d4-a716-446655440000
                  display_name: Сочи, Краснодарский край, Россия
                  lat: 43.5854723
                  lon: 39.7230629
                events:
                - event_id: 770e8400-e29b-41d4-a716-446655440002
                  published: true
        '404':
          description: Место не найдено
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /public/companies:
    get:
      tags:
      - public
      x-maturity: production
      summary: Список публичных компаний
      description: 'Список опубликованных компаний с пагинацией и фильтрами.

        Используется для каталога организаторов на публичной странице.

        '
      security: []
      parameters:
      - name: search
        in: query
        schema:
          type: string
        description: Поиск по названию компании
        example: мастер-класс
      - name: category_id
        in: query
        schema:
          type: string
          format: uuid
        description: Фильтр по категории компании
      - name: page
        in: query
        schema:
          type: integer
          default: 1
        description: Номер страницы
      - name: limit
        in: query
        schema:
          type: integer
          default: 20
        description: Размер страницы
      responses:
        '200':
          description: Список компаний
          content:
            application/json:
              schema:
                type: object
                properties:
                  companies:
                    type: array
                    items:
                      $ref: '#/components/schemas/PublicCompany'
                  total:
                    type: integer
                  page:
                    type: integer
                  limit:
                    type: integer
              example:
                companies:
                - company_id: 660e8400-e29b-41d4-a716-446655440001
                  code: sochi-events
                  name: Сочи Ивентс
                total: 15
                page: 1
                limit: 20
  /public/companies/{code}:
    get:
      tags:
      - public
      x-maturity: production
      summary: Публичная компания по коду
      description: 'Получить данные опубликованной компании по её коду (slug).

        Код задаётся в настройках компании и используется в URL публичной страницы.

        '
      parameters:
      - name: code
        in: path
        required: true
        schema:
          type: string
        description: Код компании (slug)
        example: sochi-events
      security: []
      responses:
        '200':
          description: Данные компании
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicCompany'
              example:
                company_id: 660e8400-e29b-41d4-a716-446655440001
                code: sochi-events
                name: Сочи Ивентс
                description: {}
                logo: null
                categories: []
        '404':
          description: Компания не найдена или не опубликована
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
  /events/{id}/slots/{slotId}/register:
    post:
      tags:
      - registration
      x-maturity: production
      summary: Записаться на событие
      description: 'Публичная запись на слот события без авторизации.

        Клиент указывает email (обязательно), имя и телефон.

        Создаётся заказ; при наличии свободных мест — бронирование.

        '
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      - name: slotId
        in: path
        required: true
        schema:
          type: string
          format: uuid
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - email
              properties:
                email:
                  type: string
                  format: email
                  description: Email для подтверждения записи
                  example: client@example.com
                first_name:
                  type: string
                  description: Имя участника
                  example: Анна
                phone:
                  type: string
                  description: Телефон (опционально)
            example:
              email: client@example.com
              first_name: Анна
              phone: +7 999 123-45-67
      responses:
        '201':
          description: Регистрация успешна
          content:
            application/json:
              schema:
                type: object
                properties:
                  order_id:
                    type: string
                  message:
                    type: string
        '400':
          description: Слот заполнен или неверный
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '404':
          description: Слот не найден
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Аутентификация Bearer токеном. Токен получается при входе/регистрации.
  schemas:
    LoginRequest:
      type: object
      required:
      - email
      - password
      properties:
        email:
          type: string
          format: email
          example: user@example.com
        password:
          type: string
          format: password
          example: password123
    RegisterRequest:
      type: object
      required:
      - email
      properties:
        email:
          type: string
          format: email
          description: Email пользователя (обязательно)
          example: user@example.com
        password:
          type: string
          format: password
          description: Пароль (опционально). Минимум 8 символов.
          example: password123
          minLength: 8
        first_name:
          type: string
          description: Имя пользователя (опционально)
          example: Иван
        privacy_policy_accepted:
          type: boolean
          description: Принятие политики конфиденциальности. При активации будет запрошено,
            если не указано.
          example: true
        personal_data_consent_accepted:
          type: boolean
          description: Согласие на обработку персональных данных. При активации будет
            запрошено, если не указано.
          example: true
    ActivateRequest:
      type: object
      required:
      - token
      properties:
        token:
          type: string
          description: Токен активации из письма
          example: abc123def456...
        password:
          type: string
          format: password
          description: 'Пароль для аккаунта (опционально).

            - Если пароль уже есть — будет обновлён

            - При указании сессия создаётся автоматически

            - Минимум 8 символов

            '
          example: password123
          minLength: 8
        privacy_policy_accepted:
          type: boolean
          description: 'Принятие политики конфиденциальности (опционально).

            - Сохраняется только если ещё не заполнено

            - Если уже заполнено — значение игнорируется

            '
          example: true
        personal_data_consent_accepted:
          type: boolean
          description: 'Согласие на обработку данных (опционально).

            - Сохраняется только если ещё не заполнено

            - Если уже заполнено — значение игнорируется

            '
          example: true
    ActivationInfoResponse:
      type: object
      properties:
        user:
          type: object
          properties:
            user_id:
              type: string
              format: uuid
            email:
              type: string
              format: email
            first_name:
              type: string
              nullable: true
        privacy_policy_accepted_at:
          type: string
          format: date-time
          nullable: true
          description: Время принятия политики конфиденциальности. NULL если не принято.
        personal_data_consent_accepted_at:
          type: string
          format: date-time
          nullable: true
          description: Время согласия на обработку данных. NULL если не дано.
        is_activated:
          type: boolean
          description: Уже активирован ли аккаунт
    AuthResponse:
      type: object
      properties:
        token:
          type: string
          description: Токен сессии (Bearer)
          example: abc123def456...
        user:
          $ref: '#/components/schemas/User'
        expires_at:
          type: string
          format: date-time
          example: 2025-01-01 00:00:00+00:00
    User:
      type: object
      properties:
        user_id:
          type: string
          format: uuid
        email:
          type: string
          format: email
        first_name:
          type: string
        phone:
          type: string
          nullable: true
        avatar:
          type: string
          nullable: true
        current_company_id:
          type: string
          format: uuid
          nullable: true
    Session:
      type: object
      properties:
        session_id:
          type: string
          format: uuid
        created_at:
          type: string
          format: date-time
        expires_at:
          type: string
          format: date-time
        user_agent:
          type: string
          nullable: true
        ip_address:
          type: string
          nullable: true
        is_active:
          type: boolean
        source:
          type: string
          nullable: true
    CreateCompanyRequest:
      type: object
      required:
      - name
      properties:
        name:
          type: string
          example: My Company
        description:
          type: object
          additionalProperties: true
    AddUserRequest:
      type: object
      required:
      - email
      properties:
        email:
          type: string
          format: email
          example: user@example.com
    UpdateUserPermissionsRequest:
      type: object
      properties:
        allow_events_edit:
          type: boolean
          description: Право редактировать события
        allow_products_edit:
          type: boolean
          description: Право редактировать товары
        allow_company_edit:
          type: boolean
          description: Право редактировать данные компании
        allow_applications_edit:
          type: boolean
          description: Право редактировать заявки клиентов
        allow_add_employees:
          type: boolean
          description: Право добавлять сотрудников
    TransferOwnershipRequest:
      type: object
      required:
      - new_owner_id
      properties:
        new_owner_id:
          type: string
          format: uuid
          description: ID нового владельца
    CompanyUser:
      type: object
      properties:
        user_id:
          type: string
          format: uuid
        company_id:
          type: string
          format: uuid
        invited_by:
          type: string
          format: uuid
          nullable: true
        invited_time:
          type: string
          format: date-time
          nullable: true
        allow_events_edit:
          type: boolean
        allow_products_edit:
          type: boolean
        allow_company_edit:
          type: boolean
        allow_applications_edit:
          type: boolean
        allow_add_employees:
          type: boolean
        comment:
          type: string
          nullable: true
        is_owner:
          type: boolean
          description: Является ли пользователь владельцем компании
    Company:
      type: object
      properties:
        company_id:
          type: string
          format: uuid
        owner_user_id:
          type: string
          format: uuid
        name:
          type: string
        description:
          type: object
          additionalProperties: true
        status:
          type: string
        published:
          type: boolean
        created_at:
          type: string
          format: date-time
    UpdateCompanyRequest:
      type: object
      properties:
        name:
          type: string
        description:
          type: object
          additionalProperties: true
        code:
          type: string
        published:
          type: boolean
        gallery:
          type: array
          items: {}
    File:
      type: object
      properties:
        file_id:
          type: string
          format: uuid
        original_name:
          type: string
        stored_name:
          type: string
        file_path:
          type: string
        mime_type:
          type: string
        file_size:
          type: integer
        entity_type:
          type: string
          nullable: true
        entity_id:
          type: string
          format: uuid
          nullable: true
        description:
          type: string
          nullable: true
        sort_order:
          type: integer
          nullable: true
        created_at:
          type: string
          format: date-time
    StorageInfo:
      type: object
      properties:
        used:
          type: integer
        limit:
          type: integer
        free:
          type: integer
    RequestPasswordResetRequest:
      type: object
      required:
      - email
      properties:
        email:
          type: string
          format: email
          example: user@example.com
    ResetPasswordRequest:
      type: object
      required:
      - token
      - password
      properties:
        token:
          type: string
          description: Токен из письма сброса пароля
        password:
          type: string
          format: password
          minLength: 8
          example: newpassword123
    TelegramAuthRequest:
      type: object
      required:
      - init_data
      properties:
        init_data:
          type: string
          description: initData из Telegram WebApp
    TelegramWidgetAuthRequest:
      type: object
      required:
      - auth_data
      properties:
        auth_data:
          type: object
          additionalProperties: true
          description: auth_data из callback виджета Telegram
    TelegramAuthResponse:
      type: object
      properties:
        token:
          type: string
        user:
          $ref: '#/components/schemas/User'
        expires_at:
          type: string
          format: date-time
        is_new_user:
          type: boolean
    UpdateProfileRequest:
      type: object
      properties:
        first_name:
          type: string
          nullable: true
        phone:
          type: string
          nullable: true
        avatar:
          type: string
          nullable: true
    RequestEmailChangeRequest:
      type: object
      required:
      - email
      properties:
        email:
          type: string
          format: email
    ConfirmEmailChangeByCodeRequest:
      type: object
      required:
      - code
      properties:
        code:
          type: string
    LinkTelegramRequest:
      type: object
      required:
      - init_data
      properties:
        init_data:
          type: string
    LinkTelegramWidgetRequest:
      type: object
      required:
      - auth_data
      properties:
        auth_data:
          type: object
          additionalProperties: true
    ChangePasswordRequest:
      type: object
      required:
      - old_password
      - new_password
      properties:
        old_password:
          type: string
          format: password
          description: Текущий пароль
          example: oldpassword123
        new_password:
          type: string
          format: password
          description: Новый пароль (минимум 8 символов)
          example: newpassword123
          minLength: 8
    Event:
      type: object
      properties:
        event_id:
          type: string
          format: uuid
        company_id:
          type: string
          format: uuid
        category_id:
          type: string
          format: uuid
          nullable: true
          description: ID категории события
        category:
          $ref: '#/components/schemas/EventCategory'
        description:
          type: object
        published:
          type: boolean
        preview_image_id:
          type: string
          format: uuid
          nullable: true
        nearest_time:
          type: string
          format: date-time
          nullable: true
          description: Ближайшее время проведения (прошедшие события имеют nearest_time
            < now)
        slots:
          type: array
          items:
            $ref: '#/components/schemas/EventSlot'
        places:
          type: array
          items:
            $ref: '#/components/schemas/Place'
          description: Места проведения (при публичном списке/детали)
        created_at:
          type: string
          format: date-time
    EventCategory:
      type: object
      description: Категория события (мастер-класс, тренинг и т.д.)
      properties:
        category_id:
          type: string
          format: uuid
        name:
          type: string
          description: Название категории
    CreateEventRequest:
      type: object
      properties:
        currency_id:
          type: string
          format: uuid
        description:
          type: object
        is_online:
          type: boolean
        published:
          type: boolean
        price:
          type: number
        category_id:
          type: string
          format: uuid
    UpdateEventRequest:
      type: object
      properties:
        description:
          type: object
        published:
          type: boolean
        price:
          type: number
    EventListResponse:
      type: object
      properties:
        events:
          type: array
          items:
            $ref: '#/components/schemas/Event'
        total_count:
          type: integer
    EventSlot:
      type: object
      properties:
        event_slot_id:
          type: string
          format: uuid
        event_id:
          type: string
          format: uuid
        starts_at:
          type: string
          format: date-time
        ends_at:
          type: string
          format: date-time
        capacity:
          type: integer
        participant_count:
          type: integer
    CreateEventSlotRequest:
      type: object
      required:
      - starts_at
      - ends_at
      - capacity
      properties:
        starts_at:
          type: string
          format: date-time
        ends_at:
          type: string
          format: date-time
        capacity:
          type: integer
    CreateEventSlotsBatchRequest:
      type: object
      required:
      - slots
      properties:
        slots:
          type: array
          items:
            $ref: '#/components/schemas/CreateEventSlotRequest'
    UpdateEventSlotRequest:
      type: object
      properties:
        starts_at:
          type: string
          format: date-time
        ends_at:
          type: string
          format: date-time
        capacity:
          type: integer
    EventSlotListResponse:
      type: object
      properties:
        slots:
          type: array
          items:
            $ref: '#/components/schemas/EventSlot'
        total_count:
          type: integer
    Schedule:
      type: object
      properties:
        schedule_id:
          type: string
          format: uuid
        event_id:
          type: string
          format: uuid
        time_start:
          type: string
        time_end:
          type: string
        date_start:
          type: string
          format: date
        capacity:
          type: integer
    CreateScheduleRequest:
      type: object
      required:
      - time_start
      - time_end
      - date_start
      - capacity
      properties:
        period_day:
          type: string
        period_week:
          type: array
          items:
            type: integer
        time_start:
          type: string
        time_end:
          type: string
        date_start:
          type: string
          format: date
        date_end:
          type: string
          format: date
        capacity:
          type: integer
    UpdateScheduleRequest:
      type: object
      properties:
        time_start:
          type: string
        time_end:
          type: string
        date_start:
          type: string
          format: date
        capacity:
          type: integer
    ScheduleListResponse:
      type: object
      properties:
        schedules:
          type: array
          items:
            $ref: '#/components/schemas/Schedule'
    Order:
      type: object
      properties:
        order_id:
          type: string
          format: uuid
        company_id:
          type: string
          format: uuid
        status:
          type: string
        items:
          type: array
    OrderListResponse:
      type: object
      properties:
        orders:
          type: array
          items:
            $ref: '#/components/schemas/Order'
        total_count:
          type: integer
    Place:
      type: object
      description: Место проведения события (адрес из Nominatim/OpenStreetMap)
      properties:
        place_id:
          type: string
          format: uuid
          description: Уникальный ID места
        osm_type:
          type: string
          example: relation
          description: Тип OSM объекта (node, way, relation)
        osm_id:
          type: integer
          format: int64
          description: ID в OpenStreetMap
        display_name:
          type: string
          description: Отображаемое название адреса
          example: Сочи, Краснодарский край, Россия
        lat:
          type: number
          format: double
          description: Широта
        lon:
          type: number
          format: double
          description: Долгота
        address:
          type: object
          description: Структурированный адрес (JSON)
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
          nullable: true
        event_count:
          type: integer
          description: Количество опубликованных событий (только для списка мест)
          nullable: true
    PublicCompany:
      type: object
      properties:
        company_id:
          type: string
          format: uuid
        code:
          type: string
        name:
          type: string
        description:
          type: object
        logo:
          type: object
        categories:
          type: array
    Problem:
      type: object
      properties:
        type:
          type: string
          format: uri
        title:
          type: string
        status:
          type: integer
        detail:
          type: string
        instance:
          type: string
          format: uri
        errors:
          type: array
          items:
            type: object
            properties:
              pointer:
                type: string
              detail:
                type: string
              rule:
                type: string
