openapi: 3.0.1
info:
  version: 2.1.0
  title: Facephi Finger Service REST API
  description: |
    IMPORTANTE - CAMBIO INCOMPATIBLE (BREAKING CHANGE) (2.0.0)
    Esta versión de la API no es compatible con la 1.x.x.
    Los formatos de payload de petición y respuesta de las operaciones de huella dactilar cambiaron en la 2.0.0.

    API REST pública para la extracción de plantillas de huella dactilar, autenticación 1:1 y gestión del servicio.
    Para las entradas de huella dactilar basadas en imagen, los formatos admitidos son: wsq, bmp, png, jpg, jp2.
    La autenticación JWT opcional puede habilitarse al inicio desde la configuración o desde variables de entorno.

servers:
  - url: http://127.0.0.1:6982/

tags:
  - name: Finger Operations
    description: |
      IMPORTANTE - CAMBIO INCOMPATIBLE (BREAKING CHANGE) (2.0.0)
      Los endpoints de esta etiqueta utilizan el nuevo contrato público de payload 2.0.0.
  - name: Management
    description: Endpoints de salud, versión y configuración en tiempo de ejecución del servicio.

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key

  schemas:
    TimeStamp:
      type: string
      description: Fecha y hora en formato ISO-8601.
      example: "2026-04-20T10:42:05Z"

    MessageResult:
      type: object
      properties:
        message:
          type: string
          description: Mensaje del servicio.
      required:
        - message
      example:
        message: "Healthy"

    ConfigData:
      type: object
      description: Configuración actual de arranque/tiempo de ejecución expuesta por el endpoint de gestión. Los ajustes de autenticación JWT se omiten intencionadamente.
      properties:
        port:
          type: string
          example: "6982"
        number_of_threads:
          type: string
          example: "1"
        connection_timeout:
          type: string
          example: "0"
        keep_alive_request_number:
          type: string
          example: "0"
        client_max_body_size:
          type: string
          description: Tamaño máximo del cuerpo de la petición en MB.
          example: "100"
        logger_path:
          type: string
          example: ""
        logger_level:
          type: string
          example: "info"
        logger_rotation:
          type: string
          example: "daily"
        logger_max_files:
          type: string
          example: "7"

    ConfigUpdateRequest:
      type: object
      required:
        - config_json_string
      properties:
        config_json_string:
          type: string
          description: Configuración completa en tiempo de ejecución serializada como cadena JSON. Este endpoint no acepta ajustes de autenticación JWT.
          example: '{"port":6982,"number_of_threads":1}'

    PublicOptions:
      type: object
      description: Parámetros de ajuste opcionales para las operaciones de extract y authenticate.
      properties:
        dpi:
          type: integer
          minimum: 250
          maximum: 1000
          default: 500
          example: 500
        scanType:
          type: string
          enum:
            - Plain
            - Rolled
            - Latent
          default: Plain
          example: Plain
        includeQuality:
          type: boolean
          default: true
          example: true
        authThreshold:
          type: integer
          description: Umbral de autenticación como número entero entre 0 y 100.
          minimum: 0
          maximum: 100
          default: 20
          example: 20

    ExtractRequest:
      type: object
      required:
        - image
        - position
      properties:
        image:
          type: string
          description: Imagen de huella dactilar codificada en Base64. Formatos admitidos; wsq, bmp, png, jpg, jp2.
          example: "<base64_image>"
        position:
          type: string
          description: Nombre público de la posición del dedo.
          enum:
            - RightThumb
            - RightIndex
            - RightMiddle
            - RightRing
            - RightLittle
            - LeftThumb
            - LeftIndex
            - LeftMiddle
            - LeftRing
            - LeftLittle
          example: RightIndex
        options:
          $ref: '#/components/schemas/PublicOptions'
      example:
        image: "<base64_image>"
        position: RightIndex
        options:
          dpi: 500
          scanType: Plain
          includeQuality: true

    QualityDetails:
      type: object
      properties:
        nfiq2:
          type: number
          format: float
          example: 79.0
        nfiq:
          type: number
          format: float
          example: 1.0
        score:
          type: number
          format: float
          example: 88.0

    ExtractResponse:
      type: object
      description: Respuesta pública de extract.
      required:
        - fingerTemplate
        - position
        - scanType
        - sdkDuration
        - queueDuration
      properties:
        fingerTemplate:
          type: string
          description: Plantilla generada, codificada en Base64.
          example: "<base64_template>"
        position:
          type: string
          enum:
            - RightThumb
            - RightIndex
            - RightMiddle
            - RightRing
            - RightLittle
            - LeftThumb
            - LeftIndex
            - LeftMiddle
            - LeftRing
            - LeftLittle
          example: RightIndex
        scanType:
          type: string
          enum:
            - Plain
            - Rolled
            - Latent
          example: Plain
        quality:
          type: integer
          description: Puntuación de calidad global (0-100), cuando está disponible.
          example: 88
        qualityDetails:
          $ref: '#/components/schemas/QualityDetails'
        sdkDuration:
          type: integer
          format: int64
          description: Tiempo de ejecución del SDK en milisegundos.
          example: 123
        queueDuration:
          type: integer
          format: int64
          description: Tiempo de espera en cola en milisegundos.
          example: 2
      example:
        fingerTemplate: "<base64_template>"
        position: RightIndex
        scanType: Plain
        quality: 88
        qualityDetails:
          nfiq2: 79.0
          nfiq: 1.0
          score: 88.0
        sdkDuration: 123
        queueDuration: 2

    AuthenticateRequest:
      type: object
      description: |
        Petición pública de autenticación 1:1.
        Se requiere exactamente un origen por lado:
        - Lado 1: image1 o fingerTemplate1
        - Lado 2: image2 o fingerTemplate2
        La posición puede indicarse como `position` compartida o mediante `position1` y `position2` específicas de cada lado.
      properties:
        image1:
          type: string
          description: Imagen de huella dactilar de referencia (probe), codificada en Base64. Formatos admitidos; wsq, bmp, png, jpg, jp2.
        image2:
          type: string
          description: Imagen de huella dactilar de galería, codificada en Base64. Formatos admitidos; wsq, bmp, png, jpg, jp2.
        fingerTemplate1:
          type: string
          description: Plantilla de huella dactilar de referencia (probe), codificada en Base64.
        fingerTemplate2:
          type: string
          description: Plantilla de huella dactilar de galería, codificada en Base64.
        position:
          type: string
          description: Posición pública compartida del dedo, usada cuando no se indican posiciones específicas por lado.
          enum:
            - RightThumb
            - RightIndex
            - RightMiddle
            - RightRing
            - RightLittle
            - LeftThumb
            - LeftIndex
            - LeftMiddle
            - LeftRing
            - LeftLittle
        position1:
          type: string
          description: Sobrescritura opcional de la posición del dedo de referencia (probe).
          enum:
            - RightThumb
            - RightIndex
            - RightMiddle
            - RightRing
            - RightLittle
            - LeftThumb
            - LeftIndex
            - LeftMiddle
            - LeftRing
            - LeftLittle
        position2:
          type: string
          description: Sobrescritura opcional de la posición del dedo de galería.
          enum:
            - RightThumb
            - RightIndex
            - RightMiddle
            - RightRing
            - RightLittle
            - LeftThumb
            - LeftIndex
            - LeftMiddle
            - LeftRing
            - LeftLittle
        options:
          $ref: '#/components/schemas/PublicOptions'
      example:
        fingerTemplate1: "<base64_probe_template>"
        fingerTemplate2: "<base64_gallery_template>"
        position: RightIndex
        options:
          authThreshold: 20

    AuthenticateResponse:
      type: object
      description: Respuesta pública de autenticación 1:1.
      required:
        - authStatus
        - similarity
        - sdkDuration
        - queueDuration
      properties:
        authStatus:
          type: string
          enum:
            - Positive
            - Negative
          example: Positive
        similarity:
          type: number
          format: float
          description: Puntuación de similitud en el rango 0-100.
          example: 84.65
        sdkDuration:
          type: integer
          format: int64
          description: Tiempo de ejecución del SDK en milisegundos.
          example: 131
        queueDuration:
          type: integer
          format: int64
          description: Tiempo de espera en cola en milisegundos.
          example: 1
      example:
        authStatus: Positive
        similarity: 84.65
        sdkDuration: 131
        queueDuration: 1

    UsageMetricsResponse:
      type: object
      description: Informe de contadores de uso de los endpoints de operaciones de huella dactilar.
      required:
        - usageCountersEnabled
        - extractCount
        - authenticateCount
        - totalCount
      properties:
        usageCountersEnabled:
          type: boolean
          description: Indica si los contadores de uso están habilitados mediante metadatos de licencia.
          example: true
        extractCount:
          type: integer
          format: int64
          minimum: 0
          description: Valor del contador de la operación extract.
          example: 12
        authenticateCount:
          type: integer
          format: int64
          minimum: 0
          description: Valor del contador de la operación authenticate.
          example: 7
        totalCount:
          type: integer
          format: int64
          minimum: 0
          description: Suma de extractCount y authenticateCount.
          example: 19
      example:
        usageCountersEnabled: true
        extractCount: 12
        authenticateCount: 7
        totalCount: 19

    BadRequestResult:
      type: object
      properties:
        status:
          type: integer
          example: 400
        error:
          type: string
          example: "BadRequest"
        message:
          type: string
          example: "Finger template creation failed"
        timeStamp:
          $ref: '#/components/schemas/TimeStamp'
      required:
        - status
        - error
        - message
        - timeStamp

    ExceptionResult:
      type: object
      properties:
        status:
          type: integer
          example: 500
        error:
          type: string
          example: "Backend Exception"
        message:
          type: string
          example: "Unexpected error while processing request"
        exception:
          type: string
          example: "RuntimeError: unexpected failure"
        timeStamp:
          $ref: '#/components/schemas/TimeStamp'
      required:
        - status
        - error
        - message
        - exception
        - timeStamp

security:
  - BearerAuth: []
  - ApiKeyAuth: []

paths:
  /api/v1/finger/version:
    get:
      summary: Obtener la versión del servicio
      description: Devuelve la versión del servicio y el mensaje de estado de la licencia.
      operationId: getVersion
      security: []
      tags:
        - Management
      responses:
        '200':
          description: Información de versión.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResult'
        '400':
          description: El servicio no está inicializado.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BadRequestResult'

  /api/v1/finger/health:
    get:
      summary: Comprobación de salud
      description: Devuelve el estado de salud y disponibilidad del servicio.
      operationId: getHealth
      security: []
      tags:
        - Management
      responses:
        '200':
          description: Mensaje de salud del servicio.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResult'
        '400':
          description: El servicio o los componentes de procesamiento requeridos no están saludables.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BadRequestResult'

  /api/v1/finger/metrics:
    get:
      summary: Obtener métricas de uso
      description: Devuelve los valores de los contadores de uso de los endpoints públicos de operaciones de huella dactilar.
      operationId: getMetrics
      tags:
        - Management
      responses:
        '200':
          description: Respuesta de métricas de uso.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UsageMetricsResponse'
        '400':
          description: El servicio no está inicializado.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BadRequestResult'

  /api/v1/finger/config:
    get:
      summary: Obtener la configuración en tiempo de ejecución
      description: Devuelve la configuración actual en memoria cargada por el servicio.
      operationId: getConfig
      tags:
        - Management
      responses:
        '200':
          description: Configuración actual.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConfigData'
        '400':
          description: Configuración inválida o no disponible.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BadRequestResult'
    post:
      summary: Actualizar la configuración en tiempo de ejecución
      description: Aplica una nueva configuración en tiempo de ejecución a partir de un payload en cadena JSON. Los ajustes de autenticación JWT requieren un reinicio para aplicarse.
      operationId: updateConfig
      tags:
        - Management
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConfigUpdateRequest'
      responses:
        '200':
          description: Configuración actualizada correctamente.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResult'
        '400':
          description: Petición o payload de configuración inválidos.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BadRequestResult'
        '500':
          description: Fallo inesperado al aplicar la configuración.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExceptionResult'

  /api/v1/finger/extract:
    post:
      summary: Extraer plantilla de huella dactilar
      description: |
        IMPORTANTE - CAMBIO INCOMPATIBLE (BREAKING CHANGE) (2.0.0)
        Este endpoint no es compatible con la versión 1.x.x.
        La versión 2.0.0 utiliza el contrato público (`image`, `position`, `options`) y devuelve
        campos públicos (`fingerTemplate`, `quality`, `qualityDetails`, `sdkDuration`, `queueDuration`).
        Formatos de imagen de entrada admitidos para `image`: wsq, bmp, png, jpg, jp2.
      operationId: extract
      tags:
        - Finger Operations
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExtractRequest'
      responses:
        '200':
          description: Respuesta pública de extract.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExtractResponse'
        '400':
          description: Payload inválido o fallo en el procesamiento subyacente.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BadRequestResult'
        '500':
          description: Error inesperado del servicio.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExceptionResult'

  /api/v1/finger/authenticate:
    post:
      summary: Autenticar huellas dactilares (1:1)
      description: |
        IMPORTANTE - CAMBIO INCOMPATIBLE (BREAKING CHANGE) (2.0.0)
        Este endpoint no es compatible con la versión 1.x.x.
        La versión 2.0.0 acepta imágenes/plantillas mediante campos públicos y devuelve
        los campos públicos `authStatus` y `similarity`.
        Formatos de imagen de entrada admitidos para `image1` e `image2`: wsq, bmp, png, jpg, jp2.
      operationId: authenticate
      tags:
        - Finger Operations
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AuthenticateRequest'
      responses:
        '200':
          description: Respuesta pública de autenticación.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthenticateResponse'
        '400':
          description: Payload inválido o fallo en el procesamiento subyacente.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BadRequestResult'
        '500':
          description: Error inesperado del servicio.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExceptionResult'
