openapi: 3.1.0
info:
  version: v.0.4.0
  title: Luna Vinder Matcher API
  description: Index projection matching service.
paths:
  /1/matcher:
    parameters:
      - $ref: '#/components/parameters/luna_request_id'
    post:
      tags:
        - matcher
      summary: object matching
      description: Perform matching request across indexed collection
      operationId: matcher
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/matching_request'
      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/matching_response'
        '400':
          description: Bad request
          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:
                object_type:
                  value:
                    error_code: 12022
                    desc: Bad/incomplete input data
                    detail: 'Failed to validate input json. Path: ''candidate.origin'',  message: ''origin must be one of [''events'']'
                    link: https://docs.visionlabs.ai/info/luna/troubleshooting/errors-description/code-12022
        '403':
          $ref: '#/components/responses/forbidden_error'
        '409':
          description: Conflict
          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:
                projection_conflict:
                  value:
                    error_code: 49001
                    desc: Object not found
                    detail: Projection with id 4c845b9c-5a8d-4e65-b5fd-bdb12b994ce1 not loaded
                    link: https://docs.visionlabs.ai/info/luna/troubleshooting/errors-description/code-49001
                index_conflict:
                  value:
                    error_code: 49002
                    desc: Object not found
                    detail: For projection with id 4c845b9c-5a8d-4e65-b5fd-bdb12b994ce1 no suitable index built for request filters
                    link: https://docs.visionlabs.ai/info/luna/troubleshooting/errors-description/code-49002
        '500':
          $ref: '#/components/responses/internal_server_error'
        '504':
          $ref: '#/components/responses/server_timeout_error'
  /1/projections:
    parameters:
      - $ref: '#/components/parameters/luna_request_id'
    get:
      tags:
        - projections
      summary: get projections info
      description: Get info on all the projections & indexes available to search by
      operationId: getProjections
      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:
                type: object
                properties:
                  projections:
                    type: array
                    items:
                      $ref: '#/components/schemas/projection'
                required:
                  - projections
        '500':
          $ref: '#/components/responses/internal_server_error'
        '504':
          $ref: '#/components/responses/server_timeout_error'
  /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'
        - name: Accept
          in: header
          schema:
            type: string
            enum:
              - application/x-yaml
              - text/html
            description: One of application/x-yaml, text/html
          required: true
          description: acceptable type of receiving data
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                enum:
                  - application/x-yaml
                  - text/html
              required: true
              description: The content type of the response body.
            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:
    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'
        - name: Accept
          in: header
          schema:
            type: string
            enum:
              - application/json
              - text/plain
            description: One of application/json, text/plain
          required: false
          description: acceptable type of receiving data
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              description: The content type of the response body.
              schema:
                type: string
                enum:
                  - application/json
                  - text/plain
              required: true
            Luna-Request-Id:
              $ref: '#/components/headers/luna_request_id'
          content:
            application/json:
              schema:
                type: object
                description: json format configuration
                additionalProperties: true
              example:
                INFLUX_MONITORING:
                  SEND_DATA_FOR_MONITORING: 0
                  VERSION: 2
                  ORGANIZATION: ORGANIZATION_NAME
                  TOKEN: '********'
                  BUCKET: luna_monitoring
                  HOST: 127.0.0.1
                  PORT: 8086
                  USE_SSL: 0
                  FLUSHING_PERIOD: 1
            text/plain:
              schema:
                type: string
                description: text format configuration
              example: |
                [INFLUX_MONITORING]
                SEND_DATA_FOR_MONITORING = 0
                VERSION = 2
                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'
  /healthcheck:
    get:
      tags:
        - health
      summary: get health
      description: get health of service
      operationId: healthcheck
      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:
                description: Successful healthcheck execution info.
                type: object
                properties:
                  execution_time:
                    type: number
                    example: 0.123
                    description: Request execution time in seconds.
                required:
                  - execution_time
        '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:
                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: redis
                      error:
                        error_code: 0
                        desc: Success
                        detail: Success
                        link: https://docs.visionlabs.ai/info/luna/troubleshooting/errors-description/code-0
                      status: 0
  /metrics:
    get:
      tags:
        - metrics
      summary: get service requests statistics
      description: Get statistics of success and failed requests to the service in prometheus format.
      operationId: metrics
      parameters:
        - $ref: '#/components/parameters/luna_request_id'
      responses:
        '200':
          description: OK.
          headers:
            Content-Type:
              schema:
                type: string
                enum:
                  - text/plain; charset=UTF-8
              required: true
              description: Content type is `text/plain`.
            Luna-Request-Id:
              $ref: '#/components/headers/parameters_luna_request_id'
          content:
            text/plain:
              schema:
                type: string
                description: Prometheus plain text format.
              example: |
                # HELP request_count_total Counter of requests
                # TYPE request_count_total counter
                request_count_total{path="GET:/healthcheck",status_code="200"} 1.0
        '403':
          $ref: '#/components/responses/forbidden_resource_error'
        '500':
          $ref: '#/components/responses/internal_server_error'
components:
  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: request identifier.
      name: Luna-Request-Id
  schemas:
    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
    raw_reference:
      type: object
      properties:
        type:
          enum:
            - raw_descriptor
          description: Reference type.
        data:
          type: object
          description: Descriptor and its version.
          properties:
            descriptor:
              type: string
              format: byte
              description: Raw descriptor encoded.
            version:
              type: integer
              description: Descriptor version.
          required:
            - descriptor
            - version
      required:
        - type
        - data
      description: Raw descriptor.
    sdk_reference:
      type: object
      properties:
        type:
          enum:
            - sdk_descriptor
          description: Reference type.
        data:
          type: string
          format: byte
          description: SDK descriptor encoded (The descriptor version, a signature and descriptor).
      required:
        - type
        - data
      description: SDK descriptor.
    any:
      anyOf:
        - type: string
        - type: number
        - type: boolean
        - type: array
          items:
            anyOf:
              - type: string
              - type: number
              - type: boolean
        - type: object
    candidate:
      type: object
      properties:
        origin:
          enum:
            - events
          description: Search origin.
        filters:
          type: array
          description: |
            Search filters.

            Allowed usage of operator is:

            | Operator | Value |       |        |       |
            |----------|-------|-------|--------|-------|
            |          | int   | float | string | array |
            | eq       | +     | +     | +      | +     |
            | neq      | +     | +     | +      | +     |
            | in       | -     | -     | -      | +     |
            | nin      | -     | -     | -      | +     |
            | like     | -     | -     | +      | -     |
            | nlike    | -     | -     | +      | -     |
            | gt       | +     | +     | +      | -     |
            | gte      | +     | +     | +      | -     |
            | lt       | +     | +     | +      | -     |
            | lte      | +     | +     | +      | -     |
          items:
            type: object
            properties:
              path:
                type: string
                enum:
                  - create_time
                  - account_id
                  - handler_id
                  - event_id
                  - face_id
                  - external_id
                  - source
                  - user_data
                  - stream_id
                  - track_id
                  - gender
                  - age
                  - emotion
                  - mask
                  - ethnic_group
                  - liveness
                  - deepfake
                  - tags
                  - location.city
                  - location.area
                  - location.district
                  - location.street
                  - location.house_number
                  - top_match.event_id
                  - top_match.face_id
                  - top_match.external_id
                  - top_match.label
                  - top_match.similarity
                  - body_basic_attributes.apparent_age
                  - body_basic_attributes.apparent_gender
                  - upper_body.headwear.state
                  - upper_body.headwear.apparent_color
                  - upper_body.sleeve.length
                  - lower_body.lower_garment.type
                  - lower_body.shoes.apparent_color
                  - accessories.backpack.state
                description: Filter field path. To navigate through nested objects the dot (.) is used.
                example: source
              op:
                type: string
                enum:
                  - eq
                  - neq
                  - like
                  - nlike
                  - in
                  - nin
                  - gt
                  - gte
                  - lt
                  - lte
                description: Filter operator.
                example: eq
              value:
                allOf:
                  - $ref: '#/components/schemas/any'
                description: Filter value.
                example: moscow
        limit:
          type: integer
          minimum: 1
          default: 3
          maximum: 100
          description: Maximum number of search results.
        threshold:
          type: number
          minimum: 0
          maximum: 1
          default: 0
          description: Search similarity threshold.
      required:
        - origin
        - filters
      example:
        origin: events
        filters:
          - path: source
            op: eq
            value: moscow
        limit: 3
        threshold: 0
    matching_request:
      type: object
      description: Matching request.
      properties:
        projection_id:
          allOf:
            - $ref: '#/components/schemas/uuid'
          description: Projection ID.
        reference:
          oneOf:
            - $ref: '#/components/schemas/raw_reference'
            - $ref: '#/components/schemas/sdk_reference'
          discriminator:
            propertyName: type
            mapping:
              raw_descriptor: '#/components/schemas/raw_reference'
              sdk_descriptor: '#/components/schemas/sdk_reference'
          description: Matching reference.
        candidate:
          $ref: '#/components/schemas/candidate'
      required:
        - projection_id
        - reference
        - candidate
    matching_response:
      type: object
      description: Matching response.
      properties:
        result:
          type: array
          description: Matching candidate.
          items:
            type: object
            properties:
              payload:
                type: object
                additionalProperties: true
                description: Candidate payload.
              similarity:
                type: number
                minimum: 0
                maximum: 1
                description: Candidate similarity.
            required:
              - payload
              - similarity
      required:
        - result
      example:
        result:
          - payload:
              age: 35
              source: moscow
              create_time: '2025-08-13T11:36:41.674Z'
            similarity: 0.99
          - payload:
              age: 37
              source: moscow
              create_time: '2025-09-23T04:14:45.324Z'
            similarity: 0.88
    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
    projection:
      type: object
      description: Projection info.
      properties:
        projection_id:
          allOf:
            - $ref: '#/components/schemas/uuid'
          description: Projection ID.
        indexes:
          type: array
          items:
            type: array
            items:
              type: string
              description: Index composite field.
              example: age
            description: Collection of index composite fields.
            example:
              - gender
              - age
          description: |
            Projection indexes in the form: `[[<field1>, <field2>], [<field3>, <field4>]]`.
      required:
        - projection_id
        - indexes
      example:
        projection_id: 157342d0-6f7e-4d62-ba56-4362b43201f7
        indexes:
          - - source
            - age
          - - user_data
            - external_id
    int_version:
      type: integer
      minimum: 0
    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
  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
    text_html:
      schema:
        type: string
        enum:
          - text/html
      required: true
      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: request identifier.
      name: Luna-Request-Id
  responses:
    forbidden_error:
      description: Forbidden
      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:
            events_disabled:
              value:
                error_code: 11040
                desc: Forbidden
                detail: Luna Events service is disabled
                link: https://docs.visionlabs.ai/info/luna/troubleshooting/errors-description/code-11040
    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'
    server_timeout_error:
      description: server timeout error.
      headers:
        Content-Type:
          $ref: '#/components/headers/application_json'
        Luna-Request-Id:
          $ref: '#/components/headers/luna_request_id'
      content:
        application/json:
          schema:
            allOf:
              - $ref: '#/components/schemas/error'
            example:
              error_code: 9
              detail: Request timeout
              desc: Request timeout on http://127.0.0.1:5100/{...}, method {...}
              link: https://docs.visionlabs.ai/info/luna/troubleshooting/errors-description/code-9
    forbidden_resource_error:
      description: Forbidden.
      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:
            resource_is_disabled:
              value:
                error_code: 12049
                desc: Forbidden
                detail: Resource is disabled.
                link: https://docs.visionlabs.ai/info/luna/troubleshooting/errors-description/code-12049
x-tagGroups:
  - name: Matching
    tags:
      - matcher
  - name: Projections
    tags:
      - projections
  - name: Sys
    tags:
      - documents
      - config
      - metrics
      - health
      - version
