openapi: 3.0.0
info:
  title: Mount Management API
  description: API for managing mounts and associated entities
  version: 1.0.0
servers:
  - url: http://localhost:3000/dev/api/v1
  - url: https://api.dev.obh-mobility.com:3000/dev/api/v1
  - url: https://api.staging.obh-mobility.com:3000/dev/api/v1
tags:
  - name: Accounts
  - name: Mounts
  - name: Firmware
paths:
  /accounts/me:
    get:
      operationId: getAccountDetails
      summary: Get Account Details
      description: |
        This operation will return the details of the account.
        The account is found by the token provided in the header.
      responses:
        '200':
          description: Account details retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Account'
      security:
        - ApiKeyAuth: []
      tags:
        - Accounts
  /mounts:
    get:
      operationId: getOwnedMounts
      summary: Get owned mounts
      description: |
        This operation will return a list of all mounts owned by the account.
        The list can be filtered by serial number, macAddress and mount UID. 
        The filters are case insensitive, and are linked by an AND operator.
      parameters:
        - name: currentPage
          in: query
          description: Page number of the mounts listing. Starts at 1.
          required: false
          schema:
            type: integer
            default: 1
        - name: pageSize
          in: query
          description: Number of mounts per page
          required: false
          schema:
            type: integer
            default: 10
        - name: serialNumber
          in: query
          description: Filter mounts by serial number
          required: false
          schema:
            type: string
        - name: macAddress
          in: query
          description: Filter mounts by mac address
          required: false
          schema:
            type: string
        - name: mountUid
          in: query
          description: Filter mounts by UID
          required: false
          schema:
            type: string
      responses:
        '200':
          description: List of all mounts with pagination
          content:
            application/json:
              schema:
                type: object
                properties:
                  mounts:
                    type: array
                    items:
                      $ref: '#/components/schemas/Mount'
                  pagination:
                    type: object
                    properties:
                      currentPage:
                        type: integer
                      pageSize:
                        type: integer
                      totalItems:
                        type: integer
                      totalPages:
                        type: integer
      security:
        - ApiKeyAuth: []
      tags:
        - Mounts
    post:
      operationId: associateMount
      summary: Request mount association
      description: >
        This operation will request the association of a mount to the account.

        If the mount is not in a INACTIVE state, it has to be owned by the
        account, otherwise the request will be rejected.

        After this request is successful, the mount will be in a IDLE state,
        unless it's already associated.

        Once in IDLE, the association has to be confirmed within 10 minutes.

        Doing this request while being already the owner allows you to refresh
        the public key in the mount.

        If the mount doesn't exist, it will be created, otherwise it will be
        updated based on the uid.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                uid:
                  type: string
                serialNumber:
                  type: string
                macAddress:
                  type: string
                firmwareRevision:
                  type: string
                softwareRevision:
                  type: string
                modelNumber:
                  type: string
                name:
                  type: string
              required:
                - uid
                - serialNumber
                - macAddress
                - firmwareRevision
                - softwareRevision
                - modelNumber
      responses:
        '200':
          description: >-
            Mount association ready. You need to confirm the association after
            the mount has accepted it.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Query'
      security:
        - ApiKeyAuth: []
      tags:
        - Mounts
  /mounts/{uid}/confirm-association:
    post:
      operationId: confirmMountAssociation
      summary: Confirm the mount has accepted the association
      description: >
        This operation will confirm the mount has accepted the association.

        The mount has to be in a IDLE state to be confirmed.

        The account needs to be the owner of the mount to confirm the
        association.
      parameters:
        - name: uid
          in: path
          required: true
          schema:
            type: string
      responses:
        '204':
          description: Mount associated successfully
      security:
        - ApiKeyAuth: []
      tags:
        - Mounts
  /mounts/{uid}:
    get:
      operationId: getMountById
      summary: Get mount data by uid
      description: |
        This operation will return the details of the mount with the given UID.
        The account needs to be the owner of the mount to retrieve its details.
      parameters:
        - name: uid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Mount details retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Mount'
      security:
        - ApiKeyAuth: []
      tags:
        - Mounts
    patch:
      operationId: updateMountById
      summary: Update mount data by uid
      description: |
        This operation will update the details of the mount with the given UID.
        The account needs to be the owner of the mount to update its details.
      parameters:
        - name: uid
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: Human readable name of the mount
                softwareRevision:
                  type: string
      responses:
        '200':
          description: Mount details updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Mount'
      security:
        - ApiKeyAuth: []
      tags:
        - Mounts
    delete:
      operationId: dissociateMountById
      summary: Dissociate mount from the account
      description: >
        This operation will dissociate the mount from the account. The mount
        will be available for association with another account.

        The mount needs to be in an ASSOCIATED state to be dissociated and the
        account needs to be the owner of the mount.
      parameters:
        - name: uid
          in: path
          required: true
          schema:
            type: string
      responses:
        '204':
          description: Mount dissociated successfully
      security:
        - ApiKeyAuth: []
      tags:
        - Mounts
  /mounts/{uid}/states:
    post:
      operationId: createMountState
      summary: Record a new state for the mount
      description: |
        This operation will record a new state for the mount.\n
        The state will be recorded with the date and time of the occurrence.
        You may passe one or more states at once.
      parameters:
        - name: uid
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                states:
                  type: array
                  items:
                    $ref: '#/components/schemas/CreateMountState'
      responses:
        '201':
          description: Mount states saved successfully
      security:
        - ApiKeyAuth: []
      tags:
        - Mounts
  /mounts/{uid}/query:
    get:
      operationId: queryMount
      summary: Request a signed query to send to the mount
      description: >
        This operation will request a signed query to send to the mount.

        The query will be signed with the account's private key and will be used
        to send commands to the mount.

        Note: You cannot generate a query to ASSOCIATE_OWNER with this endpoint,
        use the POST /mounts endpoint instead.
      parameters:
        - name: uid
          in: path
          required: true
          schema:
            type: string
        - name: code
          in: query
          required: true
          schema:
            type: string
        - name: tagUid
          description: Required when using REMOVE_TAG
          in: query
          required: false
          schema:
            type: string
        - name: rfidMode
          description: Required when using SET_RFID_MODE
          in: query
          required: false
          schema:
            type: string
            enum:
              - NORMAL
              - LEARNING
        - name: alarmSensitivity
          description: Required when using SET_ALARM_SENSITIVITY
          in: query
          required: false
          schema:
            type: string
            enum:
              - HIGH
              - AVERAGE
              - LOW
        - name: alarmVolume
          description: Required when using SET_ALARM_VOLUME
          in: query
          required: false
          schema:
            type: string
            enum:
              - HIGH
              - NORMAL
              - LOW
        - name: alarmMode
          description: Required when using SET_ALARM_MODE
          in: query
          required: false
          schema:
            type: string
            enum:
              - 'OFF'
              - AUTO
      responses:
        '200':
          description: Query executed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Query'
      security:
        - ApiKeyAuth: []
      tags:
        - Mounts
  /mounts/{uid}/abandon:
    delete:
      operationId: abandonMount
      summary: Abandon a mount
      description: >
        This operation will abandon the mount, making it available for
        association with another account.

        The account needs to be the owner of the mount to abandon it.
      parameters:
        - name: uid
          in: path
          required: true
          schema:
            type: string
      responses:
        '204':
          description: Mount abandoned successfully
      security:
        - ApiKeyAuth: []
      tags:
        - Mounts
  /nfc-tags:
    get:
      operationId: getNfcTags
      summary: Get NFC tags
      description: |
        This operation will return a list of all NFC tags.
      parameters:
        - name: currentPage
          in: query
          description: Page number of the NFC tags listing. Starts at 1.
          required: false
          schema:
            type: integer
            default: 1
        - name: pageSize
          in: query
          description: Number of NFC tags per page
          required: false
          schema:
            type: integer
            default: 20
      responses:
        '200':
          description: List of all NFC tags with pagination
          content:
            application/json:
              schema:
                type: object
                properties:
                  tags:
                    type: array
                    items:
                      $ref: '#/components/schemas/NfcTag'
                  pagination:
                    type: object
                    properties:
                      currentPage:
                        type: integer
                      pageSize:
                        type: integer
                      totalItems:
                        type: integer
                      totalPages:
                        type: integer
      security:
        - ApiKeyAuth: []
      tags:
        - NfcTags
    post:
      operationId: syncNfcTags
      summary: Synchronize NFC tags
      description: |
        This operation will synchronize NFC tags with the given mount.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                tagUids:
                  type: array
                  items:
                    type: string
                mountUid:
                  type: string
              required:
                - tagUids
                - mountUid
      responses:
        '200':
          description: NFC tags synchronized successfully
      security:
        - ApiKeyAuth: []
      tags:
        - NfcTags
  /nfc-tags/{uid}:
    patch:
      operationId: updateNfcTag
      summary: Update an NFC tag
      description: >
        This operation will update the details of the NFC tag with the given
        UID.
      parameters:
        - name: uid
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: Human readable name of the NFC tag
                color:
                  type: string
                  description: color of the NFC tag
                iconName:
                  type: string
                  description: Icon name of the NFC tag
      responses:
        '200':
          description: NFC tag updated successfully
      security:
        - ApiKeyAuth: []
      tags:
        - NfcTags
  /firmware/versions:
    get:
      operationId: getFirmwareVersions
      summary: Get all available firmware versions
      description: |
        This operation will return a list of all firmware versions available.
        Versions are sorted by the availableSince date in descending order.
      parameters:
        - name: currentPage
          in: query
          description: Page number. Starts at 1.
          required: false
          schema:
            type: integer
            default: 1
        - name: pageSize
          in: query
          description: Number of elements per page
          required: false
          schema:
            type: integer
            default: 10
      responses:
        '200':
          description: List of all firmware versions
          content:
            application/json:
              schema:
                type: object
                properties:
                  versions:
                    type: array
                    items:
                      $ref: '#/components/schemas/FirmwareVersion'
                  pagination:
                    type: object
                    properties:
                      currentPage:
                        type: integer
                      pageSize:
                        type: integer
                      totalItems:
                        type: integer
                      totalPages:
                        type: integer
      security:
        - ApiKeyAuth: []
      tags:
        - Firmware
  /firmware/check-update:
    get:
      operationId: checkFirmwareUpdate
      summary: Check if a firmware update is available
      description: >
        This operation will check if a firmware update is available for the
        given version.
      parameters:
        - name: softwareRevision
          in: query
          required: false
          schema:
            type: string
        - name: modelNumber
          in: query
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Firmware update check successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FirmwareUpdateCheckResult'
      security:
        - ApiKeyAuth: []
      tags:
        - Firmware
  /firmware/download:
    get:
      operationId: downloadFirmware
      summary: Download a specific firmware version
      description: >
        This operation will return a binary file of the specified firmware
        version.

        If no version is given, the latest version will be downloaded.
      parameters:
        - name: softwareRevision
          in: query
          required: false
          schema:
            type: string
        - name: modelNumber
          in: query
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Firmware download link
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FirmwareDownloadLink'
      security:
        - ApiKeyAuth: []
      tags:
        - Firmware
components:
  schemas:
    Query:
      description: >
        Response for a signed query to send to the mount. The payload and
        signedToken are base64 encoded as it contains binary data that may be
        incompatible with JSON.
      type: object
      properties:
        code:
          type: string
          enum:
            - ASSOCIATE_OWNER
            - DISSOCIATE_OWNER
            - RELEASE_HELMET
            - READ_TAG
            - SET_RFID_MODE
            - REMOVE_TAG
            - SET_ALARM_SENSITIVITY
            - SET_ALARM_VOLUME
            - SET_ALARM_MODE
        data:
          type: object
          description: Human readable data to send to the mount
        generatedAt:
          type: string
          format: date-time
        payload:
          type: string
          format: date-time
          description: Payload to send to the mount
        signedToken:
          type: string
          description: Signature of the query
          format: 32 bytes
      example:
        - code: ASSOCIATE_OWNER
          data:
            accountUid: b2413500-8106-4530-b7dc-91ebe3b6236
            publicKey: 605A2F4C21C7D560D3C5DCDB1581B2B8
          generatedAt: '2023-12-12T17:24:43.000Z'
          payload: >-
            2023-12-12T17:24:43.000Zb2413500-8106-4530-b7dc-91ebe3b6236605A2F4C21C7D560D3C5DCDB1581B2B8
          signedToken: null
        - code: RELEASE_HELMET
          data:
            releaseHelmet: 1
          generatedAt: '2023-12-12T17:24:43.000Z'
          payload: >-
            12023-12-12T17:24:43.000Z28C6A9258EC9579187175AD6FE4FD55B929F0BFC9F008FEBE082D64474B5DE9E2FC2B51EA207
          signedToken: >-
            28C6A9258EC9579187175AD6FE4FD55B929F0BFC9F008FEBE082D64474B5DE9E2FC2B51EA207
    Account:
      type: object
      properties:
        uid:
          type: string
          description: Unique identifier of the account
        name:
          type: string
          description: Human readable name of the account
        createdAt:
          type: string
          format: date-time
          description: Date and time of the account creation
    CreateMountState:
      type: object
      properties:
        code:
          type: string
          description: Code of the state
          enum:
            - HELMET_MOUNTED
            - BATTERY_LEVEL
            - CPU_TEMPERATURE
            - MOUNT_LOCKED
            - ALARM_STATE
            - ALARM_MODE
            - ALARM_SENSITIVITY
            - ALARM_VOLUME
        value:
          type: string
          description: Value of the state
        occurredAt:
          type: string
          format: date-time
          description: Date and time the state was recorded at
      example:
        - code: BATTERY_LEVEL
          value: '82'
          occurredAt: '2023-12-12T17:24:43.000Z'
        - code: CPU_TEMPERATURE
          value: '45.5'
          occurredAt: '2023-12-12T17:24:43.000Z'
        - code: MOUNT_LOCKED
          value: '1'
          occurredAt: '2023-12-12T17:24:43.000Z'
    Mount:
      type: object
      properties:
        uid:
          type: string
          description: Unique identifier of the mount
        serialNumber:
          type: string
          description: Serial number of the mount
        macAddress:
          type: string
          description: Mac Address of the BLE device
        firmwareRevision:
          type: string
          description: Firmware version of the mount
        softwareRevision:
          type: string
          description: Software version of the mount
        modelNumber:
          type: string
          description: Model number of the mount
        name:
          type: string
          description: Human readable name of the mount
        associationState:
          type: string
          description: Current association state of the mount
          enum:
            - ASSOCIATED
            - IDLE
            - INACTIVE
        associatedAt:
          type: string
          format: date-time
          description: Date and time of the association
        mountLocked:
          type: boolean
          description: >-
            Whether the mount is locked or not, null if not available. Value
            computed from the states.
        helmetMounted:
          type: boolean
          description: >-
            Whether the helmet is mounted or not, null if not available. Value
            computed from the states.
        batteryLevel:
          type: integer
          description: >-
            Battery level in percentage (0-100) no decimals, null if not
            available. Value computed from the states.
        cpuTemperature:
          type: number
          description: >-
            CPU temperature in Celsius, 1 decimal, null if not available. Value
            computed from the states.
        nfcTagsCount:
          type: number
          description: Number of NFC tags associated with the mount
      example:
        - uid: b2413500-8106-4530-b7dc-91ebe3b6236
          name: My favorite mount
          serialNumber: '1234567890'
          macAddress: '00:00:00:00:00:00'
          firmwareRevision: NCS2.4.0
          softwareRevision: 0.99.2
          modelNumber: 52832-OP
          associationState: ASSOCIATED
          mountLocked: false
          helmetMounted: true
          batteryLevel: 82
          cpuTemperature: 45.5
          associatedAt: '2023-12-12T17:24:43.000Z'
    NfcTag:
      type: object
      properties:
        uid:
          type: string
        name:
          type: string
        color:
          type: string
        iconName:
          type: string
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    FirmwareVersion:
      type: object
      properties:
        softwareRevision:
          type: number
          description: Version number of the firmware
        availableSince:
          type: string
          format: date-time
          description: Date and time when the firmware version became available
        deprecated:
          type: boolean
          description: Indicated if this version is deprecated
        modelNumber:
          type: boolean
          description: Indicated if this version is deprecated
      example:
        - softwareRevision: 0.99.3
          modelNumber: 52832-OP
          availableSince: '2023-12-12T17:24:43.000Z'
          deprecated: false
        - softwareRevision: 0.99.2
          modelNumber: 52832-OP
          availableSince: '2021-06-12T17:24:43.000Z'
          deprecated: true
        - softwareRevision: 0.99.5
          modelNumber: 53840-CO
          availableSince: '2021-06-12T17:24:43.000Z'
          deprecated: false
    FirmwareUpdateCheckResult:
      type: object
      properties:
        code:
          type: string
          description: Result code of the firmware update check
          enum:
            - UP_TO_DATE
            - UPDATE_AVAILABLE
            - MANDATORY_UPDATE
        version:
          $ref: '#/components/schemas/FirmwareVersion'
      example:
        - code: UP_TO_DATE
        - code: UPDATE_AVAILABLE
          version:
            softwareRevision: 0.99.3
            modelNumber: 52832-OP
            availableSince: '2023-12-12T17:24:43.000Z'
            deprecated: false
        - code: MANDATORY_UPDATE
          version:
            softwareRevision: 0.99.5
            modelNumber: 53840-CO
            availableSince: '2023-12-12T17:24:43.000Z'
            deprecated: false
    FirmwareDownloadLink:
      type: object
      properties:
        version:
          $ref: '#/components/schemas/FirmwareVersion'
        downloadLink:
          type: string
          description: Download link for the firmware
        expiresAt:
          type: string
          format: date-time
          description: Expiration date and time for the download link
      example:
        - version:
            softwareRevision: 0.99.5
            modelNumber: 53840-CO
            availableSince: '2023-12-12T17:24:43.000Z'
            deprecated: false
          downloadLink: https://someObjectStorage?authKey=temporaryKey
          expiresAt: '2023-12-12T17:24:43.000Z'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Access-Key
