openapi: 3.1.0
info:
  title: MEGOGO Partner Billing API
  version: 1.0.0
  summary: Користувачі, передплати й окремі купівлі для партнерів, які самі виставляють рахунки своїм
    користувачам.
  description: 'Billing API для партнерів: запити з префіксом `/partners/{partnerId}/`.


    ## Доступ


    Запити не підписуються. Запити, які читають або змінюють послуги

    користувача (`subscription/*`, `buyMovie`, `user/subscriptions`),

    MEGOGO приймає лише з IP-адрес партнера. Запит з іншої IP-адреси

    отримує HTTP 401. Передайте свої IP-адреси вашому менеджеру MEGOGO.

    Щоб змінити список IP-адрес, надішліть лист на

    supportpartners@megogo.net і вкажіть свій ID партнера. Нова IP-адреса

    починає працювати через кілька хвилин після зміни.


    ## Обмеження


    1000 запитів на хвилину для кожного ID партнера. Якщо перевищити цей ліміт, можна отримати

    HTTP 429 Too Many Requests.


    ## Тестове середовище


    Окремого тестового середовища немає. MEGOGO надає кожному партнерові

    тестовий ID партнера (наприклад, `testprod_ua`, `testprod_az`) і

    тестові ключі в продуктивному середовищі.


    ## Правило білінгу


    MEGOGO фіксує передплату або купівлю, коли запит виконано успішно

    (`"successful": true`), навіть якщо користувач нічого не дивиться.

    Списуйте оплату з користувача лише після успішної відповіді.


    ## Повторні запити


    Надсилайте запит повторно лише після тайм-ауту або відповіді HTTP 5xx.

    Між спробами чекайте 1 хвилину. Зробіть не більше 6 спроб.

    Для `subscribe` спочатку прочитайте блок «УВАГА» в розділі «Режими продовження».


    ## Помилки


    Помилка повертається з HTTP 200 і таким тілом:


    ```json

    {"successful": false, "message": "<text>, code <number>"}

    ```


    Текст повідомлення не фіксований і може містити код помилки. Не

    аналізуйте текст, окрім як для пошуку коду. Запит з IP-адреси

    або ID партнера, яких MEGOGO не знає, отримує HTTP 401 із тілом у

    вигляді простого тексту (не JSON).


    Найчастіша помилка — 2023: послуга вже активна для цього

    користувача. Інші коди допомагають команді MEGOGO знайти причину

    проблеми. Повідомте код і час запиту підтримці MEGOGO.


    | Код | Назва | Значення |

    |---|---|---|

    | 2009 | SUBSCRIPTION_NOT_SELLING | Передплата не продається |

    | 2010 | SUBSCRIPTION_NOT_FOUND | Передплату не знайдено |

    | 2012 | INVALID_PERMISSIONS | Неправильні налаштування передплати або тарифу |

    | 2013 | SUBSCRIPTION_NOT_GEO_PRESENTED | Передплата недоступна в регіоні |

    | 2015 | OBJECT_NO_VOD_PERMISSION_FOR_SALE | Відео не має моделі доступу для продажу |

    | 2016 | USER_SERVICE_CREATION_ERROR | MEGOGO не може створити послугу користувача |

    | 2017 | USER_SERVICE_NOT_FOUND | Послугу партнера не знайдено |

    | 2022 | TARIFF_ID_DOESNT_MATCH_ORDER_SERVICE_ID | ID тарифу не належить до тарифів цієї послуги |

    | 2023 | PROLONGATION_DISABLED | Послуга вже активна для цього користувача (`subscribe` або `resume`).
    Жодних дій не потрібно |

    | 2027 | DATE_FINISH_OUT_OF_BOUNDS | Дата завершення більш ніж на 5 років пізніша за поточну. Продовжити
    ще не можна |

    | 2029 | VOD_RULES_NOT_FOUND_FOR_OBJECT | Відео не має моделей доступу |

    | 2031 | SUBSCRIPTION_QUALITY_FOR_OBJECT_NOT_FOUND | Ця якість відео не входить до послуги |

    | 400 | — | Запит неможливо виконати. Наприклад, `buyMovie` для відео, яке користувач уже купив |

    | 4001 | OBJECT_PREVIOUSLY_PURCHASED | Користувач уже купив це відео |

    | 4003 | PARTNER_NOT_FOUND | Партнера не знайдено |

    | 5001 | USER_NOT_FOUND | Користувача не знайдено (`"message": "User not found"`) |

    | 40416 | — | ID послуги або ID тарифу не знайдено для вашого ID партнера |

    | 42901 | error.too_many_requests | Забагато запитів. Ліміт — 1000 запитів на хвилину для кожного
    ID партнера |




    ## Режими продовження


    MEGOGO встановлює для кожної послуги передплати один із двох режимів:


    | Режим | Продовження | Повторний `subscribe` для активної передплати |

    |---|---|---|

    | Автоматичне продовження | MEGOGO продовжує передплату щоперіоду, доки партнер не надішле `unsubscribe`
    | Помилка 2023: послуга вже активна для цього користувача. Жодних дій не потрібно |

    | Без автоматичного продовження | Передплату продовжує партнер: він знову надсилає `subscribe` | Кожен
    запит додає один період |


    Період задано в тарифі послуги. Зазвичай це 30 днів.

    Тестова послуга `ottsvod` партнера `testprod_ua` має автоматичне

    продовження і період 30 днів.

    MEGOGO може надати окремі послуги для пробного доступу (наприклад, на 7

    або 14 днів). Не обчислюйте дату завершення самостійно: беріть `dateFinish` з

    `user/subscriptions`.


    УВАГА: У режимі без автоматичного продовження запит `subscribe` **не

    ідемпотентний**. Кожен успішний запит додає ще один період. Перш ніж

    повторити запит після тайм-ауту, отримайте `user/subscriptions` і

    переконайтеся, що перший запит не було застосовано.


    УВАГА: Дата завершення передплати не може бути більш ніж на 5 років

    пізнішою за поточну. Запит `subscribe`, який виходить за цю межу, завершується

    помилкою 2027.


    ## Журналювання


    Рекомендуємо зберігати журнал усіх запитів і відповідей.

    '
  contact:
    name: MEGOGO partner support
    email: supportpartners@megogo.net
servers:
- url: https://billing.megogo.net
  description: 'Продуктивне середовище

    '
tags:
- name: Users
- name: Subscriptions
- name: Single purchases
paths:
  /partners/{partnerId}/user/create:
    get:
      tags:
      - Users
      operationId: createUser
      summary: Створити користувача без послуги
      description: 'Створює користувача в білінгу MEGOGO. Використовуйте цей запит, якщо

        користувач має авторизуватися (`/auth/by_partners`) ще до купівлі.

        `subscribe` і `buyMovie` також створюють користувача.


        Запит можна надсилати повторно: він повертає той самий `uid`.

        '
      parameters:
      - $ref: '#/components/parameters/partnerId'
      - $ref: '#/components/parameters/identifier'
      responses:
        '200':
          description: 'Користувача створено.

            '
          content:
            application/json:
              schema:
                type: object
                properties:
                  uid:
                    type: integer
                    description: 'ID користувача MEGOGO.

                      '
  /partners/{partnerId}/user/innerId:
    get:
      tags:
      - Users
      operationId: getUserInnerId
      summary: Отримати ID і логін користувача MEGOGO
      description: 'Якщо користувача не існує, також створює його.

        '
      parameters:
      - $ref: '#/components/parameters/partnerId'
      - $ref: '#/components/parameters/identifier'
      responses:
        '200':
          description: 'ID користувача MEGOGO. Відповідь містить лише `uid`.

            '
          content:
            application/json:
              schema:
                type: object
                properties:
                  uid:
                    type: integer
  /partners/{partnerId}/user/subscriptions:
    get:
      tags:
      - Users
      operationId: listUserServices
      summary: Отримати активні послуги користувача
      description: 'Використовуйте цей запит, щоб переконатися, що послуги користувача

        у вашій системі й у MEGOGO збігаються. Також надсилайте його, перш ніж

        повторити `subscribe` або `buyMovie`. Відповідь містить лише ті

        послуги, які ви активували через цей API.

        '
      parameters:
      - $ref: '#/components/parameters/partnerId'
      - $ref: '#/components/parameters/identifier'
      responses:
        '200':
          description: 'Активні передплати й куплені відео.

            '
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserServices'
              example:
                identifier: user123
                svod:
                - serviceId: examplesvod
                  serviceName: SVOD partners
                  dateFinish: 1798649598
                  dateFinishString: '2026-12-30 16:53:18'
  /partners/{partnerId}/subscription/{operation}:
    get:
      tags:
      - Subscriptions
      operationId: changeSubscription
      summary: Оформити, скасувати, призупинити або відновити передплату
      description: "Змінює передплату користувача. Якщо користувача не існує, створює\nйого.\n\n- `subscribe`\
        \ — оформити передплату. Для **активної**\n  передплати результат залежить від режиму продовження\n\
        \  послуги: автоматичне продовження → помилка 2023 (уже активна, жодних\n  дій не потрібно); без\
        \ автоматичного продовження → ще один період. Див.\n  «Режими продовження».\n- `unsubscribe` —\
        \ скасувати передплату. Доступ припиняється\n  **негайно**: після запиту передплати немає в `user/subscriptions`.\n\
        \  Повторний `unsubscribe` повертає `\"successful\": true`. Коли\n  надсилати запит, вирішуєте\
        \ ви: наприклад, у момент скасування або\n  в кінці періоду, за який користувач заплатив.\n- `suspend`\
        \ — призупинити передплату. Користувач не має доступу.\n  Передплати немає в `user/subscriptions`\
        \ до `resume`. Оплачений час\n  користувач не втрачає: після `resume` дата завершення\n  зсувається\
        \ вперед на час призупинення. Повторний `suspend`\n  повертає `\"successful\": true`.\n- `resume`\
        \ — відновити призупинену передплату. Для активної\n  передплати — помилка 2023.\n\nЩоб змінити\
        \ послугу, надішліть `unsubscribe` для старої послуги, а потім\n`subscribe` для нової.\n"
      parameters:
      - $ref: '#/components/parameters/partnerId'
      - name: operation
        in: path
        required: true
        schema:
          type: string
          enum:
          - subscribe
          - unsubscribe
          - suspend
          - resume
      - $ref: '#/components/parameters/userId'
      - $ref: '#/components/parameters/serviceId'
      responses:
        '200':
          description: 'Результат.

            '
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Result'
        '500':
          $ref: '#/components/responses/ServerError'
  /partners/{partnerId}/buyMovie:
    get:
      tags:
      - Single purchases
      operationId: buyMovie
      summary: Зафіксувати купівлю відео (TVOD/DTO)
      description: 'Фіксує, що користувач купив відео. Для ключів партнера має бути

        ввімкнено TVOD.


        `serviceId` — це `tariff_id`, який Content API повертає для цього

        відео в `purchase_info`. Не використовуйте

        `subscription_id` з Content API. Не використовуйте ціни та

        ID з XML-фіду: це тарифи MEGOGO. Неправильний

        `serviceId` повертає помилку 40416.


        Період оренди починається, коли користувач починає дивитися: з першого

        запиту `/stream`, який повертає `src`. До цього купівля має

        статус `unwatched` і не має дати завершення.


        Повторний `buyMovie` для того самого відео повертає помилку 400.

        '
      parameters:
      - $ref: '#/components/parameters/partnerId'
      - $ref: '#/components/parameters/userId'
      - name: videoId
        in: query
        required: true
        schema:
          type: integer
      - $ref: '#/components/parameters/serviceId'
      responses:
        '200':
          description: 'Результат.

            '
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Result'
        '500':
          $ref: '#/components/responses/ServerError'
components:
  parameters:
    partnerId:
      name: partnerId
      in: path
      required: true
      description: 'ID партнера.

        '
      schema:
        type: string
    identifier:
      name: identifier
      in: query
      required: true
      description: 'Ідентифікатор користувача на боці партнера. Будь-який рядок довжиною до 255

        символів: номер договору, номер особового рахунку, логін, номер телефону або

        хеш, якщо ви не хочете передавати реальні дані користувача.

        '
      schema:
        type: string
        maxLength: 255
    userId:
      name: userId
      in: query
      required: true
      description: 'Ідентифікатор користувача на боці партнера. Те саме значення, що й `identifier`.

        '
      schema:
        type: string
        maxLength: 255
    serviceId:
      name: serviceId
      in: query
      required: true
      description: 'ID послуги. MEGOGO створює його і передає партнерові.

        '
      schema:
        type: string
  responses:
    ServerError:
      description: 'Тимчасова помилка. Перш ніж повторити `subscribe` або `buyMovie`,

        перевірте послуги користувача через `user/subscriptions` (ці запити не

        ідемпотентні).

        '
  schemas:
    Result:
      type: object
      properties:
        successful:
          type: boolean
          description: '`true` — операцію виконано. Можна списувати оплату з користувача. Будь-яка інша

            відповідь — не списуйте оплату. Коди помилок див. в описі цього API.

            '
        message:
          type: string
    UserServices:
      type: object
      properties:
        identifier:
          type: string
        svod:
          type: array
          items:
            type: object
            properties:
              serviceId:
                type: string
              serviceName:
                type: string
              dateFinish:
                type: integer
                description: 'Unix-час (секунди).

                  '
              dateFinishString:
                type: string
                description: '`YYYY-MM-DD hh:mm:ss`, UTC.

                  '
        tvod:
          type: array
          description: 'Куплені відео. Якщо в користувача немає купівель, цього ключа у

            відповіді немає. `svod` у відповіді є завжди.

            '
          items:
            type: object
            properties:
              serviceId:
                type: string
                description: 'ID тарифу, переданий у `buyMovie`, у вигляді рядка.

                  '
              serviceName:
                type: string
              objectId:
                type: integer
                description: 'ID відео.

                  '
              status:
                type: string
                enum:
                - unwatched
                - started
                description: '`unwatched` — період оренди не почався. `started` — користувач почав перегляд.

                  '
              dateFinish:
                type: integer
                description: 'Кінець періоду оренди, Unix-час (секунди). Лише для `started`.

                  '
              dateFinishString:
                type: string
                description: '`YYYY-MM-DD hh:mm:ss`, UTC. Лише для `started`.

                  '
