openapi: 3.0.3
info:
  title: ShopStory Public API
  version: 1.0.0
  description: >-
    Публичные эндпоинты, использующиеся партнерами ShopStory. Ответы обернуты
    в общий конверт { status, serverTime, body }.
  externalDocs:
    description: Расширенное текстовое руководство
    url: ./public-api.md
servers:
  - url: https://app.shopstory.live
    description: Public app host
tags:
  - name: Mini Player
    description: Эндпоинты мини‑плеера
  - name: Public Streams
    description: Публичные списки и быстрый статус
 

paths:
  /v2/mini-player/stream:
    get:
      summary: Получить ссылку для мини‑плеера по товару
      tags: [Mini Player]
      parameters:
        - $ref: '#/components/parameters/ApplicationQuery'
        - $ref: '#/components/parameters/ProductCodeQuery'
        - in: query
          name: feedProductId
          required: false
          schema: { type: string }
          description: Альтернативный способ указать товар по feedProductId. Требуется либо productCode, либо feedProductId
        - $ref: '#/components/parameters/FeedProductGroupIdQuery'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Envelope_MiniPlayerStream'
              examples:
                vod:
                  value:
                    status: 200
                    serverTime: '2024-01-01T00:00:00.000Z'
                    body:
                      streamId: '2017'
                      streamStatus: completed
                      productId: 'p-123'
                      playbackLink: 'https://cdn.example/record/playlist.m3u8'
                      startTime: 120
        '400': { description: invalid request }
        '404': { description: not found or VOD processing }
        '500': { description: playback link not found }

  /v2/mini-player/online:
    get:
      summary: Текущий онлайн‑стрим (если есть)
      tags: [Mini Player]
      parameters:
        - $ref: '#/components/parameters/ApplicationQuery'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Envelope_MiniPlayerOnline'

  /v3/streams:
    get:
      summary: Публичный список стримов и справочники
      tags: [Public Streams]
      parameters:
        - $ref: '#/components/parameters/ApplicationIdQuery'
        - in: query
          name: feedProductId
          required: false
          schema: { type: string }
          description: Один идентификатор товара из фида (артикул)
        - in: query
          name: categoryId
          required: false
          schema: { type: integer, format: int64 }
          description: Идентификатор категории/тега стрима
        - in: query
          name: status
          required: false
          schema:
            type: string
            enum: [planned, online, finished]
          description: Фильтр по статусу. Логика AND с остальными фильтрами
        - in: query
          name: limit
          required: false
          schema: { type: integer, minimum: 0, maximum: 100 }
          description: Пагинация. Применяется к группе, которая пагинируется
        - in: query
          name: offset
          required: false
          schema: { type: integer, minimum: 0 }
          description: Смещение для пагинации
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Envelope_PublicStreams'
        '400': { description: invalid applicationId }

  /v3/translation/quick-state:
    get:
      summary: Быстрый статус стрима
      tags: [Public Streams]
      parameters:
        - $ref: '#/components/parameters/TranslationIdQuery'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Envelope_QuickState'

  

components:

  schemas:
    Envelope_MiniPlayerStream:
      type: object
      properties:
        status: { type: integer }
        serverTime: { type: string, format: date-time }
        body:
          $ref: '#/components/schemas/MiniPlayerStream'

    Envelope_MiniPlayerOnline:
      type: object
      properties:
        status: { type: integer }
        serverTime: { type: string, format: date-time }
        body:
          type: object
          properties:
            online:
              $ref: '#/components/schemas/MiniPlayerOnline'

    Envelope_PublicStreams:
      type: object
      properties:
        status: { type: integer }
        serverTime: { type: string, format: date-time }
        body:
          $ref: '#/components/schemas/PublicStreamsResponse'

    Envelope_QuickState:
      type: object
      properties:
        status: { type: integer }
        serverTime: { type: string, format: date-time }
        body:
          $ref: '#/components/schemas/QuickState'

 

    MiniPlayerStream:
      type: object
      properties:
        streamId: { type: string }
        streamStatus:
          type: string
          enum: [online, completed]
        productId: { type: string }
        feedProductId:
          type: string
          nullable: true
          description: Идентификатор товара из фида (строка). Аддитивное поле, может отсутствовать
        playbackLink: { type: string }
        startTime:
          type: integer
          description: Смещение начала эпизода с продуктом (секунды, только для VOD)

    MiniPlayerOnline:
      type: object
      properties:
        streamId: { type: string }
        streamStatus:
          type: string
          enum: [online]
        playbackLink: { type: string }

    PublicStreamsResponse:
      type: object
      properties:
        plannedStreams:
          type: array
          items: { $ref: '#/components/schemas/Translation' }
        availableStreams:
          type: array
          items: { $ref: '#/components/schemas/Translation' }
        total:
          type: integer
          description: Общий каунт для набора, к которому применена пагинация
        products:
          type: array
          items: { $ref: '#/components/schemas/Product' }
        streamers:
          type: array
          items: { $ref: '#/components/schemas/Streamer' }
        categories:
          type: array
          items: { $ref: '#/components/schemas/Category' }

    Translation:
      type: object
      properties:
        id: { type: string }
        application: { type: string }
        name: { type: string }
        description: { type: string }
        streamer: { type: string }
        status:
          type: string
          enum: [planned, online, finished]
        plannedDate: { type: string, format: date-time, nullable: true }
        startDate: { type: string, format: date-time, nullable: true }
        endDate: { type: string, format: date-time, nullable: true }
        previewImages:
          type: array
          items: { $ref: '#/components/schemas/PreviewImage' }
        products:
          type: array
          items: { type: string, description: productId }
        productFeedIds:
          type: array
          items: { type: string, description: feedProductId }
        categories:
          type: array
          items: { type: integer, format: int64 }

    Product:
      type: object
      properties:
        id: { type: string }
        name: { type: string }
        application: { type: string }
        vendorCode:
          type: string
          nullable: true
          description: SKU клиента (строка, ведущие нули сохраняются), если доступен в источнике (может отсутствовать)
        feedProductId:
          type: string
          nullable: true
          description: Идентификатор товара из фида (строка, ведущие нули сохраняются), если доступен (может отсутствовать)
        feedProductGroupId:
          type: string
          nullable: true
          description: Идентификатор группы/варианта из фида (строка), если доступен (может отсутствовать)
        url: { type: string }
        previewImages:
          type: array
          items: { $ref: '#/components/schemas/PreviewImage' }

    Streamer:
      type: object
      properties:
        id: { type: string }
        application: { type: string }
        profile:
          type: object
          properties:
            nickname: { type: string }
            firstname: { type: string }
            lastname: { type: string }
            about: { type: string }
            banner: { $ref: '#/components/schemas/Image' }
            avatar: { $ref: '#/components/schemas/Image' }

    Category:
      type: object
      properties:
        id: { type: integer, format: int64 }
        application: { type: string }
        name: { type: string }

    PreviewImage:
      type: object
      properties:
        src: { type: string }
        mediaId: { type: string }
        type: { type: string }

    Image:
      type: object
      properties:
        src: { type: string }
        type: { type: string }
        size: { type: string }

    QuickState:
      type: object
      properties:
        translationId: { type: string }
        translationState:
          type: string
          enum: [draft, confirmed, online, completed, '']
        expires: { type: string, format: date-time }

 
  parameters:
    ApplicationQuery:
      name: application
      in: query
      required: true
      schema: { type: string }
    ApplicationIdQuery:
      name: applicationId
      in: query
      required: true
      schema: { type: string }
    ProductCodeQuery:
      name: productCode
      in: query
      required: true
      schema: { type: string }
    FeedProductGroupIdQuery:
      name: feedProductGroupId
      in: query
      required: false
      schema: { type: string }
    TranslationIdQuery:
      name: translationId
      in: query
      required: true
      schema: { type: string }
