openapi: 3.0.0
info:
  version: 'v.0.0.4'
  title: 'Luna Video Agent API'
  description: |
     'VisionLabs Luna Video Agent'

components:
  headers:
    application_json:
      schema:
        type: string
        enum:
        - application/json
      required: true
      description: The content type of the response body.

    luna_request_id:
      schema:
        type: string
        format: timestamp,uuid
        example: 1536751345,8b8b5937-2e9c-4e8b-a7a7-5caf86621b5a
        pattern: ^[0-9]{10},[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$
      description: request id. Helps to uniquely identify messages that correspond to particular requests, in system logs.
      required: true

    docs_content_type:
      schema:
        type: string
        enum:
          - application/x-yaml
          - text/html
      required: true
      description: The content type of the response body.

    text_html:
      schema:
        type: string
        enum:
          - text/html
      required: true
      description: The content type of the response body.

    config_accept_content_type:
      schema:
        type: string
        enum:
          - application/json
          - text/plain
      required: false
      description: The content type of the response body.
  parameters:
    luna_request_id:
      in: header
      schema:
        type: string
        format: timestamp,uuid
        example: 1536751345,8b8b5937-2e9c-4e8b-a7a7-5caf86621b5a
        pattern: ^[0-9]{10},[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$
      description: |
        external request id. Helps to uniquely identify messages that correspond to particular requests, in system logs.
        If it was not set, system will set it in default format ("timestamp,UUID"). It will be returned with response.
      name: Luna-Request-Id

    accept_docs_handler:
      in: header
      name: Accept
      schema:
        $ref: '#/components/schemas/accept_docs_handler'
      required: true
      description: acceptable type of receiving data

    Accept:
      in: header
      name: Accept
      schema:
        type: string
        enum:
          - application/json
      description: Preferred response content type

    accept_config_handler:
      in: header
      name: Accept
      schema:
        type: string
        enum:
          - application/json
          - text/plain
        description: One of application/json, text/plain
      required: false
      description: acceptable type of receiving data

    include_luna_services:
      in: query
      name: include_luna_services
      schema:
        type: integer
        enum: [0, 1]
        default: 0
      description: Whether to perform healthchecks for dependent luna services.
  schemas:
    error:
      type: object
      properties:
        error_code:
          type: integer
          description: Error code.
        desc:
          type: string
          description: Short error description.
        detail:
          type: string
          description: Error details.
        link:
          type: string
          description: Link to the documentation website with the error description.
      required: [error_code, detail, desc, link]
      example:
        error_code: 1
        detail: internal server error
        desc: internal server error
        link: "https://docs.visionlabs.ai/info/luna/troubleshooting/errors-description/code-1"

    int_version:
      type: integer
      minimum: 0

    accept_docs_handler:
      type: string
      enum:
        - application/x-yaml
        - text/html
      description: One of application/x-yaml, text/html.

    version:
      type: object
      properties:
        Version:
          type: object
          properties:
            api:
              allOf:
                - $ref: '#/components/schemas/int_version'
              description: An api version of service.
            major:
              allOf:
                - $ref: '#/components/schemas/int_version'
              description: A major version of service.
            minor:
              allOf:
                - $ref: '#/components/schemas/int_version'
              description: A minor version of service.
            patch:
              allOf:
                - $ref: '#/components/schemas/int_version'
              description: A patch version of service.
          required: [ api, major, minor, patch ]
      required: [ Version ]

      example:
        Version:
          api: 1
          major: 0
          minor: 0
          patch: 0

    plugin_status:
      type: object
      properties:
        name:
          type: string
          description: Plugin name
        running:
          allOf:
            - $ref: '#/components/schemas/int01'
            - description: Whether plugin is running or not.
      required: [name, running]

    plugins:
      type: object
      properties:
        plugins:
          description: List of imported plugins.
          type: array
          items:
            $ref: '#/components/schemas/plugin_status'
      required: [plugins]
      example:
        plugins:
          - name: foo
            running: 1

    health_ok:
      description: Successful healthcheck execution info.
      type: object
      properties:
        execution_time:
          type: number
          example: 0.123
          description: Request execution time in seconds.
      required: [ execution_time ]

    health_errors:
      type: object
      properties:
        errors:
          description: Failed healthcheck execution info.
          type: array
          items:
            type: object
            properties:
              component:
                description: Component name.
                type: string
              error:
                allOf:
                  - description: Healthcheck error.
                  - $ref: '#/components/schemas/error'
              status:
                description: Component health status.
                type: integer
                enum: [ 0, 1 ]
            required: [ component, error, status ]
      required: [ errors ]
      example:
        errors:
          - component: licenses
            error:
              error_code: 38001
              desc: Health check error
              detail: License error
              link: https://docs.visionlabs.ai/info/luna/troubleshooting/errors-description/code-38001
            status: 0

    int01:
      type: integer
      enum: [0,1]

    roi_int_coordinates:
      type: integer
      minimum: 0
      default: 0
      maximum: 65536
      example: 3327

    roi_float_percent:
      type: number
      format: float
      minimum: 0
      default: 0.0
      maximum: 100.0
      example: 87.4

    roi_float_percent_size:
      type: number
      format: float
      minimum: 0.00001
      maximum: 100.0
      example: 66.3

    roi_abs:
      type: object
      properties:
        x:
          $ref: '#/components/schemas/roi_int_coordinates'
        y:
          $ref: '#/components/schemas/roi_int_coordinates'
        width:
          $ref: '#/components/schemas/roi_int_coordinates'
        height:
          $ref: '#/components/schemas/roi_int_coordinates'
        mode:
          type: string
          enum: [abs]
          example: "abs"
          description: Coordinates and size are set in pixels.
      required: [x, y, width, height, mode]

    roi_percent:
      type: object
      properties:
        x:
          $ref: '#/components/schemas/roi_float_percent'
        y:
          $ref: '#/components/schemas/roi_float_percent'
        width:
          $ref: '#/components/schemas/roi_float_percent_size'
        height:
          $ref: '#/components/schemas/roi_float_percent_size'
        mode:
          type: string
          enum: [ percent ]
          example: "percent"
          description: Coordinates and size are set in percentage.
      required: [x, y, width, height, mode]

    roi:
      oneOf:
        - $ref: '#/components/schemas/roi_abs'
        - $ref: '#/components/schemas/roi_percent'
      description: |
          Region of interest on a frame. Boundaries of the area are described in `x`, `y` coordinates 
          of the top left point and `width`, `height` properties
          **Region must not be any bigger than the original frame**

          The region of interest will be sent to estimator. The smaller the `roi`, the smaller the area the estimator 
          will process and, accordingly, work faster.

    droi:
      type: object
      properties:
        area:
          type: array
          items:
            type: array
            items:
              type: object
              properties:
                x:
                  type: number
                  minimum: 0
                y:
                  type: number
                  minimum: 0
              required: [ x, y ]
            minItems: 3
            description: |
              Polygon defined by a number of vertex coordinates.
              
              The people coordinates located outside of the `droi` will not be taken into account.
          minItems: 1
        mode:
          type: string
          enum: [ percent, abs ]
        form:
          type: string
          enum: [ common ]
      required: [ area, mode, form ]
      description: |
          Region of interest on a frame to apply filter for targets estimated.
          Boundaries of the area are described by a combination of polygons defined by vertex coordinates.

    number01:
      type: number
      minimum: 0
      maximum: 1

    rate:
      type: object
      description: |
        Analytic rate execution determines on which frames the analytics will be launched.
        
        Analytic rate execution can be configured in next ways:
        - execute analytic on each Nth frame (`unit` - `frame`)
        - execute analytic on each frame corresponding to the Nth second (`unit` - `second`)
      properties:
        period:
          type: integer
          minimum: 1
          description: Period length.
        unit:
          type: string
          enum:
            - frame
            - second
          description: Unit for a period calculation (every `n` seconds or every `n` frames).
      required: [ unit, period ]

    callback_base:
      type: object
      properties:
        enable:
          type: integer
          enum: [0, 1]
          default: 1
          description: Whether callback enabled or not.
        trigger:
          type: object
          description: Callback actuation trigger.
          properties:
            threshold:
              type: integer
              minimum: 1
              default: 1
              description: Lower included boundary of `people_count` in generated event for callback execution.

    callback_ws:
      allOf:
        - $ref: "#/components/schemas/callback_base"
        - type: object
          properties:
            type:
              type: string
              enum: [luna-ws-notification]
              description: Event will be sent with `crowd` type.
      required: [type]

    callback_basic_authorization:
      type: object
      properties:
        type:
          type: string
          description: Authorization type.
          enum: [basic]
        login:
          type: string
          maxLength: 128
          description: Login.
        password:
          type: string
          maxLength: 128
          description: Password.
      required: [ type, login, password]
      description: Callback basic authorization parameters.

    callback_http:
      allOf:
        - $ref: "#/components/schemas/callback_base"
        - type: object
          properties:
            type:
              type: string
              enum: [http]
              description: Event will be sent to http url.
            url:
              type: string
              description: Callback url.
            authorization:
              $ref: '#/components/schemas/callback_basic_authorization'
            params:
              type: object
              properties:
                timeout:
                  type: integer
                  default: 60
                  description: Callback request timeout.
                content_type:
                  type: string
                  default: application/json
                  enum: [application/json, application/msgpack]
                  description: Callback request content type.
                headers:
                  type: object
                  description: Callback request headers.
                  additionalProperties: true
              description: Callback request parameters
      required: [url, type]

    callback:
      oneOf:
        - $ref: '#/components/schemas/callback_http'
        - $ref: '#/components/schemas/callback_ws'
      discriminator:
        propertyName: type
        mapping:
          http: '#/components/schemas/callback_http'
          luna-ws-notification: '#/components/schemas/callback_ws'

    image_retain_policy:
      type: object
      description: |
        Image retain policy applicable when analytic `overview` target is specified, 
        and configures parameters with which will image be saved.
      properties:
        mimetype:
          type: string
          enum:
            - PNG
            - JPEG
          default: JPEG
          description: Image format.
        quality:
          allOf:
            - $ref: '#/components/schemas/number01'
            - default: 1
          description: Image quality, on a scale from 0 (worst) to 1 (best). Has no effect on `PNG`.
        max_size:
          type: integer
          minimum: 0
          default: 640
          description: Image max size, in pxl. Neither the width nor the height will exceed this value.

    period_event_policy:
      type: object
      properties:
        trigger:
          type: string
          enum: [period]
        interval:
          type: float
          description: Event generation period interval.
          minimum: 0.0
          default: 1.0
      required: [trigger]

    start_event_policy:
      type: object
      properties:
        trigger:
          type: string
          enum: [start]
      required: [trigger]

    end_event_policy:
      type: object
      properties:
        trigger:
          type: string
          enum: [end]
      required: [trigger]

    parameters:
      type: object
      properties:
        targets:
          type: array
          default: []
          items:
            type: string
            enum: [coordinates, overview]
          description: |
            Estimations to perform on the video.

            `coordinates` will add `people_coordinates` to frames estimations.
            
            `overview` will add overview processing and enable image saving.
        callbacks:
          type: array
          description: |
            Callbacks parameters.
            
            `http` type callback sends events to the specified url by POST request.

            `luna-ws-notification` type callback sends events to websocket using sender.
          maxItems: 10
          items:
            $ref: '#/components/schemas/callback'

        parameters:
          type: object
          description: Estimation parameters.
          properties:
            people_count_threshold:
              type: integer
              min: 0
              description: Minimal human count for an analytics track generation.
              default: 0
            event_policy:
              description: |
                Event policy. 
                
                When people count reaches specified `people_count_threshold` the new `track` will starts, when people count will
                be less than `people_count_threshold` `track` will ends. Event can be generated in next cases:

                - when track starts (`trigger` - `start`)
                - when track ends (`trigger` - `end`)
                - periodically while track exists (`trigger` - `period`)
              type: object
              properties:
              oneOf:
                - $ref: '#/components/schemas/period_event_policy'
                - $ref: '#/components/schemas/start_event_policy'
                - $ref: '#/components/schemas/end_event_policy'
              discriminator:
                propertyName: trigger
                mapping:
                  period: '#/components/schemas/period_event_policy'
                  start: '#/components/schemas/start_event_policy'
                  end: '#/components/schemas/end_event_policy'
            image_retain_policy:
              $ref: '#/components/schemas/image_retain_policy'
            roi:
              $ref: '#/components/schemas/roi'
            droi:
              $ref: '#/components/schemas/droi'
            rate:
              allOf:
                - $ref: '#/components/schemas/rate'
                - default:
                    unit: frame
                    period: 10
            probe_count:
              description: |
                A number of consecutive `people count` estimations where people count more or equal 
                `people_count_threshold` before start analytic track generation. This parameter is intended to
                prevent false positives from analytics.
              type: integer
              minimum: 0
              default: 3

    string36_nullable:
      type: string
      maxLength: 36
      nullable: true

    longitude:
      type: number
      minimum: -180
      maximum: 180
      example: 36.616

    latitude:
      type: number
      minimum: -90
      maximum: 90
      example: 55.752

    geo_position:
      type: object
      nullable: true
      description: Geo position specified by geographic coordinates - longitude and latitude.
      properties:
        longitude:
          allOf:
            - $ref: '#/components/schemas/longitude'
            - description: Longitude in degrees.
        latitude:
          allOf:
            - $ref: '#/components/schemas/latitude'
            - description: Latitude in degrees.
      required: [longitude, latitude]
      example:
        longitude: 36.616
        latitude: 55.752

    uuid:
      type: string
      format: uuid
      pattern: '^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$'
      example: "557d54ec-29ad-4f3c-93b4-c9092ef12515"

    callback_request:
      type: object
      properties:
        event_type:
          type: string
          enum: [crowd]
          description: Event type.
        account_id:
          type: string
          description: Account id of event.
        event_create_time:
          type: string
          description: Event creation time.
        event_end_time:
          type: string
          description: Event end time.
        event:
          type: object
          description: Event.
          properties:
            stream_id:
              allOf:
                - $ref: '#/components/schemas/uuid'
              description: Stream ID.
            event_id:
              allOf:
                - $ref: '#/components/schemas/uuid'
              description: Event ID.
            track_id:
              allOf:
                - $ref: '#/components/schemas/uuid'
              description: Track id.
              nullable: true
            people_count:
              type: integer
              minimum: 0
              description: People count on a frame.
            overview:
              type: object
              description: Event overview.
              properties:
                people_coordinates:
                  type: array
                  description: |
                    People coordinates estimation.
                    
                    Required analytic target `coordinates` to be enabled to send this value.
                  items:
                    type: array
                    items:
                      type: integer
                    minItems: 2
                    maxItems: 2
                    description: Human x, y coordinates.
                    example: [ 64, 128 ]
                  example: [ [ 64, 128 ], [ 491, 375 ] ]
                image:
                  type: string
                  description: |
                    Url of saved image.
                    
                    Required analytic target `overview` to be enabled to send this value.
                time_offset:
                  type: number
                  example: 1.234
                  description: Frame time offset (seconds).
            location:
              type: object
              properties:
                city:
                  allOf:
                    - $ref: '#/components/schemas/string36_nullable'
                  example: Moscow
                  description: City that stream belongs.
                area:
                  allOf:
                    - $ref: '#/components/schemas/string36_nullable'
                  example: Central
                  description: Area that stream belongs.
                district:
                  allOf:
                    - $ref: '#/components/schemas/string36_nullable'
                  example: Basmanny
                  description: District that stream belongs.
                street:
                  allOf:
                    - $ref: '#/components/schemas/string36_nullable'
                  example: Podsosensky lane
                  description: Street that stream belongs.
                house_number:
                  allOf:
                    - $ref: '#/components/schemas/string36_nullable'
                  example: 23 bldg.3
                  description: Street that stream belongs.
                geo_position:
                  $ref: '#/components/schemas/geo_position'
              description: |
                Stream location parameters.

                Required callback `location` target to send this value.
            video_segment:
              type: object
              description: Video segment.
              properties:
                start_time_offset:
                  type: number
                  example: 0.123
                  description: Event start video segment offset (seconds).
                end_time_offset:
                  type: number
                  example: 1.234
                  description: Event end video segment offset (seconds).
          required: [stream_id, event_id, people_count, video_segment, track_id]
      required: [event_type, event, account_id, event_create_time, event_end_time]
  responses:
    internal_server_error:
      description: internal server error.
      headers:
        Content-Type:
          $ref: '#/components/headers/application_json'
        Luna-Request-Id:
          $ref: '#/components/headers/luna_request_id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/error'
paths:
  /version:
    get:
      tags:
      - version

      summary: get version
      description: get service version
      operationId: getVersion

      parameters:
      - $ref: '#/components/parameters/luna_request_id'
      responses:
        200:
          description: OK
          headers:
            Content-Type:
              $ref: '#/components/headers/application_json'
            Luna-Request-Id:
              $ref: '#/components/headers/luna_request_id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/version'
        500:
          $ref: '#/components/responses/internal_server_error'
  /1/docs/spec:
    get:
      tags:
        - documents
      summary: get openapi documentation
      description: |
        Get service OpenApi documentation. If *Accept* request header is of type `application/x-yaml`,
        returns documentation in `yaml` format or returns `html` documentation, if *Accept-Type* is `text/html`
      operationId: getSpec

      parameters:
        - $ref: '#/components/parameters/luna_request_id'
        - $ref: '#/components/parameters/accept_docs_handler'
      responses:
        200:
          description: OK
          headers:
            Content-Type:
              $ref: '#/components/headers/docs_content_type'
            Luna-Request-Id:
              $ref: '#/components/headers/luna_request_id'
          content:
            application/x-yaml:
              schema:
                type: string
                description: yaml format documentation
            text/html:
              schema:
                type: string
                description: html format documentation
        415:
          description: Unsupported Media Type
          headers:
            Content-Type:
              $ref: '#/components/headers/application_json'
            Luna-Request-Id:
              $ref: '#/components/headers/luna_request_id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
              examples:
                unsupported_media_type:
                  value:
                    error_code: 12024
                    detail: 'Bad/incomplete input data'
                    desc: "Unsupported media type"
                    link: "https://docs.visionlabs.ai/info/luna/troubleshooting/errors-description/code-12024"
        500:
          $ref: '#/components/responses/internal_server_error'
  /1/docs/dev:
    parameters:
      - $ref: '#/components/parameters/Accept'
    get:
      tags:
        - documents
      summary: get development manual
      description: |
        Get sphinx documentation - *Development Manual*. After the request you will be redirected to the page `/docs/dev/index.html`
      operationId: getDevManual

      parameters:
        - $ref: '#/components/parameters/luna_request_id'
      responses:
        200:
          description: OK
          headers:
            Content-Type:
              $ref: '#/components/headers/text_html'
            Luna-Request-Id:
              $ref: '#/components/headers/luna_request_id'
          content:
            text/html:
              schema:
                type: string
                description: html format documentation
        500:
          $ref: '#/components/responses/internal_server_error'
  /1/config:
    get:
      tags:
        - config
      summary: get service configuration
      description: Get service configuration. Passwords and tokens will be hidden in the response.
      operationId: getConfig

      parameters:
        - $ref: '#/components/parameters/luna_request_id'
        - $ref: '#/components/parameters/accept_config_handler'
      responses:
        200:
          description: OK
          headers:
            Content-Type:
              $ref: '#/components/headers/config_accept_content_type'
            Luna-Request-Id:
              $ref: '#/components/headers/luna_request_id'
          content:
            application/json:
              schema:
                type: object
                description: json format configuration
              example:
                INFLUX_MONITORING:
                  SEND_DATA_FOR_MONITORING: 0
                  ORGANIZATION: ORGANIZATION_NAME
                  TOKEN: '********'
                  BUCKET: luna_monitoring
                  HOST: 127.0.0.1
                  PORT: 8086
                  USE_SSL: 0
                  FLUSHING_PERIOD: 1.0
            text/plain:
              schema:
                type: string
                description: text format configuration
              example: |
                [INFLUX_MONITORING]
                SEND_DATA_FOR_MONITORING = 0
                ORGANIZATION = ORGANIZATION_NAME
                TOKEN = ********
                BUCKET = luna_monitoring
                HOST = 127.0.0.1
                PORT = 8086
                USE_SSL = 0
                FLUSHING_PERIOD = 1.0
        415:
          description: Unsupported Media Type
          headers:
            Content-Type:
              $ref: '#/components/headers/application_json'
            Luna-Request-Id:
              $ref: '#/components/headers/luna_request_id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
              examples:
                unsupported_media_type:
                  value:
                    error_code: 12024
                    detail: 'Bad/incomplete input data'
                    desc: "Unsupported media type"
                    link: "https://docs.visionlabs.ai/info/luna/troubleshooting/errors-description/code-12024"
        500:
          $ref: '#/components/responses/internal_server_error'
  /1/plugins:
    get:
      tags:
        - plugins
      summary: get list of plugins
      description: |
        Get list of service plugins
      operationId: getPlugins
      parameters:
        - $ref: '#/components/parameters/luna_request_id'
      responses:
        200:
          description: OK.
          headers:
            Content-Type:
              $ref: '#/components/headers/application_json'
            Luna-Request-Id:
              $ref: '#/components/headers/luna_request_id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/plugins'
        500:
          $ref: '#/components/responses/internal_server_error'
  /healthcheck:
    get:
      tags:
      - health
      summary: get health
      description: get health of service
      operationId: healthcheck
      parameters:
        - $ref: '#/components/parameters/luna_request_id'
        - $ref: '#/components/parameters/include_luna_services'
      responses:
        200:
          description: OK
          headers:
            Content-Type:
              $ref: '#/components/headers/application_json'
            Luna-Request-Id:
              $ref: '#/components/headers/luna_request_id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/health_ok'
        500:
          $ref: '#/components/responses/internal_server_error'
        502:
          description: Unhealthy
          headers:
            Content-Type:
              $ref: '#/components/headers/application_json'
            Luna-Request-Id:
              $ref: '#/components/headers/luna_request_id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/health_errors'
