openapi: '3.0.0'
info:
  version: 1.0.0
  title: Infuse API
  description: Infuse API for device management
paths:
  /health:
    get:
      operationId: getHealth
      summary: Health check endpoint
      x-internal: true
      security: []
      responses:
        '200':
          description: Health check response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HealthCheck'
  /organisation:
    get:
      operationId: getAllOrganisations
      tags:
        - organisation
      summary: Get all organisations that user has access to
      responses:
        '200':
          description: A list of organisations
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Organisation'
        '500':
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    post:
      operationId: createOrganisation
      tags:
        - organisation
      summary: Create a new organisation
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NewOrganisation'
      responses:
        '201':
          description: Created organisation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Organisation'
        '409':
          description: Conflicts with an existing organisation.
  /organisation/id/{id}:
    get:
      operationId: getOrganisationById
      tags:
        - organisation
      summary: Get an organisation by ID
      parameters:
        - in: path
          name: id
          description: ID of organisation
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Returned organisation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Organisation'
        '404':
          description: An organisation with the specified ID was not found or you do not have permission to view it.
  /organisation/name/{name}:
    get:
      operationId: getOrganisationByName
      tags:
        - organisation
      summary: Get an organisation by name
      parameters:
        - in: path
          name: name
          description: Name of organisation
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Returned organisation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Organisation'
        '404':
          description: An organisation with the specified name was not found or you do not have permission to view it.
  /board:
    get:
      operationId: getBoards
      tags:
        - board
      summary: Get all boards in an organisation
      parameters:
        - in: query
          name: organisationId
          description: ID of organisation
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: A list of boards
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Board'
    post:
      operationId: createBoard
      tags:
        - board
      summary: Create a new board
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NewBoard'
      responses:
        '201':
          description: Created board
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Board'
        '409':
          description: Conflicts with an existing board.
        '422':
          description: Specified organisation does not exist.
  /board/id/{id}:
    get:
      operationId: getBoardById
      tags:
        - board
      summary: Get a board by ID
      parameters:
        - in: path
          name: id
          description: ID of board
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Returned board
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Board'
        '404':
          description: A board with the specified ID was not found.
  /board/id/{id}/devices:
    get:
      operationId: getDevicesByBoardId
      tags:
        - board
      summary: Get devices by board id and optional metadata field
      parameters:
        - in: path
          name: id
          description: ID of board
          required: true
          schema:
            type: string
            format: uuid
        - in: query
          name: metadataName
          description: Name of metadata field to filter by (must also provide metadataValue)
          schema:
            type: string
        - in: query
          name: metadataValue
          description: Value of metadata field to filter by (must also provide metadataName)
          schema:
            type: string
      responses:
        '200':
          description: A list of devices
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Device'
        '404':
          description: A board with the specified ID was not found.
  /network:
    get:
      operationId: getNetworks
      tags:
        - network
      summary: Get networks
      description: Get all networks in an organisation
      parameters:
        - in: query
          name: organisationId
          description: ID of organisation to get networks for
          required: true
          schema:
            type: string
            format: uuid
        - in: query
          name: includePublic
          description: Whether to include public networks from outside the org in the results
          required: true
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: A list of networks
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Network'
    post:
      operationId: createNetwork
      tags:
        - network
      summary: Create a new network
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NewNetwork'
      responses:
        '201':
          description: Created network
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Network'
        '409':
          description: Conflicts with an existing network.
        '422':
          description: Invalid organisation.
  /device:
    get:
      operationId: getDevices
      tags:
        - device
      summary: Get all devices in an organisation
      parameters:
        - in: query
          name: organisationId
          description: ID of organisation
          required: true
          schema:
            type: string
            format: uuid
        - in: query
          name: limit
          description: Maximum number of devices to return
          schema:
            type: integer
            format: uint32
            minimum: 1
            maximum: 1000
            default: 100
        - in: query
          name: offset
          description: Number of devices to skip
          schema:
            type: integer
            format: uint32
            minimum: 0
            default: 0
      responses:
        '200':
          description: A list of devices
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Device'
    post:
      operationId: createDevice
      tags:
        - device
      summary: Create a new device
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NewDevice'
      responses:
        '201':
          description: Created device
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Device'
        '409':
          description: Conflicts with an existing device.
        '422':
          description: Invalid organisation, board, device ID or MCU ID.
  /device/id/{id}:
    get:
      operationId: getDeviceById
      tags:
        - device
      summary: Get a device by ID
      parameters:
        - in: path
          name: id
          description: ID of device
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Returned device
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Device'
        '404':
          description: A device with the specified ID was not found.
    put:
      operationId: updateDeviceById
      tags:
        - device
      summary: Update a device by ID
      parameters:
        - in: path
          name: id
          description: ID of device
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DeviceUpdate'
      responses:
        '200':
          description: Updated device
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Device'
        '404':
          description: A device with the specified ID was not found.
  /device/id/{id}/state:
    get:
      operationId: getDeviceStateById
      tags:
        - device
      summary: Get device state by ID
      parameters:
        - in: path
          name: id
          description: ID of device
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Returned device state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceState'
        '404':
          description: A device with the specified ID was not found.
    put:
      operationId: updateDeviceStateByID
      tags:
        - device
      summary: Update device state by ID
      parameters:
        - in: path
          name: id
          description: ID of device
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NewDeviceState'
      responses:
        '200':
          description: Updated device state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceState'
        '404':
          description: A device with the specified ID was not found.
  /device/deviceId/{deviceId}:
    get:
      operationId: getDeviceByDeviceId
      tags:
        - device
      summary: Get a device by DeviceID
      parameters:
        - in: path
          name: deviceId
          description: DeviceID of device as a hex string
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Returned device
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Device'
        '404':
          description: A device with the specified DeviceID was not found.
  /device/deviceId/{deviceId}/state:
    get:
      operationId: getDeviceStateByDeviceID
      tags:
        - device
      summary: Get device state by DeviceID
      parameters:
        - in: path
          name: deviceId
          description: DeviceID of device as a hex string
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Returned device state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceState'
        '404':
          description: A device with the specified DeviceID was not found.
  /device/deviceId/{deviceId}/lastRoute:
    get:
      operationId: getDeviceLastRouteByDeviceID
      tags:
        - device
      summary: Get last route by DeviceID
      parameters:
        - in: path
          name: deviceId
          description: DeviceID of device as a hex string
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Returned device last route
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UplinkRoute'
        '404':
          description: A device with the specified DeviceID was not found.
  /device/deviceId/{deviceId}/loggerState/{index}:
    get:
      operationId: getDeviceLoggerStateByDeviceIDAndIndex
      tags:
        - device
        - logger
      summary: Get logger state by DeviceID and index
      parameters:
        - in: path
          name: deviceId
          description: DeviceID of device as a hex string
          required: true
          schema:
            type: string
        - in: path
          name: index
          description: Index of the logger state
          required: true
          schema:
            type: integer
            format: uint8
      responses:
        '200':
          description: Returned device logger state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceLoggerState'
        '404':
          description: A device with the specified DeviceID was not found.
    patch:
      operationId: updateDeviceLoggerStateByDeviceIDAndIndex
      tags:
        - device
        - logger
      summary: Update logger state by DeviceID and index
      parameters:
        - in: path
          name: deviceId
          description: DeviceID of device as a hex string
          required: true
          schema:
            type: string
        - in: path
          name: index
          description: Index of the logger state
          required: true
          schema:
            type: integer
            format: uint8
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DeviceLoggerStateUpdate'
      responses:
        '200':
          description: Updated device logger state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceLoggerState'
        '404':
          description: A device with the specified DeviceID was not found.
  /device/deviceId/{deviceId}/loggerStates:
    get:
      operationId: getDeviceLoggerStatesByDeviceID
      tags:
        - device
        - logger
      summary: Get all logger states by DeviceID
      parameters:
        - in: path
          name: deviceId
          description: DeviceID of device as a hex string
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Returned device logger states
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/DeviceLoggerStateWithIndex'
        '404':
          description: A device with the specified DeviceID was not found.
  /device/deviceId/{deviceId}/kv/entries:
    get:
      operationId: getDeviceKVEntriesByDeviceID
      tags:
        - device
        - kv
      summary: Get KV entries by DeviceID
      parameters:
        - in: path
          name: deviceId
          description: DeviceID of device as a hex string
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Returned device KV entries
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/DeviceKVEntry'
        '404':
          description: A device with the specified DeviceID was not found.
  /device/deviceId/{deviceId}/kv/entries/{keyId}:
    get:
      operationId: getDeviceKVEntryByDeviceIDAndKeyID
      tags:
        - device
        - kv
      summary: Get a KV entry by DeviceID and Key ID
      parameters:
        - in: path
          name: deviceId
          description: DeviceID of device as a hex string
          required: true
          schema:
            type: string
        - in: path
          name: keyId
          description: Key ID of the KV entry
          required: true
          schema:
            type: integer
            format: uint16
      responses:
        '200':
          description: Returned device KV entry
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceKVEntry'
        '404':
          description: A device with the specified DeviceID or Key ID was not found.
  /device/deviceId/{deviceId}/kv/entries/{keyId}/updates:
    get:
      operationId: getDeviceKVEntryUpdatesByDeviceIDAndKeyID
      tags:
        - device
        - kv
      summary: Get KV entry updates by DeviceID and Key ID
      parameters:
        - in: path
          name: deviceId
          description: DeviceID of device as a hex string
          required: true
          schema:
            type: string
        - in: path
          name: keyId
          description: Key ID of the KV entry
          required: true
          schema:
            type: integer
            format: uint16
        - in: query
          name: status
          description: Filter updates by status
          schema:
            $ref: '#/components/schemas/DeviceEntryUpdateStatus'
        - in: query
          name: limit
          description: Maximum number of updates to return
          schema:
            type: integer
            format: uint32
            minimum: 1
            maximum: 1000
            default: 100
        - in: query
          name: offset
          description: Number of updates to skip
          schema:
            type: integer
            format: uint32
            minimum: 0
            default: 0
      responses:
        '200':
          description: Returned device KV entry updates
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/DeviceKVEntryUpdate'
    post:
      operationId: createDeviceKVEntryUpdateByDeviceIDAndKeyID
      tags:
        - device
        - kv
      summary: Create a KV entry update by DeviceID and Key ID
      parameters:
        - in: path
          name: deviceId
          description: DeviceID of device as a hex string
          required: true
          schema:
            type: string
        - in: path
          name: keyId
          description: Key ID of the KV entry
          required: true
          schema:
            type: integer
            format: uint16
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NewDeviceKVEntryUpdate'
      responses:
        '200':
          description: Existing device KV entry is already up to date, no update created. Returned existing entry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceKVEntry'
        '201':
          description: Created device KV entry update
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceKVEntryUpdate'
        '400':
          description: Invalid request parameters.
        '403':
          description: Key is read-only.
        '404':
          description: An entry with the specified DeviceID or Key ID was not found.
        '409':
          description: A pending update already exists for the specified DeviceID and Key ID.
    delete:
      operationId: cancelPendingDeviceKVEntryUpdatesByDeviceIDAndKeyID
      tags:
        - device
        - kv
      summary: Cancel pending KV entry update by DeviceID and Key ID
      parameters:
        - in: path
          name: deviceId
          description: DeviceID of device as a hex string
          required: true
          schema:
            type: string
        - in: path
          name: keyId
          description: Key ID of the KV entry
          required: true
          schema:
            type: integer
            format: uint16
      responses:
        '200':
          description: Cancelled pending update for device KV entry
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceKVEntryUpdate'
        '204':
          description: No pending update to cancel for the specified DeviceID and Key ID.
  /device/soc/{soc}/mcuId/{mcuId}:
    get:
      operationId: getDeviceBySocAndMcuId
      tags:
        - device
      summary: Get a device by SoC and MCU ID
      parameters:
        - in: path
          name: soc
          description: SoC of device
          required: true
          schema:
            type: string
        - in: path
          name: mcuId
          description: MCU ID of device as a hex string
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Returned device
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Device'
        '404':
          description: A device with the specified SoC and MCU ID was not found.
  /device-and-state:
    get:
      operationId: getDevicesAndStates
      tags:
        - device
      summary: Get all devices and their states in an organisation
      parameters:
        - in: query
          name: organisationId
          description: ID of organisation
          required: true
          schema:
            type: string
            format: uuid
        - in: query
          name: limit
          description: Maximum number of devices to return
          schema:
            type: integer
            format: uint32
            minimum: 1
            maximum: 1000
            default: 100
        - in: query
          name: offset
          description: Number of devices to skip
          schema:
            type: integer
            format: uint32
            minimum: 0
            default: 0
      responses:
        '200':
          description: A list of device with states included
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/DeviceAndState'
  /device/lastRoute:
    post:
      operationId: getLastRoutesForDevices
      tags:
        - device
      summary: Get last routes for a group of devices
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GetLastRoutesForDevicesBody'
      responses:
        '200':
          description: A list of last routes for devices in the organisation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/UplinkRouteAndDeviceId'
  /key/sharedSecret:
    post:
      operationId: getSharedSecret
      tags:
        - key
      summary: Generate a shared secret key from a device's public key
      requestBody:
        required: true
        description: Device's public key
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Key'
      responses:
        '200':
          description: Generated shared secret
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Key'
  /key/derived/device:
    post:
      operationId: deriveDeviceKey
      tags:
        - key
      summary: Derive a device key for encryption
      description: Generate a derived key to use for device level encrpytion, if security state is provided, it will be used to derive the key, otherwise the last stored security state will be used.
      requestBody:
        required: true
        description: Device ID and key derivation parameters
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DeriveDeviceKeyBody'
      responses:
        '200':
          description: Generated derived key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Key'
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /key/publicKey:
    get:
      operationId: getPublicKey
      tags:
        - key
      summary: Get the current public key of the cloud
      responses:
        '200':
          description: Cloud public key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Key'
  /rpc:
    get:
      summary: Get RPC messages
      operationId: getRPCs
      parameters:
        - $ref: '#/components/parameters/organisationIdQuery'
        - $ref: '#/components/parameters/deviceIdQuery'
        - $ref: '#/components/parameters/rpcStatusQuery'
        - $ref: '#/components/parameters/startTimeQuery'
        - $ref: '#/components/parameters/endTimeQuery'
        - $ref: '#/components/parameters/limitQuery'
        - $ref: '#/components/parameters/rpcCommandIdQuery'
        - $ref: '#/components/parameters/rpcShowExpiredQuery'
      tags:
        - rpc
      responses:
        '200':
          description: A list of RPC messages
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/RpcMessage'
        '500':
          description: An unexpected error occurred getting the RPC messages
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    post:
      summary: Send an RPC to a device
      operationId: sendRPC
      tags:
        - rpc
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NewRPCMessage'
      responses:
        '201':
          description: The RPC was sent successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreatedRpcMessage'
        '400':
          description: The RPC request is invalid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Not authorised to send an RPC to this device
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: An unexpected error occurred sending the RPC
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /rpc/{id}:
    get:
      summary: Get an RPC message by ID
      operationId: getRPCByID
      tags:
        - rpc
      parameters:
        - name: id
          in: path
          description: The ID of the RPC message
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: The RPC message was found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RpcMessage'
        '404':
          description: The RPC message was not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: An unexpected error occurred getting the RPC status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /defs/rpc:
    get:
      summary: Get the latest RPC definitions
      operationId: getLatestRPCDefinitions
      tags:
        - defs
      security: []
      responses:
        '200':
          description: The latest RPC definitions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DefinitionsRPCResponse'
        '404':
          description: No RPC definitions found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: An unexpected error occurred getting the RPC definitions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    post:
      summary: Add new version of RPC definitions
      operationId: addRPCDefinitions
      tags:
        - defs
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DefinitionsRPC'
      responses:
        '201':
          description: The RPC definitions were updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DefinitionsRPCResponse'
        '400':
          description: The RPC definitions are invalid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: An unexpected error occurred updating the RPC definitions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /defs/rpc/{version}:
    get:
      summary: Get RPC definitions by version
      operationId: getRPCDefinitionsByVersion
      tags:
        - defs
      security: []
      parameters:
        - name: version
          in: path
          description: The version of the RPC definitions
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: The RPC definitions were found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DefinitionsRPCResponse'
        '404':
          description: The RPC definitions were not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: An unexpected error occurred getting the RPC definitions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /defs/tdf:
    get:
      summary: Get the latest TDF definitions
      operationId: getLatestTDFDefinitions
      tags:
        - defs
      security: []
      responses:
        '200':
          description: The latest TDF definitions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DefinitionsTDFResponse'
        '404':
          description: No TDF definitions found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: An unexpected error occurred getting the TDF definitions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    post:
      summary: Add new version of TDF definitions
      operationId: addTDFDefinitions
      tags:
        - defs
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DefinitionsTDF'
      responses:
        '201':
          description: The TDF definitions were updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DefinitionsTDFResponse'
        '400':
          description: The TDF definitions are invalid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: An unexpected error occurred updating the TDF definitions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /defs/tdf/{version}:
    get:
      summary: Get TDF definitions by version
      operationId: getTDFDefinitionsByVersion
      tags:
        - defs
      security: []
      parameters:
        - name: version
          in: path
          description: The version of the TDF definitions
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: The TDF definitions were found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DefinitionsTDFResponse'
        '404':
          description: The TDF definitions were not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: An unexpected error occurred getting the TDF definitions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /defs/kv:
    get:
      summary: Get the latest KV definitions
      operationId: getLatestKVDefinitions
      tags:
        - defs
      security: []
      responses:
        '200':
          description: The latest KV definitions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DefinitionsKVResponse'
        '404':
          description: No KV definitions found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: An unexpected error occurred getting the KV definitions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    post:
      summary: Add new version of key-value definitions
      operationId: addKVDefinitions
      tags:
        - defs
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DefinitionsKV'
      responses:
        '201':
          description: The key-value definitions were updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DefinitionsKVResponse'
        '400':
          description: The key-value definitions are invalid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: An unexpected error occurred updating the key-value definitions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /defs/kv/{version}:
    get:
      summary: Get key-value definitions by version
      operationId: getKVDefinitionsByVersion
      tags:
        - defs
      security: []
      parameters:
        - name: version
          in: path
          description: The version of the key-value definitions
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: The key-value definitions were found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DefinitionsKVResponse'
        '404':
          description: The key-value definitions were not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: An unexpected error occurred getting the key-value definitions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /coap/files:
    get:
      summary: Get a list of files on the COAP server
      operationId: getCOAPFiles
      tags:
        - coap
      parameters:
        - in: query
          name: regex
          description: Regular expression to filter files by (leave blank to get all files)
          schema:
            type: string
            format: regex
      responses:
        '200':
          description: A list of files
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/COAPFilesList'
        '400':
          description: The regular expression is invalid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: An unexpected error occurred getting the files
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /coap/file/{filename}/stats:
    get:
      summary: Get statistics for a file on the COAP server
      operationId: getCOAPFileStats
      tags:
        - coap
      parameters:
        - in: path
          name: filename
          description: Name of file
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Statistics for the file
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/COAPFileStats'
        '404':
          description: The file was not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: An unexpected error occurred getting the file statistics
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /admin/apiKey:
    post:
      operationId: generateAPIKey
      tags:
        - admin
      x-scalar-ignore: true
      summary: Generate an API key
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GenerateAPIKeyBody'
      responses:
        '200':
          description: Generated API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeneratedAPIKey'
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: An unexpected error occurred creating the API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /mqtt/token:
    post:
      operationId: generateMQTTToken
      tags:
        - mqtt
      summary: Generate an MQTT token
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GenerateMQTTTokenBody'
      responses:
        '200':
          description: Generated MQTT token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeneratedMQTTToken'
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: An unexpected error occurred creating the MQTT token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    CreatedOrganisationProperties:
      properties:
        id:
          type: string
          description: Generated UUID for organisation
          format: uuid
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - createdAt
        - updatedAt
    NewOrganisation:
      properties:
        name:
          type: string
          description: Name of organisation
          example: Organisation Name
      required:
        - name
    Organisation:
      allOf:
        - $ref: '#/components/schemas/CreatedOrganisationProperties'
        - $ref: '#/components/schemas/NewOrganisation'
      properties:
        id:
          type: string
          description: Generated UUID for organisation
          format: uuid
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - createdAt
    CreatedBoardProperties:
      properties:
        id:
          type: string
          format: uuid
          description: Generated UUID for board
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - createdAt
        - updatedAt
    MetadataField:
      properties:
        name:
          type: string
          description: Name of metadata field
          example: Field Name
        required:
          type: boolean
          description: Whether field is required
          example: true
        unique:
          type: boolean
          description: Whether field is unique (across all devices of the same board)
          example: false
      required:
        - name
        - required
        - unique
    BoardMetadataFields:
      type: array
      description: Metadata fields for board
      example: [{ 'name': 'Field Name', 'required': true, 'unique': false }]
      items:
        $ref: '#/components/schemas/MetadataField'
    NewBoard:
      properties:
        name:
          type: string
          description: Name of board
          example: Board Name
        description:
          type: string
          description: Description of board
          example: Extended description of board
        soc:
          type: string
          description: System on Chip (SoC) of board
          example: nRF9151
        organisationId:
          type: string
          format: uuid
          description: ID of organisation for board to exist in
        public:
          type: boolean
          description: Whether the board is public (devices from other organisations can use it)
          default: false
        metadataFields:
          $ref: '#/components/schemas/BoardMetadataFields'
      required:
        - name
        - description
        - soc
        - organisationId
    Board:
      allOf:
        - $ref: '#/components/schemas/CreatedBoardProperties'
        - $ref: '#/components/schemas/NewBoard'
        - type: object
          required:
            - metadataFields
            - public
    DeviceIdField:
      properties:
        deviceId:
          type: string
          description: 8 byte DeviceID as a hex string (if not provided will be auto-generated)
          example: d291d4d66bf0a955
          minLength: 16
          maxLength: 16
          pattern: ^[a-fA-F0-9]+$
    CreatedDeviceProperties:
      properties:
        id:
          type: string
          format: uuid
          description: Generated UUID for organisation
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - createdAt
        - updatedAt
    DeviceMetadata:
      type: object
      additionalProperties:
        type: string
      description: Metadata fields for device
      example: { 'Field Name': 'Field Value' }
    NewDevice:
      allOf:
        - $ref: '#/components/schemas/DeviceIdField'
        - type: object
          properties:
            mcuId:
              type: string
              description: Device's MCU ID as a hex string
              example: '0011223344556677'
              minLength: 2
              maxLength: 32
              pattern: ^[a-fA-F0-9]+$
            boardId:
              type: string
              format: uuid
              description: ID of board of device
            organisationId:
              type: string
              format: uuid
              description: ID of organisation for board to exist in
            metadata:
              $ref: '#/components/schemas/DeviceMetadata'
            initialDeviceState:
              $ref: '#/components/schemas/NewDeviceState'
          required:
            - mcuId
            - boardId
            - organisationId
    DeviceMetadataUpdate:
      type: object
      description: Metadata update
      properties:
        operation:
          type: string
          description: Operation to perform on metadata, patch to update/add provided fields, replace to replace all metadata with provided fields
          enum: [patch, replace]
        value:
          $ref: '#/components/schemas/DeviceMetadata'
      required:
        - operation
        - value
    DeviceUpdate:
      type: object
      properties:
        metadata:
          $ref: '#/components/schemas/DeviceMetadataUpdate'
    Device:
      allOf:
        - $ref: '#/components/schemas/CreatedDeviceProperties'
        - $ref: '#/components/schemas/NewDevice'
        - type: object
          required:
            - deviceId
            - metadata
    DeviceAndState:
      allOf:
        - $ref: '#/components/schemas/Device'
        - type: object
          properties:
            state:
              $ref: '#/components/schemas/DeviceState'
          required:
            - state
    ApplicationVersion:
      description: Application version
      properties:
        major:
          type: integer
          format: uint8
          description: Major version number
          x-order: 1
        minor:
          type: integer
          format: uint8
          description: Minor version number
          x-order: 2
        revision:
          type: integer
          format: uint16
          description: Revision number
          x-order: 3
        buildNum:
          type: integer
          format: uint32
          description: Build number
          x-order: 4
      required:
        - major
        - minor
        - revision
        - buildNum
    Algorithm:
      properties:
        id:
          type: integer
          format: uint32
          description: ID of algorithm
        version:
          type: integer
          format: uint16
          description: Version of algorithm
      required:
        - id
        - version
    RouteType:
      type: string
      enum: [unknown, udp, serial, bt_adv, bt_peripheral, bt_central, hci]
      description: Interface of route
    DeviceState:
      allOf:
        - $ref: '#/components/schemas/NewDeviceState'
        - type: object
          properties:
            createdAt:
              type: string
              format: date-time
            updatedAt:
              type: string
              format: date-time
            lastRouteInterface:
              $ref: '#/components/schemas/RouteType'
              description: Interface of last packet sent by device
            lastRouteUdpAddress:
              type: string
              description: Address of last packet sent directly via UDP
            lastRouteUdpTime:
              type: string
              format: date-time
              description: Time of last packet sent directly via UDP
            lastRoute:
              $ref: '#/components/schemas/UplinkRoute'
              description: Route of last packet sent by device (via any route)
            lastRouteTime:
              type: string
              format: date-time
              description: Time of last packet sent by device (via any route)
          required:
            - createdAt
            - updatedAt
    NewDeviceState:
      properties:
        applicationId:
          type: integer
          format: uint32
          description: Last announced application ID
        applicationVersion:
          description: Last announced application version
          $ref: '#/components/schemas/ApplicationVersion'
        algorithms:
          type: array
          description: Last announced algorithms
          items:
            $ref: '#/components/schemas/Algorithm'
    DeviceLoggerState:
      type: object
      properties:
        lastReportedBlock:
          type: integer
          format: uint32
          description: Last reported block number
        lastReportedTime:
          type: string
          format: date-time
          description: Last time logger state was reported
        lastDownloadedBlock:
          type: integer
          format: uint32
          description: Last downloaded block number
        lastDownloadedWrapCount:
          type: integer
          format: uint32
          description: Last downloaded block wrap count
        lastDownloadedTime:
          type: string
          format: date-time
          description: Last time logger state was downloaded
        downloadEnabled:
          type: boolean
          description: Whether logger download is enabled
      required:
        - downloadEnabled
    DeviceLoggerStateWithIndex:
      allOf:
        - $ref: '#/components/schemas/DeviceLoggerState'
        - type: object
          properties:
            index:
              type: integer
              format: uint8
              description: Index of logger
          required:
            - index
    DeviceLoggerStateUpdate:
      type: object
      properties:
        downloadEnabled:
          type: boolean
          description: Whether logger download is enabled
      required:
        - downloadEnabled
      additionalProperties: false
    Key:
      properties:
        key:
          type: string
          format: byte
          description: Key bytes as a base64 encoded string
          example: A+JIpO+B1oYxwLfXQ9xXLjIaRxhmLrZtPDtWw36N24Y=
      required:
        - key
    SecurityState:
      properties:
        cloudPublicKey:
          type: string
          format: byte
          description: Cloud public ECC key as a base64 encoded string
        devicePublicKey:
          type: string
          format: byte
          description: Device public ECC key as a base64 encoded string
        networkId:
          type: integer
          format: uint32
          description: Current network ID
        challenge:
          type: string
          format: byte
          description: Challenge used in request as a base64 encoded string
        challengeResponseType:
          type: integer
          format: uint8
          description: Type of the challenge response
        challengeResponse:
          type: string
          format: byte
          description: Challenge response as a base64 encoded string
      required:
        - cloudPublicKey
        - devicePublicKey
        - networkId
        - challenge
        - challengeResponseType
        - challengeResponse
    KeyInterface:
      type: string
      enum: [serial, udp, bt_adv, bt_gatt]
    DeriveDeviceKeyBody:
      properties:
        deviceId:
          type: string
          description: The ID of the device to send the RPC to as a hex string
          example: d291d4d66bf0a955
          minLength: 16
          maxLength: 16
          pattern: ^[a-fA-F0-9]+$
        interface:
          $ref: '#/components/schemas/KeyInterface'
          description: Interface to generate key for
        securityState:
          $ref: '#/components/schemas/SecurityState'
          description: Current security state of the device (if not provided, will use last stored shared key)
      required:
        - deviceId
        - interface
    HealthCheck:
      properties:
        health:
          type: string
      required:
        - health
    RPCParams:
      type: object
      description: RPC request or response params (must be a JSON object with string or embedded json values - numbers sent as decimal strings)
      example: { 'primitive_vaue': '1000', 'struct_value': { 'field': 'value' } }
    RPCReqDataHeader:
      type: object
      properties:
        size:
          type: integer
          format: uint32
          description: Amount of data expected
        rxAckPeriod:
          type: integer
          format: uint8
          description: Send an ACK every N packets received
          default: 0
      required:
        - size
        - rxAckPeriod
    NewRPCReq:
      type: object
      properties:
        commandId:
          type: integer
          format: uint16
          description: ID of RPC command (must provide either commandId or commandName)
          example: 3
        commandName:
          type: string
          description: Name of RPC command (must provide either commandId or commandName)
          example: time_get
        params:
          $ref: '#/components/schemas/RPCParams'
        paramsEncoded:
          type: string
          format: byte
          description: Base64 encoded params (if provided, will be used instead of params)
        dataHeader:
          $ref: '#/components/schemas/RPCReqDataHeader'
          decription: Data header for RPC request with RPC_DATA
    NewRPCMessage:
      type: object
      properties:
        deviceId:
          type: string
          description: The ID of the device to send the RPC to as a hex string
          example: d291d4d66bf0a955
          minLength: 16
          maxLength: 16
          pattern: ^[a-fA-F0-9]+$
        sendWaitTimeoutMs:
          type: integer
          format: uint64
          description: Maximum time to wait (in milliseconds) for the device to send a packet.
            If 0 or not set, the RPC is sent immediately using the device's last route.
          minimum: 0
          default: 60000
          # 24 hour
          maximum: 86400000
        rpc:
          $ref: '#/components/schemas/NewRPCReq'
      required:
        - deviceId
        - rpc
    CreatedRpcMessage:
      type: object
      properties:
        createdAt:
          type: string
          format: date-time
          description: The time the RPC message was created
        id:
          type: string
          format: uuid
          description: The ID of the RPC message
          example: 5f4b1b2b-3b4d-4b5e-8c6f-7d8e9f0a1b2c
        downlinkMessageId:
          type: string
          format: uuid
          description: The ID of the corresponding downlink message sent to the device
          example: 7527bf1c-9868-4afd-b07d-16dc7eb7bed3
      required:
        - createdAt
        - id
        - downlinkMessageId
    UdpUplinkRoute:
      type: object
      properties:
        address:
          type: string
          description: UDP address of device
        time:
          type: string
          format: date-time
          description: Time packet was received by UDP server
      required:
        - address
        - time
    BtLeRoute:
      type: object
      properties:
        address:
          type: string
          description: Bluetooth LE address of device
        type:
          type: string
          description: Type of Bluetooth LE address (public or random)
          enum: [public, random, unknown]
      required:
        - address
        - type
    ForwardedUplinkRoute:
      type: object
      properties:
        deviceId:
          type: string
          description: The ID of the forwarding device as a hex string
          example: d291d4d66bf0a955
          minLength: 16
          maxLength: 16
          pattern: ^[a-fA-F0-9]+$
        route:
          description: Route taken by forwarding device
          $ref: '#/components/schemas/UplinkRoute'
        auth:
          type: integer
          format: uint8
          description: Auth level for the forwarding device packet
        rssi:
          type: integer
          format: int16
          description: RSSI of the packet
      required:
        - deviceId
        - route
        - auth
        - rssi
    InterfaceData:
      type: object
      properties:
        sequence:
          type: integer
          format: uint16
          description: Sequence number of packet
    UplinkRoute:
      type: object
      properties:
        interface:
          $ref: '#/components/schemas/RouteType'
          description: Interface of route
        udp:
          description: UDP route (if taken)
          $ref: '#/components/schemas/UdpUplinkRoute'
        btAdv:
          description: Bluetooth LE advertising route (if taken)
          $ref: '#/components/schemas/BtLeRoute'
        btPeripheral:
          description: Bluetooth LE peripheral route (if taken)
          $ref: '#/components/schemas/BtLeRoute'
        btCentral:
          description: Bluetooth LE central route (if taken)
          $ref: '#/components/schemas/BtLeRoute'
        forwarded:
          description: Forwarded route (if taken)
          $ref: '#/components/schemas/ForwardedUplinkRoute'
        interfaceData:
          description: Interface specific data
          $ref: '#/components/schemas/InterfaceData'
      required:
        - interface
        - interfaceData
    UdpDownlinkRoute:
      type: object
      properties:
        address:
          type: string
          description: UDP address of device
      required:
        - address
    ForwardedDownlinkRoute:
      type: object
      properties:
        deviceId:
          type: string
          description: The ID of the forwarding device as a hex string
          example: d291d4d66bf0a955
          minLength: 16
          maxLength: 16
          pattern: ^[a-fA-F0-9]+$
        route:
          description: Route taken by forwarding device
          $ref: '#/components/schemas/DownlinkRoute'
        auth:
          type: integer
          format: uint8
          description: Auth level for the forwarding device packet
      required:
        - deviceId
        - route
        - auth
    DownlinkRoute:
      type: object
      properties:
        interface:
          $ref: '#/components/schemas/RouteType'
          description: Interface of route
        udp:
          description: UDP route (if taken)
          $ref: '#/components/schemas/UdpDownlinkRoute'
        btAdv:
          description: Bluetooth LE advertising route (if taken)
          $ref: '#/components/schemas/BtLeRoute'
        btPeripheral:
          description: Bluetooth LE peripheral route (if taken)
          $ref: '#/components/schemas/BtLeRoute'
        btCentral:
          description: Bluetooth LE central route (if taken)
          $ref: '#/components/schemas/BtLeRoute'
        forwarded:
          description: Forwarded route (if taken)
          $ref: '#/components/schemas/ForwardedDownlinkRoute'
        interfaceData:
          description: Interface specific data
          $ref: '#/components/schemas/InterfaceData'
      required:
        - interface
        - interfaceData
    RpcReq:
      type: object
      properties:
        requestId:
          type: integer
          format: uint32
          description: The unique ID of the RPC request
        commandId:
          type: integer
          format: uint16
          description: ID of RPC command
        params:
          $ref: '#/components/schemas/RPCParams'
        paramsEncoded:
          type: string
          format: byte
          description: Base64 encoded params (if provided, will be used instead of params)
        dataHeader:
          $ref: '#/components/schemas/RPCReqDataHeader'
        route:
          description: Route taken by RPC (if sent)
          $ref: '#/components/schemas/DownlinkRoute'
      required:
        - requestId
        - commandId
    RpcRsp:
      type: object
      properties:
        params:
          $ref: '#/components/schemas/RPCParams'
        paramsEncoded:
          type: string
          format: byte
          description: Base64 encoded params (provided if there was an issue decoding the RPC params)
        route:
          description: Route taken for RPC response
          $ref: '#/components/schemas/UplinkRoute'
        returnCode:
          type: integer
          format: int16
          description: Return code of RPC
      required:
        - route
        - returnCode
    DownlinkMessageStatus:
      type: string
      enum: [waiting, sent, completed]
      description: Status of downlink message
    DownlinkMessage:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: The ID of the downlink message
          example: 7527bf1c-9868-4afd-b07d-16dc7eb7bed3
        createdAt:
          type: string
          format: date-time
          description: The time the downlink message was created
        updatedAt:
          type: string
          format: date-time
          description: The time the downlink message was last updated
        deviceId:
          type: string
          format: uuid
          description: The ID of the device the message is for
          example: 5f4b1b2b-3b4d-4b5e-8c6f-7d8e9f0a1b2c
        payloadType:
          type: integer
          format: uint8
          description: The type of payload
        auth:
          type: integer
          format: uint8
          description: The auth level of the message
        rpcReq:
          description: The RPC request
          $ref: '#/components/schemas/RpcReq'
        rpcRsp:
          description: The RPC response
          $ref: '#/components/schemas/RpcRsp'
        sendWaitTimeoutMs:
          type: integer
          format: uint64
          description:
            Maximum time to wait (in milliseconds) for the device to send a packet before expiring.
            If 0 or not set, the RPC was sent immediately using the device's last route.
        sentAt:
          type: string
          format: date-time
          description: The time the downlink message was sent
        expiresAt:
          type: string
          format: date-time
          description: The time the downlink message expires
        completedAt:
          type: string
          format: date-time
          description: The time the downlink message was completed
        status:
          $ref: '#/components/schemas/DownlinkMessageStatus'
      required:
        - id
        - createdAt
        - updatedAt
        - deviceId
        - payloadType
        - auth
        - rpcReq
        - status
    RpcMessage:
      allOf:
        - $ref: '#/components/schemas/CreatedRpcMessage'
        - type: object
          properties:
            device:
              $ref: '#/components/schemas/Device'
            downlinkMessage:
              $ref: '#/components/schemas/DownlinkMessage'
          required:
            - device
            - downlinkMessage
    DefinitionsFieldConversion:
      type: object
      description: Conversion formula for a field (m * <value> + c)
      properties:
        m:
          type: number
          format: double
        c:
          type: number
          format: double
        int:
          type: string
          description: Byte array value should be treated  as an integer
          enum: [little, big]
    DefinitionsFieldDisplay:
      type: object
      description: Display settings for a field
      properties:
        fmt:
          type: string
          description: Format string for field
          enum: [hex, float]
        digits:
          type: integer
          format: uint8
        postfix:
          type: string
    DefinitionsFieldDefinition:
      type: object
      properties:
        name:
          type: string
          description: Field name
        type:
          type: string
          description: Field type
        description:
          type: string
          description: Field description
        num:
          type: integer
          format: uint16
          description: If field is array, the number of elements (0 for variable length)
        counted_by:
          type: string
          description: If field is array, the name of the field that contains the number of elements (overrides num)
        display:
          $ref: '#/components/schemas/DefinitionsFieldDisplay'
        conversion:
          $ref: '#/components/schemas/DefinitionsFieldConversion'
      required:
        - name
        - type
    DefinitionsStructDefinition:
      type: object
      properties:
        description:
          type: string
        fields:
          type: array
          items:
            $ref: '#/components/schemas/DefinitionsFieldDefinition'
      required:
        - description
        - fields
    DefinitionsEnumValue:
      type: object
      properties:
        name:
          type: string
        value:
          type: integer
          format: uint8
        description:
          type: string
      required:
        - name
        - value
        - description
    DefinitionsEnumDefinition:
      type: object
      properties:
        description:
          type: string
        type:
          type: string
        values:
          type: array
          items:
            $ref: '#/components/schemas/DefinitionsEnumValue'
      required:
        - description
        - type
        - values
    DefinitionsRPCCommand:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
        depends_on:
          type: string
        default:
          type: string
        default_auth:
          type: string
          enum: [EPACKET_AUTH_DEVICE, EPACKET_AUTH_NETWORK]
        rpc_data:
          type: boolean
          description: Whether the command is an RPC data command
        request_params:
          type: array
          items:
            $ref: '#/components/schemas/DefinitionsFieldDefinition'
        response_params:
          type: array
          items:
            $ref: '#/components/schemas/DefinitionsFieldDefinition'
      required:
        - name
        - description
        - default_auth
        - request_params
        - response_params
    DefinitionsRPC:
      type: object
      properties:
        commands:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/DefinitionsRPCCommand'
        structs:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/DefinitionsStructDefinition'
        enums:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/DefinitionsEnumDefinition'
      required:
        - commands
        - structs
        - enums
    DefinitionsRPCResponse:
      type: object
      properties:
        createdAt:
          type: string
          format: date-time
        version:
          type: integer
        definitions:
          $ref: '#/components/schemas/DefinitionsRPC'
      required:
        - createdAt
        - version
        - definitions
    DefinitionsTDFDefinition:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
        fields:
          type: array
          items:
            $ref: '#/components/schemas/DefinitionsFieldDefinition'
      required:
        - name
        - description
        - fields
    DefinitionsTDF:
      type: object
      properties:
        structs:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/DefinitionsStructDefinition'
        definitions:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/DefinitionsTDFDefinition'
      required:
        - structs
        - definitions
    DefinitionsTDFResponse:
      type: object
      properties:
        createdAt:
          type: string
          format: date-time
        version:
          type: integer
        definitions:
          $ref: '#/components/schemas/DefinitionsTDF'
      required:
        - createdAt
        - version
        - definitions
    DefinitionsKVDefinition:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
        reflect:
          type: boolean
        read_only:
          type: boolean
        write_only:
          type: boolean
        default:
          type: string
        depends_on:
          type: string
        range:
          type: integer
          format: uint16
        fields:
          type: array
          items:
            $ref: '#/components/schemas/DefinitionsFieldDefinition'
      required:
        - name
        - description
        - fields
    DefinitionsKV:
      type: object
      properties:
        structs:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/DefinitionsStructDefinition'
        definitions:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/DefinitionsKVDefinition'
      required:
        - structs
        - definitions
    DefinitionsKVResponse:
      type: object
      properties:
        createdAt:
          type: string
          format: date-time
        version:
          type: integer
        definitions:
          $ref: '#/components/schemas/DefinitionsKV'
      required:
        - createdAt
        - version
        - definitions
    COAPFilesList:
      type: object
      properties:
        filenames:
          type: array
          items:
            type: string
      required:
        - filenames
    COAPFileStats:
      type: object
      properties:
        name:
          type: string
        len:
          type: integer
        crc:
          type: integer
          format: uint32
      required:
        - name
        - len
        - crc
    Error:
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
          description: Error code
        message:
          type: string
          description: Error message
    APIKeyOrgUserType:
      type: string
      enum:
        - admin
        - standard
      description: The type of user in the organization.
    APIKeyResourcePerm:
      type: string
      enum:
        - view
        - update
        - delete
        - create
        - admin
      description: Permission level for specified resource
    APIKeyResourceName:
      type: string
      enum:
        - device
        - network
        - board
      description: The name of the resource.
    GenerateAPIKeyBody:
      type: object
      properties:
        organisationId:
          type: string
          description: ID of the organisation
          example: 123e4567-e89b-12d3-a456-426614174000
          format: uuid
        userType:
          $ref: '#/components/schemas/APIKeyOrgUserType'
          description: The type of user in the organization.
        resourcePerms:
          type: object
          additionalProperties:
            type: array
            items:
              $ref: '#/components/schemas/APIKeyResourcePerm'
            description: A map of resource names to lists of permissions.
      required:
        - organisationId
        - userType
        - resourcePerms
    GeneratedAPIKey:
      properties:
        key:
          type: string
          description: Generated API Key
          example: 'Bearer abcdefghijklmnopqrstuvwxyz1234567890'
      required:
        - key
    GetLastRoutesForDevicesBody:
      type: object
      description: Body for getting last routes for devices
      properties:
        deviceIds:
          type: array
          maxItems: 100
          items:
            type: string
            description: 8 byte DeviceID as a hex string
            example: d291d4d66bf0a955
            minLength: 16
            maxLength: 16
            pattern: ^[a-fA-F0-9]+$
      required:
        - deviceIds
    UplinkRouteAndDeviceId:
      type: object
      description: Uplink route with device ID
      properties:
        deviceId:
          type: string
          description: 8 byte DeviceID as a hex string
          example: d291d4d66bf0a955
          minLength: 16
          maxLength: 16
          pattern: ^[a-fA-F0-9]+$
        lastRoute:
          $ref: '#/components/schemas/UplinkRoute'
      required:
        - deviceId
        - lastRoute
    GenerateMQTTTokenBody:
      type: object
      properties:
        organisationId:
          type: string
          format: uuid
          description: ID of organisation to scope the token to
        ttlSeconds:
          type: integer
          format: int32
          minimum: 60
          maximum: 86400
          default: 3600
      required:
        - organisationId
        - ttlSeconds
    GeneratedMQTTToken:
      type: object
      properties:
        token:
          type: string
          description: Generated MQTT token
        issuedAt:
          type: string
          format: date-time
          description: Issue time of token
        expiresAt:
          type: string
          format: date-time
          description: Expiry time of token
      required:
        - token
        - issuedAt
        - expiresAt
    DeviceKVEntry:
      type: object
      properties:
        keyId:
          type: integer
          format: uint16
          description: Key id
        keyName:
          type: string
          description: Key name - if definition known
        data:
          type: string
          format: byte
          description: Raw entry data as a base64 encoded string - if not write_only
        crc:
          type: integer
          format: uint32
          description: CRC32 of entry value
        decoded:
          type: object
          description: Decoded entry value - if not write_only and definition known
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - keyId
        - crc
        - createdAt
        - updatedAt
    NewDeviceKVEntryUpdate:
      type: object
      properties:
        data:
          type: string
          format: byte
          description: Raw entry data as a base64 encoded string (must provide either data or decoded)
        decoded:
          type: object
          description: Decoded entry value (must provide either data or decoded)
    DeviceEntryUpdateStatus:
      type: string
      enum: [pending, success, failed, cancelled]
      description: Status of device KV entry update
    DeviceKVEntryUpdate:
      description: Device KV entry update - note for write-only entries the data/decoded fields will not be returned, only CRC.
      allOf:
        - $ref: '#/components/schemas/NewDeviceKVEntryUpdate'
        - type: object
          properties:
            id:
              type: string
              format: uuid
              description: ID of update
            keyId:
              type: integer
              format: uint16
              description: Key id
            crc:
              type: integer
              format: uint32
              description: CRC32 of entry update value
            status:
              $ref: '#/components/schemas/DeviceEntryUpdateStatus'
              description: Status of update
            lastError:
              type: string
              description: Last error message if update failed
            lastAttemptAt:
              type: string
              format: date-time
              description: Time of last attempt
            createdAt:
              type: string
              format: date-time
            updatedAt:
              type: string
              format: date-time
          required:
            - id
            - keyId
            - crc
            - status
            - createdAt
            - updatedAt
    NewNetwork:
      type: object
      properties:
        name:
          type: string
          description: Unique name of network
        description:
          type: string
          description: Description of network
        key:
          type: string
          format: byte
          description: Key bytes as a base64 encoded string (must be 32 bytes long)
          example: AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=
        organisationId:
          type: string
          format: uuid
          description: ID of organisation the network belongs to
        public:
          type: boolean
          description: Whether the network is public (visible to all infuse organisations)
          default: false
        networkId:
          type: integer
          format: uint32
          description: Network ID
      required:
        - name
        - description
        - key
        - organisationId
        - public
        - networkId
    Network:
      allOf:
        - $ref: '#/components/schemas/NewNetwork'
        - type: object
          properties:
            id:
              type: string
              format: uuid
              description: UUID of network
            createdAt:
              type: string
              format: date-time
            updatedAt:
              type: string
              format: date-time
          required:
            - id
            - createdAt
            - updatedAt
  parameters:
    deviceIdQuery:
      name: deviceId
      in: query
      schema:
        type: string
        description: 8 byte DeviceID as a hex string (if not provided will be auto-generated)
        example: d291d4d66bf0a955
        minLength: 16
        maxLength: 16
        pattern: ^[a-fA-F0-9]+$
    organisationIdQuery:
      name: organisationId
      in: query
      schema:
        type: string
        format: uuid
        description: ID of organisation
    rpcStatusQuery:
      name: status
      in: query
      schema:
        $ref: '#/components/schemas/DownlinkMessageStatus'
        description: Status of RPC message
    rpcShowExpiredQuery:
      name: showExpired
      in: query
      schema:
        type: boolean
        default: true
        description: Whether to show expired RPC messages
    rpcCommandIdQuery:
      name: rpcCommandId
      in: query
      schema:
        type: integer
        format: uint16
        description: ID of RPC command
    startTimeQuery:
      name: startTime
      in: query
      schema:
        type: string
        format: date-time
        description: The start time of the query (only return items on or after this time)
    endTimeQuery:
      name: endTime
      in: query
      schema:
        type: string
        format: date-time
        description: The end time of the query (only return items on or before this time)
    limitQuery:
      name: limit
      in: query
      schema:
        type: integer
        format: int32
        description: Maximum number of items to return
        minimum: 1
        maximum: 100
        default: 10
  securitySchemes:
    # BearerAuth:
    #   type: http
    #   scheme: bearer
    #   bearerFormat: JWT
    ApiKey:
      type: apiKey
      in: header
      name: x-api-key
security:
  - ApiKey: []
