---
openapi: 3.0.3
info:
  title: Quandify Backend API
  version: 1.0.0
  description: |
    <h3>IoT Device Management & Time Series Platform API</h3>
    <b>Authentication</b><br/>
    Use the <b>Authorize</b> button to log in via Keycloak.<br/><br/>

    <b>Important:</b> Swagger UI “Logout” only clears the access token.<br/>
    To fully log out and end the SSO session, use the Keycloak Account Console:<br/>
    <a href="https://auth.backend.quandify.com/auth/realms/quandify/account"
      target="_blank">
      Keycloak Account Console – Logout
    </a>

    <br/><br/>
    This API uses JWTs and determines the tenant based on the token issuer (<code>iss</code>).
components:
  securitySchemes:
    keycloak:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://auth.backend.quandify.com/auth/realms/quandify/protocol/openid-connect/auth
          tokenUrl: https://auth.backend.quandify.com/auth/realms/quandify/protocol/openid-connect/token
          scopes:
            openid: OpenID scope
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-Api-Key
      description: Quandify API key issued via Keycloak verification endpoint
    oidc:
      type: openIdConnect
      openIdConnectUrl: http://localhost:8180/realms/quandify/.well-known/openid-configuration
      description: Authentication
  schemas:
    Bucketing:
      enum:
      - HOUR
      - DAY
      - WEEK
      - MONTH
      - YEAR
      type: string
    ConsumptionSample:
      type: object
      properties:
        offsetSeconds:
          format: int64
          type: integer
        values:
          type: object
          additionalProperties: {}
    ConsumptionSeriesDto:
      type: object
      properties:
        deviceId:
          type: string
        serial:
          type: string
        measurement:
          type: string
        windowStart:
          $ref: "#/components/schemas/Instant"
        windowEnd:
          $ref: "#/components/schemas/Instant"
        samples:
          type: array
          items:
            $ref: "#/components/schemas/ConsumptionSample"
    CreateChildNodeRequest:
      type: object
      properties:
        name:
          type: string
        type:
          $ref: "#/components/schemas/NodeType"
        parentId:
          $ref: "#/components/schemas/QuID"
    CreateDeviceParams:
      type: object
      properties:
        type:
          $ref: "#/components/schemas/DeviceType"
        serial:
          type: string
        name:
          type: string
        subType:
          $ref: "#/components/schemas/DeviceSubType"
        parentNode:
          $ref: "#/components/schemas/QuID"
    CreateRootNodeRequest:
      type: object
      properties:
        name:
          type: string
    DayOfWeek:
      enum:
      - MONDAY
      - TUESDAY
      - WEDNESDAY
      - THURSDAY
      - FRIDAY
      - SATURDAY
      - SUNDAY
      type: string
    DeviceBrokerDetails:
      type: object
      properties:
        username:
          type: string
        password:
          type: string
        brokerHost:
          type: string
        brokerPort:
          format: int32
          type: integer
        pubTopic:
          type: string
        subTopic:
          type: string
        keepAlive:
          format: int32
          type: integer
        qos:
          format: int32
          type: integer
    DeviceDetails:
      type: object
      properties:
        id:
          $ref: "#/components/schemas/QuID"
        serial:
          type: string
        status:
          $ref: "#/components/schemas/DeviceStatus"
        name:
          type: string
        firmwareVersion:
          type: string
        deviceType:
          $ref: "#/components/schemas/DeviceType"
        lastSeen:
          $ref: "#/components/schemas/Instant"
    DeviceMeasurementRequest:
      type: object
      properties:
        start:
          $ref: "#/components/schemas/ZonedDateTime"
        end:
          $ref: "#/components/schemas/ZonedDateTime"
        fields:
          uniqueItems: true
          type: array
          items:
            $ref: "#/components/schemas/Field"
    DeviceProvisioningDetails:
      type: object
      properties:
        id:
          $ref: "#/components/schemas/QuID"
        serial:
          type: string
        status:
          $ref: "#/components/schemas/DeviceStatus"
        broker:
          $ref: "#/components/schemas/DeviceBrokerDetails"
    DeviceStatus:
      enum:
      - PROVISIONING
      - NORMAL
      - DISCONNECTED
      - DELETED
      type: string
    DeviceSubType:
      enum:
      - HOT
      - COLD
      - UNKNOWN
      type: string
    DeviceType:
      enum:
      - WATER_GRIP
      - CUBIC_SECURE
      - CUBIC_DETECTOR
      - CUBIC_METER
      type: string
    DownlinkDto:
      type: object
      properties:
        id:
          $ref: "#/components/schemas/QuID"
        serial:
          type: string
        downlinkType:
          type: string
        error:
          type: string
        sentAt:
          $ref: "#/components/schemas/Instant"
        pubAckAt:
          $ref: "#/components/schemas/Instant"
        publishedAt:
          $ref: "#/components/schemas/Instant"
        deliveredAt:
          $ref: "#/components/schemas/Instant"
        ackedAt:
          $ref: "#/components/schemas/Instant"
        expireAt:
          $ref: "#/components/schemas/Instant"
        payload:
          $ref: "#/components/schemas/JsonNode"
    Duration:
      format: duration
      type: string
      example: P1D
    Field:
      enum:
      - flowRate
      - ambientTemperature
      - signalStrength
      - standardDeviation
      - temperature
      type: string
    Instant:
      format: date-time
      type: string
      example: 2022-03-10T16:15:50Z
    JsonNode:
      type: object
      properties:
        empty:
          type: boolean
        valueNode:
          type: boolean
        containerNode:
          type: boolean
        missingNode:
          type: boolean
        array:
          type: boolean
        object:
          type: boolean
        nodeType:
          $ref: "#/components/schemas/JsonNodeType"
        pojo:
          type: boolean
        number:
          type: boolean
        integralNumber:
          type: boolean
        floatingPointNumber:
          type: boolean
        short:
          type: boolean
        int:
          type: boolean
        long:
          type: boolean
        float:
          type: boolean
        double:
          type: boolean
        bigDecimal:
          type: boolean
        bigInteger:
          type: boolean
        textual:
          type: boolean
        boolean:
          type: boolean
        "null":
          type: boolean
        binary:
          type: boolean
    JsonNodeType:
      enum:
      - ARRAY
      - BINARY
      - BOOLEAN
      - MISSING
      - "NULL"
      - NUMBER
      - OBJECT
      - POJO
      - STRING
      type: string
    LocalDateTime:
      format: date-time
      type: string
      example: 2022-03-10T12:15:50
    LocalTime:
      format: local-time
      type: string
      externalDocs:
        description: As defined by 'partial-time' in RFC3339
        url: https://www.rfc-editor.org/rfc/rfc3339.html#section-5.6
      example: 13:45:30.123456789
    MeasurementData:
      type: object
      properties:
        from:
          $ref: "#/components/schemas/ZonedDateTime"
        timestep:
          format: double
          type: number
        data:
          type: array
          items:
            format: double
            type: number
    MeasurementResponse:
      type: object
      properties:
        deviceId:
          $ref: "#/components/schemas/QuID"
        fields:
          type: array
          items:
            type: string
        from:
          $ref: "#/components/schemas/ZonedDateTime"
        to:
          $ref: "#/components/schemas/ZonedDateTime"
        values:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/MeasurementData"
    Month:
      enum:
      - JANUARY
      - FEBRUARY
      - MARCH
      - APRIL
      - MAY
      - JUNE
      - JULY
      - AUGUST
      - SEPTEMBER
      - OCTOBER
      - NOVEMBER
      - DECEMBER
      type: string
    NodeDto:
      type: object
      properties:
        id:
          $ref: "#/components/schemas/QuID"
        name:
          type: string
        type:
          type: string
        parentId:
          $ref: "#/components/schemas/QuID"
        hasChildren:
          type: boolean
    NodeType:
      enum:
      - REGION
      - GROUP
      - PROPERTY
      - BUILDING
      - SUITE
      - DEVICE
      type: string
    PermissionDto:
      type: object
      properties:
        userId:
          $ref: "#/components/schemas/UUID"
        role:
          type: string
    PermissionGrantRequest:
      type: object
      properties:
        userId:
          $ref: "#/components/schemas/UUID"
        role:
          type: string
    QuID:
      format: quid
      description: "Quandify ID: 2-char base32 type prefix + 26-char base32 ULID (lowercase)"
      pattern: "^[0-9a-v]{28}$"
      type: string
      example: de0123456789abcdefghijklmnop
    SettingChange:
      type: object
      properties:
        currentValue: {}
        desiredValue: {}
    SettingsDiff:
      type: object
      properties:
        added:
          type: object
          additionalProperties: {}
        modified:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/SettingChange"
        removed:
          type: object
          additionalProperties: {}
        unchanged:
          type: object
          additionalProperties: {}
        hasPendingChanges:
          type: boolean
    TimeDefinition:
      enum:
      - UTC
      - WALL
      - STANDARD
      type: string
    UUID:
      format: uuid
      pattern: "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"
      type: string
    UnifiedTree:
      type: object
      properties:
        id:
          $ref: "#/components/schemas/QuID"
        name:
          type: string
        type:
          type: string
        status:
          type: string
        children:
          type: array
          items:
            $ref: "#/components/schemas/UnifiedTree"
    UpdateNodeRequest:
      type: object
      properties:
        name:
          type: string
        type:
          type: string
        newParentId:
          $ref: "#/components/schemas/QuID"
    ZoneId:
      type: object
      properties:
        id:
          type: string
        rules:
          $ref: "#/components/schemas/ZoneRules"
    ZoneOffset:
      type: object
      properties:
        totalSeconds:
          format: int32
          type: integer
    ZoneOffsetTransition:
      type: object
      properties:
        epochSecond:
          format: int64
          type: integer
        transition:
          $ref: "#/components/schemas/LocalDateTime"
        offsetBefore:
          $ref: "#/components/schemas/ZoneOffset"
        offsetAfter:
          $ref: "#/components/schemas/ZoneOffset"
        instant:
          $ref: "#/components/schemas/Instant"
        dateTimeBefore:
          $ref: "#/components/schemas/LocalDateTime"
        dateTimeAfter:
          $ref: "#/components/schemas/LocalDateTime"
        duration:
          $ref: "#/components/schemas/Duration"
        durationSeconds:
          format: int32
          type: integer
        gap:
          type: boolean
        overlap:
          type: boolean
        validOffsets:
          type: array
          items:
            $ref: "#/components/schemas/ZoneOffset"
    ZoneOffsetTransitionRule:
      type: object
      properties:
        month:
          $ref: "#/components/schemas/Month"
        dom:
          format: int8
          type: integer
        dow:
          $ref: "#/components/schemas/DayOfWeek"
        time:
          $ref: "#/components/schemas/LocalTime"
        timeEndOfDay:
          type: boolean
        timeDefinition:
          $ref: "#/components/schemas/TimeDefinition"
        standardOffset:
          $ref: "#/components/schemas/ZoneOffset"
        offsetBefore:
          $ref: "#/components/schemas/ZoneOffset"
        offsetAfter:
          $ref: "#/components/schemas/ZoneOffset"
        dayOfMonthIndicator:
          format: int32
          type: integer
        dayOfWeek:
          $ref: "#/components/schemas/DayOfWeek"
        localTime:
          $ref: "#/components/schemas/LocalTime"
        midnightEndOfDay:
          type: boolean
    ZoneRules:
      type: object
      properties:
        standardTransitions:
          type: array
          items:
            format: int64
            type: integer
        standardOffsets:
          type: array
          items:
            $ref: "#/components/schemas/ZoneOffset"
        savingsInstantTransitions:
          type: array
          items:
            format: int64
            type: integer
        savingsLocalTransitions:
          type: array
          items:
            $ref: "#/components/schemas/LocalDateTime"
        wallOffsets:
          type: array
          items:
            $ref: "#/components/schemas/ZoneOffset"
        lastRules:
          type: array
          items:
            $ref: "#/components/schemas/ZoneOffsetTransitionRule"
        fixedOffset:
          type: boolean
        transitions:
          type: array
          items:
            $ref: "#/components/schemas/ZoneOffsetTransition"
        transitionRules:
          type: array
          items:
            $ref: "#/components/schemas/ZoneOffsetTransitionRule"
    ZonedDateTime:
      format: date-time
      type: string
      example: 2022-03-10T12:15:50-04:00
security:
- keycloak:
  - openid
- apiKeyAuth: []
paths:
  /api/v2/alert:
    get:
      responses:
        "204":
          description: No Content
      summary: Test Alert
      tags:
      - Alert Test Api
  /api/v2/consumption/devices/{deviceId}/aggregated:
    get:
      parameters:
      - name: deviceId
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/QuID"
      - name: bucketing
        in: query
        schema:
          $ref: "#/components/schemas/Bucketing"
      - name: end
        in: query
        schema:
          type: string
      - name: start
        in: query
        schema:
          type: string
      - name: timezone
        in: query
        schema:
          $ref: "#/components/schemas/ZoneId"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConsumptionSeriesDto"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      summary: Device Aggregated
      tags:
      - Consumption Api
      security:
      - keycloak: []
  /api/v2/consumption/devices/{deviceId}/flow:
    get:
      parameters:
      - name: deviceId
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/QuID"
      - name: end
        in: query
        schema:
          type: string
      - name: start
        in: query
        schema:
          type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConsumptionSeriesDto"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      summary: Device Flow
      tags:
      - Consumption Api
      security:
      - keycloak: []
  /api/v2/consumption/devices/{deviceId}/measurements:
    post:
      parameters:
      - name: deviceId
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/QuID"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DeviceMeasurementRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MeasurementResponse"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
        "400":
          description: Bad Request
      summary: Measurements
      tags:
      - Consumption Api
      security:
      - keycloak: []
  /api/v2/devices:
    get:
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/DeviceDetails"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      summary: List Claimed Devices
      tags:
      - Provisioning API
      security:
      - keycloak: []
  /api/v2/devices/create:
    post:
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateDeviceParams"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeviceProvisioningDetails"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
        "400":
          description: Bad Request
      summary: Create Device
      tags:
      - Provisioning API
      security:
      - keycloak: []
  /api/v2/devices/{deviceId}:
    delete:
      parameters:
      - name: deviceId
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/QuID"
      responses:
        "204":
          description: No Content
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      summary: Unclaim Device
      tags:
      - Provisioning API
      security:
      - keycloak: []
    get:
      parameters:
      - name: deviceId
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/QuID"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeviceDetails"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      summary: Get Device
      tags:
      - Provisioning API
      security:
      - keycloak: []
  /api/v2/devices/{deviceId}/downlink:
    get:
      parameters:
      - name: deviceId
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/QuID"
      - name: limit
        in: query
        schema:
          format: int32
          type: integer
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/DownlinkDto"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      summary: Get Downlinks
      tags:
      - Device Downlink API
      security:
      - keycloak: []
  /api/v2/devices/{deviceId}/settings:
    get:
      summary: Get current settings
      description: Retrieve the current settings of a device
      tags:
      - Device Settings
      parameters:
      - name: deviceId
        in: path
        required: true
        schema:
          type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      security:
      - keycloak: []
  /api/v2/devices/{deviceId}/settings/desired:
    put:
      summary: Update desired settings
      description: Update desired settings for a device. Changes will be sent to device
        on next connection.
      tags:
      - Device Settings
      parameters:
      - name: deviceId
        in: path
        required: true
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              additionalProperties: {}
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: string
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
        "400":
          description: Bad Request
      security:
      - keycloak: []
  /api/v2/devices/{deviceId}/settings/diff:
    get:
      summary: Get settings diff
      description: "Compare desired vs current settings for a device, showing pending\
        \ changes"
      tags:
      - Device Settings
      parameters:
      - name: deviceId
        in: path
        required: true
        schema:
          type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SettingsDiff"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      security:
      - keycloak: []
  /api/v2/devices/{deviceId}/settings/pending:
    get:
      summary: Check pending changes
      description: Check if device has any pending settings changes
      tags:
      - Device Settings
      parameters:
      - name: deviceId
        in: path
        required: true
        schema:
          type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: boolean
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      security:
      - keycloak: []
  /api/v2/devices/{deviceId}/settings/reset:
    post:
      summary: Reset desired settings
      description: Reset desired settings to match current settings (cancels all pending
        changes)
      tags:
      - Device Settings
      parameters:
      - name: deviceId
        in: path
        required: true
        schema:
          type: string
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: string
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      security:
      - keycloak: []
  /api/v2/nodes/child:
    post:
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateChildNodeRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NodeDto"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
        "400":
          description: Bad Request
      summary: Create Child Node
      tags:
      - Node Api
      security:
      - keycloak: []
  /api/v2/nodes/me/roots:
    get:
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/NodeDto"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      summary: My Roots
      tags:
      - Node Api
      security:
      - keycloak: []
  /api/v2/nodes/root:
    post:
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateRootNodeRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NodeDto"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
        "400":
          description: Bad Request
      summary: Create Root Node
      tags:
      - Node Api
      security:
      - keycloak: []
  /api/v2/nodes/{id}:
    patch:
      parameters:
      - name: id
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/QuID"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateNodeRequest"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NodeDto"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      summary: Update
      tags:
      - Node Api
      security:
      - keycloak: []
    get:
      parameters:
      - name: id
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/QuID"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NodeDto"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      summary: Get
      tags:
      - Node Api
      security:
      - keycloak: []
    delete:
      parameters:
      - name: id
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/QuID"
      responses:
        "204":
          description: No Content
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      summary: Delete
      tags:
      - Node Api
      security:
      - keycloak: []
  /api/v2/nodes/{id}/children:
    get:
      parameters:
      - name: id
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/QuID"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/NodeDto"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      summary: Children
      tags:
      - Node Api
      security:
      - keycloak: []
  /api/v2/nodes/{id}/parent:
    get:
      parameters:
      - name: id
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/QuID"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NodeDto"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      summary: Parent
      tags:
      - Node Api
      security:
      - keycloak: []
  /api/v2/nodes/{id}/permissions:
    get:
      parameters:
      - name: id
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/QuID"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/PermissionDto"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      summary: List Permissions
      tags:
      - Node Api
      security:
      - keycloak: []
    post:
      parameters:
      - name: id
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/QuID"
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PermissionGrantRequest"
        required: true
      responses:
        "201":
          description: Created
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
        "400":
          description: Bad Request
      summary: Grant Permission
      tags:
      - Node Api
      security:
      - keycloak: []
  /api/v2/nodes/{id}/permissions/{userId}:
    delete:
      parameters:
      - name: id
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/QuID"
      - name: userId
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/UUID"
      responses:
        "204":
          description: No Content
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      summary: Revoke Permission
      tags:
      - Node Api
      security:
      - keycloak: []
  /api/v2/nodes/{id}/subtree:
    get:
      parameters:
      - name: id
        in: path
        required: true
        schema:
          $ref: "#/components/schemas/QuID"
      - name: depth
        in: query
        schema:
          format: int32
          type: integer
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UnifiedTree"
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed
      summary: Subtree
      tags:
      - Node Api
      security:
      - keycloak: []
  /organization/{organizationId}/nodes/consumption:
    get:
      parameters:
      - name: organizationId
        in: path
        required: true
        schema:
          type: string
      - name: from
        in: query
        schema:
          format: int64
          type: integer
      - name: timezone
        in: query
        schema:
          type: string
      - name: to
        in: query
        schema:
          format: int64
          type: integer
      - name: truncate
        in: query
        schema:
          type: string
      responses:
        "200":
          description: OK
      summary: Get Nodes Consumption
      tags:
      - Nodes Api
  /organization/{organizationId}/nodes/detailed-consumption:
    get:
      parameters:
      - name: organizationId
        in: path
        required: true
        schema:
          type: string
      - name: from
        in: query
        schema:
          format: int64
          type: integer
      - name: timezone
        in: query
        schema:
          type: string
      - name: to
        in: query
        schema:
          format: int64
          type: integer
      - name: truncate
        in: query
        schema:
          type: string
      responses:
        "200":
          description: OK
      summary: Get Nodes Detailed Consumption
      tags:
      - Nodes Api
  /organization/{organizationId}/nodes/measurements:
    get:
      parameters:
      - name: organizationId
        in: path
        required: true
        schema:
          type: string
      - name: from
        in: query
        schema:
          format: int64
          type: integer
      - name: to
        in: query
        schema:
          format: int64
          type: integer
      - name: type
        in: query
        schema:
          type: string
      responses:
        "200":
          description: OK
      summary: Get Nodes Measurements
      tags:
      - Nodes Api
  /organization/{organizationId}/nodes/{nodeId}/consumption:
    get:
      parameters:
      - name: nodeId
        in: path
        required: true
        schema:
          type: string
      - name: organizationId
        in: path
        required: true
        schema:
          type: string
      - name: from
        in: query
        schema:
          format: int64
          type: integer
      - name: timezone
        in: query
        schema:
          type: string
      - name: to
        in: query
        schema:
          format: int64
          type: integer
      - name: truncate
        in: query
        schema:
          type: string
      responses:
        "200":
          description: OK
      summary: Get Node Consumption
      tags:
      - Nodes Api
  /organization/{organizationId}/nodes/{nodeId}/detailed-consumption:
    get:
      parameters:
      - name: nodeId
        in: path
        required: true
        schema:
          type: string
      - name: organizationId
        in: path
        required: true
        schema:
          type: string
      - name: from
        in: query
        schema:
          format: int64
          type: integer
      - name: timezone
        in: query
        schema:
          type: string
      - name: to
        in: query
        schema:
          format: int64
          type: integer
      - name: truncate
        in: query
        schema:
          type: string
      responses:
        "200":
          description: OK
      summary: Get Node Detailed Consumption
      tags:
      - Nodes Api
  /organization/{organizationId}/nodes/{nodeId}/measurements:
    get:
      parameters:
      - name: nodeId
        in: path
        required: true
        schema:
          type: string
      - name: organizationId
        in: path
        required: true
        schema:
          type: string
      - name: from
        in: query
        schema:
          format: int64
          type: integer
      - name: to
        in: query
        schema:
          format: int64
          type: integer
      - name: type
        in: query
        schema:
          type: string
      responses:
        "200":
          description: OK
      summary: Get Node Measurements
      tags:
      - Nodes Api
tags:
- name: Device Settings
  description: Device configuration and settings management
