openapi: 3.0.3
info:
  title: MCP-Merchant Integration API
  version: 1.0.5
  description: |
    Спецификация взаимодействия MCP-сервера с Мерчантами
servers:
  - url: https://yourserver.com
    description: Адрес запроса
tags:
- name: Search & Actualize
  x-displayName: Обеспечение товарного поиска
- name: Logistics & Orders
  x-displayName: Подготовка и оформление заказа
- name: Payments
  x-displayName: Оплата заказа
components:
  parameters:
    RequestId:
      name: rqUid
      in: header
      required: true
      description: Уникальный сквозной идентификатор запроса для трассировки цепочки операций.
      schema:
        type: string
        format: uuid
        example: '1c6ec07e-3103-41bb-8753-6cea67521198'
  schemas:
    # --- Базовые модели ---
    Money:
      type: object
      required: [amount, currency]
      properties:
        amount:
          type: number
          format: decimal
          example: 450.35
          description: Сумма в единицах валюты (два знака после запятой).
        currency:
          type: string
          example: "RUB"
          description: Код валюты ISO 4217
    Latitude:
      type: number
      format: double
      minimum: -90
      maximum: 90
      description: Широта местоположения пользователя.
      example: 55.755826
    Longitude:
      type: number
      format: double
      minimum: -180
      maximum: 180
      description: Долгота местоположения пользователя.
      example: 37.6173
    StoreId:
      type: string
      description: Идентификатор магазина Мерчанта.
      example: 'STORE-99821-B'
    ShippingMethods:
      type: string
      enum: [delivery, pickup]
      description: Тип доставки.
    DeliveryPickupOptions:
      type: object
      required: [startsAt, endsAt, deliveryPrice]
      description: Информация о доступных слотах доставки или интервалах для самовывоза.
      properties:
        deliveryPrice:
          $ref: '#/components/schemas/Money'
        orderPrice:
          $ref: '#/components/schemas/Money'
        startsAt:
          type: string
          format: date-time
          maxLength: 255
          description: Интервал доставки или самовывоза (начало).
        endsAt:
          type: string
          format: date-time
          maxLength: 255
          description: Интервал доставки или самовывоза (окончание).
    ProductItem:
      type: object
      required: [skuId, skuName, skuDescription, price, photo, storeId]
      properties:
        skuId:
          type: string
          example: "SKU-99821-B"
          description: Уникальный идентификатор товара на стороне Мерчанта.
        skuName:
          type: string
          example: "Колбаса докторская, 330г"
          description: Наименование товара на стороне Мерчанта.
        skuDescription:
          type: string
          example: "Колбаса докторская — самая вкусная и сочная"
          description: Описание товара на стороне Мерчанта.
        price:
          $ref: '#/components/schemas/Money'
        photo:
          type: string
          format: uri
          example: "https://example.com/product.jpg"
          description: Ссылка на фото товара.
        storeId:
          type: string
          example: "STORE-99821-B"
          description: Уникальный идентификатор магазина, в котором найден товар.
        storeAddress:
          type: string
          example: "Moscow, Tverskaya 1"
          description: Адрес магазина
        quantity:
          type: number
          format: float
          example: 0.33
          description: Количество товара (поддерживается весовой товар).
        unit:
          type: string
          enum: [pcs, kg, g, l, ml]
          example: "kg"
          description: Единица измерения товара.
        stock:
          type: integer
          minimum: 0
          example: 10
          description: Количество товара в магазине.
        rating:
          type: number
          minimum: 0
          maximum: 5
          example: 4.7
          description: Рейтинг товара в магазине Мерчанта.
        availToDelivery:
          type: boolean
          example: true
          description: Признак доступности товара для доставки.
        availToPickupFromStore:
          type: boolean
          example: true
          description: Признак доступности товара для самовывоза из магазина.
    ProductItemOrder:
      type: object
      required: [skuId, quantity]
      properties:
        skuId:
          type: string
          example: "SKU-99821-B"
          description: Уникальный идентификатор товара на стороне Мерчанта.
        price:
          $ref: '#/components/schemas/Money'
        discount:
          $ref: '#/components/schemas/Money'
        quantity:
          type: number
          format: float
          example: 0.33
          description: Количество товара (поддерживается весовой товар).
        unit:
          type: string
          enum: [pcs, kg, g, l, ml]
          example: "kg"
          description: Единица измерения товара.
    Credentials:
      type: object
      properties:
        authType:
          type: string
          enum: [oauth2]
          description: Тип аутентификации.
        oauth2:
          type: string
          description: Токен аутентификации между MCP-сервером и Мерчантом.
          example: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwia'
        accessToken:
          type: string
          description: Пользовательский токен, полученный от Мерчанта.
          example: 'userAccessToken'
    Error:
      type: object
      properties:
        code:
          type: string
          description: HTTP-статус.
          example: "400"
        message:
          type: string
          description: Подробное описание ошибки.
          example: "Неверный формат запроса: отсутствует обязательный параметр lat"
    # --- Схемы запросов и ответов (Request/Response) ---
    SearchRequest:
      type: object
      required: [lat, lon, query]
      properties:
        lat:
          $ref: '#/components/schemas/Latitude'
        lon:
          $ref: '#/components/schemas/Longitude'
        query:
          type: string
          description: Текстовый запрос пользователя для поиска товара.
          example: 'колбаса докторская 330 г'
        maxResult:
          type: integer
          format: int32
          description: Максимальное возвращаемое количество товаров.
          minimum: 1
          maximum: 500
          default: 10
        storeId:
          $ref: '#/components/schemas/StoreId'
    SearchResponse:
      type: object
      required: [merchantName, items]
      properties:
        merchantName:
          type: string
          description: Название Мерчанта.
          example: 'Sneaker Shop'
        items:
          type: array
          minimum: 0
          maximum: 500
          items:
            $ref: '#/components/schemas/ProductItem'
    ActualizeRequest:
      type: object
      required: [skuIds]
      properties:
        skuIds:
          type: array
          items:
            type: string
          description: Список skuId для проверки цен и остатков.
          minimum: 1
        storeId:
          $ref: '#/components/schemas/StoreId'
    ActualizeResponse:
      type: object
      required: [items]
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/ProductItem'
    DeliveryRequest:
      type: object
      required: [shipping, items]
      properties:
        shipping:
          $ref: '#/components/schemas/ShippingMethods'
        deliveryAddress:
          type: object
          description: Координаты доставки.
          properties:
            lat:
              $ref: '#/components/schemas/Latitude'
            lon:
              $ref: '#/components/schemas/Longitude'
        storeId:
          $ref: '#/components/schemas/StoreId'
        items:
          type: array
          items:
            $ref: '#/components/schemas/ProductItemOrder'
        credentials:
          $ref: '#/components/schemas/Credentials'
    DeliveryResponse:
      type: object
      required: [storeId]
      properties:
        storeId:
          $ref: '#/components/schemas/StoreId'
        options:
          type: array
          items:
            $ref: '#/components/schemas/DeliveryPickupOptions'
    CheckoutRequest:
      type: object
      required: [items, storeId, shipping, shippingOptions]
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/ProductItemOrder'
        storeId:
          $ref: '#/components/schemas/StoreId'
        shipping:
          $ref: '#/components/schemas/ShippingMethods'
        deliveryAdress:
          type: object
          description: Обязательно передается в случае `shipping` = `delivery`.
          properties:
            lat:
              $ref: '#/components/schemas/Latitude'
            lon:
              $ref: '#/components/schemas/Longitude'
            fullAddress:
              type: string
              description: Полный адрес доставки.
              example: 'Moscow, Tverskaya 1'
        shippingOptions:
          $ref: '#/components/schemas/DeliveryPickupOptions'
        credentials:
          $ref: '#/components/schemas/Credentials'
    CheckoutResponse:
      type: object
      required: [orderId]
      properties:
        orderId:
          type: string
          description: ID заказа в системе Мерчанта.
        externalCartUrl:
          type: string
          format: uri
          description: Ссылка на сформированную корзину на странице Мерчанта. Дальнейшее взаимодействие (оплата и подтверждение) будут происходить на стороне Мерчанта.
        sberpayDetails:
          type: object
          nullable: true
          description: Данные для проведения оплаты через Sberpay (если данный метод поддерживается Мерчантом).
          additionalProperties: true
        paymentDetails:
          type: object
          nullable: true
          description: Данные для проведения оплаты другими методами (СБП, другой эквайер).
          additionalProperties: true
    UserAuthRequest:
      type: object
      required: [token]
      properties:
        token:
          type: string
          description: Токен `account_linking` или другой атрибут, содержащий данные о пользователе.
    UserAuthSberidRequest:
      type: object
      required: [tokenSberId]
      properties:
        tokenSberId:
          type: string
          description: Токен для идентификации пользователя у Мерчанта.
    UserAuthResponse:
      type: object
      required: [accessToken, expiresIn, userId, userStatus]
      properties:
        userStatus:
          type: string
          enum: [new, authorized, sso]
          description: |
            Статус учетной записи пользователя на стороне Мерчанта. Возможные значения:
            
            * `new` - новый пользователь (создана пустая УЗ);
            * `sso` - новый пользователь, зарегистрированный бесшовно;
            * `authorized` - зарегистрированный пользователь.
        accessToken: 
          type: string
          description: Токен доступа для запросов на оформление заказа и доставки (вместо токена в этом параметре может быть передан как sessionId, uuid или другой атрибут, однозначно идентифицирующий пользователя на стороне Мерчанта).
        expiresIn:
          type: integer
          description: Время жизни токена в секундах.
          format: int64
          example: 3600
        userId:
          type: string
          description: ID пользователя в системе Мерчанта, под которыми хранятся его связки (привязанные карты и т.п.).
    StatusOrderResponse:
      type: object
      required: [status, updatedAt]
      properties:
        status:
          type: string
          enum: [new, paid, processing, delivering, ready_for_pickup, completed, cancelled]
          description: Текущий статус заказа.
        updatedAt:
          type: string
          format: date-time
          description: Дата и время обновления статуса заказа.
    PaymentInitRequest:
      type: object
      required: [orderId, backUrl, credentials]
      properties:
        orderId:
          type: string
          description: ID заказа в системе Мерчанта.
        backUrl:
          type: string
          format: uri
          description: URL для возврата пользователя к UI ретейлера.
        credentials:
          $ref: '#/components/schemas/Credentials'
      additionalProperties: true
    PaymentInitResponse:
      type: object
      required: [paymentId]
      properties:
        paymentUrl:
          type: string
          format: uri
          description: Ссылка на платежную форму.
        paymentId:
          type: string
          description: Уникальный ID транзакции в платежной системе.
        details:
          type: object
          description: Специфичные данные (например, QR-код, токен виджета и т.п.).
          additionalProperties: true
    PaymentFinishRequest:
      type: object
      required: [paymentId, credentials]
      properties:
        paymentId:
          type: string
          description: Уникальный ID транзакции в платежной системе.
        credentials:
          $ref: '#/components/schemas/Credentials'
    PaymentFinishResponse:
      type: object
      required: [status, orderId]
      properties:
        status:
          type: string
          enum: [pending, waiting_for_capture, succeeded, canceled, failed]
          description: Статус транзакции.
        orderId:
          type: string
          description: ID заказа в системе Мерчанта.
paths:
  /search:
    post:
      summary: Поиск товаров
      operationId: postSearch
      tags: [Search & Actualize]
      description: |
        Мерчант на своей стороне реализует поиск и выдачу релевантной информацию по текстовому запросу пользователя, учитывая ближайшие магазины к переданному адресу пользователя в виде координат.
        
        Один запрос используется для получения информации по одному товару.
        
        Если в запросе был передан `storeId`, то в ответе необходимо возвращать товары из этого магазина.
        
        Если не было найдено ни одного подходящего товара — возвращать пустой массив в `items`.
      parameters:
        - $ref: '#/components/parameters/RequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SearchRequest'
      responses:
        '200':
          description: Результаты поиска
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
        '400':
          description: Неверный формат запроса
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Внутренняя ошибка сервиса
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /actualize:
    post:
      summary: Актуализация информации о товарах
      operationId: postActualize
      tags: [Search & Actualize]
      description: |
        Мерчант на своей стороне реализует актуализацию информации по выбранным пользователем товаров для заказа в конкретной точке.
        
        В ответе для товара **обязательно** возвращать признаки `availToDelivery` и `availToPickupFromStore`.
      parameters:
        - $ref: '#/components/parameters/RequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ActualizeRequest'
      responses:
        '200':
          description: Актуальные данные.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActualizeResponse'
        '400':
          description: Неверный формат запроса.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Внутренняя ошибка сервиса.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /auth/sberid:
    post:
      summary: Авторизация пользователя по токену SberID
      operationId: postAuthSberid
      tags: [Logistics & Orders]
      description: |
        Перед оформлением заказа необходимо авторизовать пользователя на стороне Мерчанта.
        
        Вернувшийся в ответе токен доступа пользователя будет передаваться в запросах на получение информации доставки, оформлении заказа и оплаты.
        
        **Важно:** со стороны Мерчанта при получении запроса необходимо проводить интроспекцию — валидировать предоставленный токен у SberID.
      parameters:
        - $ref: '#/components/parameters/RequestId'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserAuthSberidRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserAuthResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /auth/other:
    post:
      summary: Авторизация пользователя
      operationId: postAuthOther
      tags: [Logistics & Orders]
      description: |
        Перед оформлением заказа необходимо авторизовать пользователя на стороне Мерчанта.
        
        Вернувшийся в ответе токен доступа пользователя будет передаваться в запросах на получение информации доставки, оформлении заказа и оплаты.
      parameters:
        - $ref: '#/components/parameters/RequestId'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserAuthRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserAuthResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /delivery:
    post:
      summary: Выбор способа получения заказа
      operationId: postDelivery
      tags: [Logistics & Orders]
      description: |
        Мерчант предоставляет пользователю выбор метода получения заказа в `shipping` — курьерская доставка или самовывоз.
        
        **Для доставки** в запросе будет передан `deliveryAdddress` с координатами доставки.
        
        **Для самовывоза** в запросе будет передан `storeId`.
      parameters:
        - $ref: '#/components/parameters/RequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DeliveryRequest'
      responses:
        '200':
          description: Расчет доставки.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeliveryResponse'
        '400':
          description: Неверный формат запроса.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Внутренняя ошибка сервиса.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /checkout:
    post:
      summary: Оформление заказа
      operationId: postCheckout
      tags: [Logistics & Orders]
      description: |
        Мерчант на своей стороне реализует оформление заказа в своей системе по предоставленной информации о выбранных товарах, выбранном методе и временном интервале доставки или самовывоза.
        
        В ответе ожидается получение информации о доступных методах оплаты для пользователя и иной доп. информации для завершения процесса оформления заказа.
        
        Если не возвращается инфорамция об оплате — должна вернуться ссылка-редирект на страничку Мерчанта `externalCartUrl`.
      parameters:
        - $ref: '#/components/parameters/RequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CheckoutRequest'
      responses:
        '200':
          description: Заказ создан.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CheckoutResponse'
        '400':
          description: Неверный формат запроса.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Не аутентифицирован.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Внутренняя ошибка сервиса.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /payment/init:
    post:
      summary: Инициация оплаты
      operationId: postPaymentInit
      tags: [Payments]
      description: |
        На данном шаге осуществляется создание платежа и получение ссылки на оплату.
      parameters:
        - $ref: '#/components/parameters/RequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PaymentInitRequest'
      responses:
        '200':
          description: Платежные данные.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentInitResponse'
  /payment/finish:
    post:
      summary: Проверка оплаты
      operationId: postPaymentFinish
      tags: [Payments]
      description: |
        Проверка финального статуса транзакции после возврата пользователя.
      parameters:
        - $ref: '#/components/parameters/RequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PaymentFinishRequest'
      responses:
        '200':
          description: Получена информация о платеже.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentFinishResponse'
  /order/{orderId}/status:
    get:
      summary: Проверка статуса заказа
      operationId: getOrderStatus
      tags: [Logistics & Orders]
      description: |
        Мерчант по `orderId` заказа возвращает его актуальное состояние.
      parameters:
        - name: orderId
          in: path
          required: true
          schema:
            type: string
            description: ID заказа в системе Мерчанта.
      responses:
        '200':
          description: Текущий статус заказа.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StatusOrderResponse'
        '404':
          description: Заказ не найден.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Внутренняя ошибка сервиса.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
