openapi: 3.1.0
info:
  title: BUSY Bar HTTP API
  description: HTTP API for BUSY Bar web server
  version: 19.0.0
  contact:
    name: tbd

security:
  - ApiKeyAuth: []
  - {}

paths:
  /api/version:
    get:
      tags:
        - System
      summary: Get API version information
      description: Retrieves API version
      operationId: getVersion
      responses:
        "200":
          description: Version information retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/VersionInfo"
        "500":
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/transport:
    get:
      tags:
        - System
      summary: Get device network connection info
      description: Retrieves device transport type (usb/wifi)
      operationId: getTransport
      responses:
        "200":
          description: Information retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NetworkInterfaceInfo"
        "500":
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/access:
    get:
      tags:
        - Settings
      summary: Get HTTP API access over Wi-Fi configuration
      description: Get HTTP API access over Wi-Fi configuration
      operationId: getHttpAccess
      responses:
        "200":
          description: Information retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HttpAccessInfo"
    post:
      tags:
        - Settings
      summary: Set HTTP API access over Wi-Fi configuration
      description: Set HTTP API access over Wi-Fi configuration
      operationId: setHttpAccess
      parameters:
        - name: mode
          in: query
          required: true
          schema:
            type: string
            enum: ["disabled", "enabled", "key"]
          description: Access mode
          example: "key"
        - name: key
          in: query
          required: false
          schema:
            type: string
            pattern: "^[0-9]{4,10}$"
          description: Access key (4-10 digits length). Required when mode is "key".
          example: "12345678"
      responses:
        "200":
          description: Set successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid request data
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/name:
    get:
      tags:
        - Settings
      summary: Get current device name
      description: Get current device name
      responses:
        "200":
          description: Information retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NameInfo"

    post:
      tags:
        - Settings
      summary: Set new device name
      description: Set new device name
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/NameInfo"
      responses:
        "200":
          description: New name successfully set
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid name parameter, or failed to store new name
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/update:
    post:
      tags:
        - Updater
      summary: Update firmware
      description: Uploads a firmware update package (TAR file) and initiates the update process.
      operationId: updateFirmware
      parameters: []
      requestBody:
        required: true
        content:
          application/octet-stream:
            schema:
              type: string
              format: binary
              description: Firmware update TAR file.
      responses:
        "200":
          description: Update initiated successfully. The device will reboot.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid parameters, invalid TAR file, or update preparation failed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "413":
          description: Update package too large.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "500":
          description: Internal server error during update process.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/update/check:
    post:
      tags:
        - Updater
      summary: Start firmware update check
      description: Initiates an asynchronous check for available firmware updates.
      operationId: checkFirmwareUpdate
      responses:
        "200":
          description: Update check started successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "409":
          description: Update check already in progress
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "500":
          description: Failed to start update check
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/update/status:
    get:
      tags:
        - Updater
      summary: Get firmware update status
      description: Returns current update and check status including progress information.
      operationId: getFirmwareUpdateStatus
      responses:
        "200":
          description: Status retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UpdateStatus"

  /api/update/changelog:
    get:
      tags:
        - Updater
      summary: Get update changelog
      description: Returns the changelog for a specific firmware version.
      operationId: getUpdateChangelog
      parameters:
        - name: version
          in: query
          required: true
          schema:
            type: string
          description: Firmware version to get changelog for
          example: "1.2.3"
      responses:
        "200":
          description: Changelog retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  changelog:
                    type: string
                    description: Changelog text
        "400":
          description: Version parameter missing, update not available, or version mismatch
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/update/install:
    post:
      tags:
        - Updater
      summary: Install firmware update
      description: |
        Starts asynchronous firmware installation from a remote URL.
        The update process (download, SHA verification, unpack, prepare, reboot) runs in the background.
        Use /api/update/status to monitor progress.
      operationId: installFirmwareUpdate
      parameters:
        - name: version
          in: query
          required: true
          schema:
            type: string
          description: Firmware version to install
          example: "1.2.3"
      responses:
        "200":
          description: Update installation started successfully in background
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Version parameter missing, update not available, or version mismatch
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: Update already in progress
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "500":
          description: Failed to start background installation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: Battery too low for update
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/update/abort_download:
    post:
      tags:
        - Updater
      summary: Abort ongoing firmware download
      description: Signals the updater to abort an ongoing download operation.
      operationId: abortFirmwareDownload
      responses:
        "200":
          description: Abort signal sent successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"

  /api/update/autoupdate:
    get:
      tags:
        - Updater
      summary: Get autoupdate settings
      description: Returns current autoupdate configuration
      operationId: getAutoupdateSettings
      responses:
        "200":
          description: Settings retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AutoupdateSettings"
        "500":
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - Updater
      summary: Set autoupdate settings
      description: Updates autoupdate configuration. All fields are optional - only provided fields are updated.
      operationId: setAutoupdateSettings
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AutoupdateSettings"
      responses:
        "200":
          description: Settings updated successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid time format (expected HH:MM)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "500":
          description: Failed to apply settings
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/assets/upload:
    post:
      tags:
        - Assets
      summary: Upload asset file with app ID
      description: Uploads a file to a specific app's assets directory
      operationId: uploadAssetWithAppId
      parameters:
        - name: application_name
          in: query
          required: true
          schema:
            type: string
            pattern: "^[a-zA-Z0-9._-]+$"
          description: Application ID for organizing assets
          example: "my_app"
        - name: file
          in: query
          required: true
          schema:
            type: string
            pattern: "^[a-zA-Z0-9._-]+$"
          description: Filename for the uploaded asset
          example: "data.png"
      requestBody:
        required: true
        content:
          application/octet-stream:
            schema:
              type: string
              format: binary
              description: File data to upload as raw binary content
      responses:
        "200":
          description: File uploaded successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid parameters or upload failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "413":
          description: File too large
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

    delete:
      tags:
        - Assets
      summary: Delete app assets
      description: Deletes all assets for a specific app ID
      operationId: deleteAppAssets
      parameters:
        - name: application_name
          in: query
          required: true
          schema:
            type: string
            pattern: "^[a-zA-Z0-9._-]+$"
          description: Application ID whose assets should be deleted
          example: "my_app"
      responses:
        "200":
          description: Assets deleted successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "500":
          description: Delete failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/storage/write:
    post:
      tags:
        - Storage
      summary: Upload file to internal storage
      description: Uploads a file to a specified path
      operationId: writeStorageFile
      parameters:
        - name: path
          in: query
          required: true
          schema:
            type: string
            pattern: "^/ext(/[a-zA-Z0-9._\\-]*)*$"
          description: Path for the uploaded file
          example: "/ext/test.png"
      requestBody:
        required: true
        content:
          application/octet-stream:
            schema:
              type: string
              format: binary
              description: File data to upload as raw binary content
      responses:
        "200":
          description: File uploaded successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid parameters or upload failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "413":
          description: File too large
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/storage/read:
    get:
      tags:
        - Storage
      summary: Download file from internal storage
      description: Downloads a file from a specified path
      operationId: readStorageFile
      parameters:
        - name: path
          in: query
          required: true
          schema:
            type: string
            pattern: "^/ext(/[a-zA-Z0-9._\\-]*)*$"
          description: Path to the file
          example: "/ext/test.png"
      responses:
        "200":
          description: File downloaded successfully
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
                description: File data as raw binary content
        "400":
          description: Invalid parameters or file not exists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/storage/list:
    get:
      tags:
        - Storage
      summary: List files on internal storage
      operationId: listStorageFiles
      parameters:
        - name: path
          in: query
          required: true
          schema:
            type: string
            pattern: "^/ext(/[a-zA-Z0-9._\\-]*)*$"
          description: Path to the file
          example: "/ext"
      responses:
        "200":
          description: Directory contents read successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StorageList"
        "400":
          description: Invalid parameters or directory does not exist
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/storage/remove:
    delete:
      tags:
        - Storage
      summary: Remove a file on internal storage
      description: Removes a file with a specified path
      operationId: removeStorageFile
      parameters:
        - name: path
          in: query
          required: true
          schema:
            type: string
            pattern: "^/ext(/[a-zA-Z0-9._\\-]*)*$"
          description: Path of a file to remove
          example: "/ext/test.png"
      responses:
        "200":
          description: File deleted successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid path or deletion failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/storage/mkdir:
    post:
      tags:
        - Storage
      summary: Create a directory on internal storage
      description: Creates a new directory with a specified path
      operationId: createStorageDir
      parameters:
        - name: path
          in: query
          required: true
          schema:
            type: string
            pattern: "^/ext(/[a-zA-Z0-9._\\-]*)*$"
          description: Path to a new directory
          example: "/ext/newdir"
      responses:
        "200":
          description: Directory created successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid path or creation failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/storage/rename:
    post:
      tags:
        - Storage
      summary: Rename/move a file
      description: Moves a file to a new location
      operationId: RenameStorageFile
      parameters:
        - name: path
          in: query
          required: true
          schema:
            type: string
            pattern: "^/ext(/[a-zA-Z0-9._\\-]*)*$"
          description: Old location path
          example: "/ext/old_name.txt"
        - name: new_path
          in: query
          required: true
          schema:
            type: string
            pattern: "^/ext(/[a-zA-Z0-9._\\-]*)*$"
          description: New location path
          example: "/ext/new_name.txt"
      responses:
        "200":
          description: Renamed successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid path or operation failed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/storage/status:
    get:
      tags:
        - Storage
      summary: Show storage usage
      operationId: getStorageStatus
      responses:
        "200":
          description: Storage status queried successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StorageStatus"
        "400":
          description: Invalid parameters or storage doesn't exist
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/display/draw:
    post:
      tags:
        - Assets
      summary: Draw on display
      description: |
        Sends drawing data to the display.
        Supports JSON-defined display elements.
      operationId: drawOnDisplay
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DisplayElements"
      responses:
        "200":
          description: Drawing command executed successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid drawing data
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: Requested priority level is below that of currently active app
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "503":
          description: Failed to load canvas app
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    delete:
      tags:
        - Assets
      summary: Clear display
      description: Deletes display elements drawn by the Canvas application. If application_name is specified, only elements for that app are removed.
      operationId: clearDisplay
      parameters:
        - name: application_name
          in: query
          required: false
          schema:
            type: string
          description: Application identifier
          example: "my_app"
      responses:
        "200":
          description: Display cleared successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"

  /api/display/brightness:
    get:
      tags:
        - Settings
      summary: Get display brightness
      description: Get brightness value for displays
      operationId: getDisplayBrightness
      responses:
        "200":
          description: Information retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DisplayBrightnessInfo"
    post:
      tags:
        - Settings
      summary: Set display brightness
      description: |
        Set brightness for one or both displays
      operationId: setDisplayBrightness
      parameters:
        - name: value
          in: query
          required: true
          schema:
            type: string
            pattern: "^(auto|[0-9]{1,2}|100)$"
          description: Displays brightness (0-100/auto)
          example: "50"
      responses:
        "200":
          description: Brightness set successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid request data
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/audio/play:
    post:
      tags:
        - Assets
      summary: Play audio file
      description: |
        Plays an audio file from the assets directory.
        Supported formats include .snd files.
      operationId: playAudio
      parameters:
        - name: application_name
          in: query
          required: true
          schema:
            type: string
            pattern: "^[a-zA-Z0-9._-]+$"
          description: Application ID for organizing assets
          example: "my_app"
        - name: path
          in: query
          required: true
          schema:
            type: string
            pattern: "^[a-zA-Z0-9._/-]+$"
          description: Path to audio file within app's assets directory
          example: "data.snd"
      responses:
        "200":
          description: Audio playback started successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid file path or file not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "500":
          description: Audio system error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

    delete:
      tags:
        - Assets
      summary: Stop audio playback
      description: Stops any currently playing audio
      operationId: stopAudio
      responses:
        "200":
          description: Audio playback stopped successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "500":
          description: Audio system error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/audio/volume:
    get:
      tags:
        - Settings
      summary: Get audio volume
      description: Get audio volume value
      operationId: getAudioVolume
      responses:
        "200":
          description: Information retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AudioVolumeInfo"
    post:
      tags:
        - Settings
      summary: Set audio volume
      description: Set audio volume value
      operationId: setAudioVolume
      parameters:
        - name: volume
          in: query
          required: true
          schema:
            type: number
          description: Audio volume (0-100)
          example: 50
        - name: silent
          in: query
          required: false
          schema:
            type: integer
            enum: [0, 1]
          description: Set volume silently (0 - play volume change sound(default), 1 - do not play sound)
          example: 1
      responses:
        "200":
          description: Volume set successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid request data
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/input:
    post:
      tags:
        - Input
      summary: Send input event
      description: Send single key press event
      operationId: setInputKey
      parameters:
        - name: key
          in: query
          required: true
          schema:
            type: string
            enum:
              [
                "up",
                "down",
                "ok",
                "back",
                "start",
                "busy",
                "custom",
                "off",
                "apps",
                "settings",
              ]
          description: Key name
          example: "ok"
      responses:
        "200":
          description: Input event sent successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid request data
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/status:
    get:
      tags:
        - System
      summary: Get device status
      description: Get device status
      operationId: getStatus
      responses:
        "200":
          description: Information retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Status"
        "500":
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/status/device:
    get:
      tags:
        - System
      summary: Get device info
      description: Get device info
      operationId: getStatusDevice
      responses:
        "200":
          description: Information retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StatusDevice"
        "500":
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/status/firmware:
    get:
      tags:
        - System
      summary: Get firmware info
      description: Get firmware info
      operationId: getStatusFirmware
      responses:
        "200":
          description: Information retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StatusFirmware"
        "500":
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/status/system:
    get:
      tags:
        - System
      summary: Get system status
      description: Get system status
      operationId: getStatusSystem
      responses:
        "200":
          description: Information retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StatusSystem"
        "500":
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/status/power:
    get:
      tags:
        - System
      summary: Get power status
      description: Get power status
      operationId: getStatusPower
      responses:
        "200":
          description: Information retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StatusPower"
        "500":
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/status/ws:
    get:
      tags:
        - Streaming
      summary: Device status streaming WebSocket endpoint
      description: |
        WebSocket connection for real-time device status and screen streaming.
        Upgrade from HTTP to WebSocket protocol is required.
        After connection, client must enable streaming by sending JSON: {"enable": true}
      operationId: connectWebSocket
      responses:
        "101":
          description: WebSocket connection established
        "400":
          description: Exceed max clients count
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/wifi/status:
    get:
      tags:
        - Wi-Fi
      description: Returns current Wi-Fi status
      parameters: []
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StatusResponse"

  /api/wifi/connect:
    post:
      tags:
        - Wi-Fi
      description: Attempts to connect to Wi-Fi using config
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConnectRequestConfig"
      responses:
        "200":
          description: Network connection established
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Already connected
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/wifi/disconnect:
    post:
      tags:
        - Wi-Fi
      description: Disconnects from Wi-Fi
      parameters: []
      responses:
        "200":
          description: Network connection terminated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Already disconnected
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/wifi/networks:
    get:
      tags:
        - Wi-Fi
      operationId: getWifiNetworks
      description: Scans environment for available Wi-Fi networks
      parameters: []
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/NetworkResponse"
        "400":
          description: Scan not possible when connected
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/screen:
    get:
      tags:
        - Streaming
      summary: Get single frame for requested screen
      parameters:
        - name: display
          in: query
          required: true
          schema:
            type: integer
            minimum: 0
            maximum: 1
          description: Type of the display Front = 0, Back = 1
          example: 0
      responses:
        "200":
          description: OK
          content:
            image/bmp:
              schema:
                $ref: "#/components/schemas/ScreenResponse"
        "400":
          description: Wrong display
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/ble/enable:
    post:
      tags:
        - BLE
      summary: Enable BLE
      description: Enables BLE module and starts advertising
      parameters: []
      responses:
        "200":
          description: BLE enabled
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "503":
          description: Unable to start BLE
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/ble/disable:
    post:
      tags:
        - BLE
      summary: Disable BLE
      description: Stops advertising
      parameters: []
      responses:
        "200":
          description: BLE disabled
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "503":
          description: Unable to stop BLE
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/ble/pairing:
    delete:
      tags:
        - BLE
      summary: Remove pairing
      description: Remove pairing with previous device
      parameters: []
      responses:
        "200":
          description: Pairing removed, now device is discoverable
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "503":
          description: Failed to remove because BLE is not initialized or pairing was already removed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/ble/status:
    get:
      tags:
        - BLE
      description: Returns current BLE status
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BleStatusResponse"
        "503":
          description: Failed to get BLE status, because of an error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/time:
    get:
      tags:
        - Time
      summary: Get current timestamp with timezone
      description: Retrieves the current timestamp from RTC with timezone in ISO 8601 format
      operationId: getTime
      responses:
        "200":
          description: Timestamp retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TimestampInfo"

  /api/account:
    delete:
      tags:
        - Account
      summary: Unlink device from account
      description: Removes account linking data
      operationId: unlinkAccount
      responses:
        "200":
          description: Done successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"

  /api/account/link:
    post:
      tags:
        - Account
      summary: Link device to account
      description: Requests account link PIN. Works only if device is connected to MQTT and is not linked to account
      operationId: linkAccount
      responses:
        "200":
          description: Data retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AccountLink"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/account/info:
    get:
      tags:
        - Account
      summary: Get linked account info
      description: Retrieves linked account data
      operationId: getAccountInfo
      responses:
        "200":
          description: Data retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AccountInfo"

  /api/account/status:
    get:
      tags:
        - Account
      summary: Get MQTT status info
      description: Retrieves MQTT status
      operationId: getAccountStatus
      responses:
        "200":
          description: Data retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AccountStatus"

  /api/account/profile:
    get:
      tags:
        - Account
      summary: Get MQTT profile
      description: Retrieves MQTT backend type (dev/prod/local)
      operationId: getAccountProfile
      responses:
        "200":
          description: Data retrieved successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AccountProfile"
    post:
      tags:
        - Account
      summary: Set MQTT profile
      description: Sets MQTT backend type (dev/prod/local)
      operationId: setAccountProfile
      parameters:
        - name: profile
          in: query
          required: true
          schema:
            type: string
            enum: ["dev", "prod", "local", "custom"]
          example: "dev"
        - name: custom_url
          in: query
          schema:
            type: string
            example: "mqtts://mqtt.example.com:8883"
      responses:
        "200":
          description: Set successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/time/timestamp:
    post:
      tags:
        - Time
      summary: Set current timestamp
      description: |
        Sets the RTC timestamp in ISO 8601 format. Time zone qualifier (e.g. Z of UTC or +hh:mm for local time) is required.
      operationId: setTimeTimestamp
      parameters:
        - name: timestamp
          in: query
          required: true
          schema:
            type: string
            pattern: "^20[0-9]{2}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](Z|[+-]([01][0-9]|2[0-3])(:?[0-5][0-9])?)$"
          description: ISO 8601 timestamp (e.g., 2025-10-02T14:30:45+02:00 for local time or 2025-10-02T14:30:45Z for UTC)
          example: "2025-10-02T14:30:45+0100"
      responses:
        "200":
          description: Timestamp set successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid timestamp format or value
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/time/timezone:
    get:
      tags:
        - Time
      summary: Get timezone
      description: Get current timezone name
      operationId: getTimeTimezone
      responses:
        "200":
          description: Timezone got successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TimezoneInfo"
        "400":
          description: Invalid timezone offset
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - Time
      summary: Set timezone
      description: Sets the timezone name. Use /api/time/tzlist to get available names list.
      operationId: setTimeTimezone
      parameters:
        - name: timezone
          in: query
          required: true
          schema:
            type: string
            pattern: "^[A-Za-z][A-Za-z0-9 _+\\-]{0,50}$"
          description: Timezone name (use /api/time/tzlist to get available names)
          example: "Berlin"
      responses:
        "200":
          description: Timezone set successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Invalid timezone offset
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/time/tzlist:
    get:
      tags:
        - Time
      summary: Get list of supported time zones
      description: Retrieves the list of time zones accepted by /api/time/timezone
      operationId: getTimeTzlist
      responses:
        "200":
          description: Got the list successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TimezoneListResponse"
        "400":
          description: Error getting time zone list
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/busy/snapshot:
    get:
      tags:
        - Busy
      summary: Get BUSY timer snapshot
      description: Gets the current state of the BUSY timer in snapshot form
      operationId: getBusySnapshot
      responses:
        "200":
          description: Got snapshot successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BusySnapshot"
        "400":
          description: Error getting snapshot
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    put:
      tags:
        - Busy
      summary: Set BUSY timer snapshot
      description: Run the timer starting from the given snapshot
      operationId: setBusySnapshot
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BusySnapshot"
      responses:
        "200":
          description: Snapshot successfully set
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Error setting snapshot
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/busy/profiles/{slot}:
    get:
      tags:
        - Busy
      summary: Get BUSY timer profile
      description: Gets the BUSY timer profile under specified slot
      operationId: getBusyProfile
      parameters:
        - name: slot
          in: path
          required: true
          schema:
            $ref: "#/components/schemas/BusyProfileSlot"
      responses:
        "200":
          description: Got profile successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BusyProfile"
        "400":
          description: Error getting profile
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

    put:
      tags:
        - Busy
      summary: Set BUSY time profile
      description: Sets the BUSY timer profile under specified slot
      operationId: setBusyProfile
      parameters:
        - name: slot
          in: path
          required: true
          schema:
            $ref: "#/components/schemas/BusyProfileSlot"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BusyProfile"
      responses:
        "200":
          description: Profile successfully set
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "400":
          description: Error setting profile
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/smart_home/pairing:
    get:
      tags:
        - Smart home
      summary: Smart home commissioning status
      operationId: getSmartHomeCommissioningStatus
      parameters: []
      responses:
        "200":
          description: Successfully got smart home commissioning status
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SmartHomePairingInfo"
    post:
      tags:
        - Smart home
      summary: Link device to a smart home
      operationId: startSmartHomePairing
      parameters: []
      responses:
        "200":
          description: Successfully started smart home pairing
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SmartHomePairingPayload"
        "503":
          description: Internal smart home service is broken
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    delete:
      tags:
        - Smart home
      summary: Erase all smart home links
      parameters: []
      responses:
        "200":
          description: Successfully erased all smart home pairing info, device restart is needed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "503":
          description: Internal smart home service is broken
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /api/smart_home/switch:
    get:
      tags:
        - Smart home
      summary: Get state of emulated smart home switch
      parameters: []
      responses:
        "200":
          description: Successfully got state of emulated smart home switch
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SmartHomeSwitchState"
        "503":
          description: Internal smart home service is broken
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - Smart home
      summary: Set state of emulated smart home switch
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SmartHomeSwitchState"
      responses:
        "200":
          description: Successfully set state of emulated smart home switch
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SuccessResponse"
        "503":
          description: Internal smart home service is broken
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Token

  schemas:
    SuccessResponse:
      type: object
      properties:
        result:
          type: string
          example: "OK"
          description: Success status message
      required:
        - result

    Error:
      type: object
      properties:
        error:
          type: string
          description: Error message
        code:
          type: integer
          description: Error code
      required:
        - error
      example:
        error: "Invalid parameter"
        code: 400

    VersionInfo:
      type: object
      properties:
        api_semver:
          type: string
          description: API SemVer
          example: "0.0.0"
      required:
        - api_semver
      example:
        api_semver: "0.0.0"

    NetworkInterfaceInfo:
      type: object
      properties:
        type:
          type: string
          description: Connection type
          enum: ["usb", "wifi"]
          example: "usb"
      required:
        - type
      example:
        type: "usb"

    UpdateStatus:
      type: object
      properties:
        install:
          type: object
          properties:
            is_allowed:
              type: boolean
              description: Whether update installation is allowed (battery check)
            event:
              type: string
              enum:
                [
                  "session_start",
                  "session_stop",
                  "action_begin",
                  "action_done",
                  "detail_change",
                  "action_progress",
                  "none",
                ]
              description: Current update event
            action:
              type: string
              enum:
                [
                  "download",
                  "sha_verification",
                  "unpack",
                  "prepare",
                  "apply",
                  "none",
                ]
              description: Current update action
            status:
              type: string
              enum:
                [
                  "ok",
                  "battery_low",
                  "busy",
                  "download_failure",
                  "download_abort",
                  "sha_mismatch",
                  "unpack_staging_dir_failure",
                  "unpack_archive_open_failure",
                  "unpack_archive_unpack_failure",
                  "install_manifest_not_found",
                  "install_manifest_invalid",
                  "install_session_config_failure",
                  "install_pointer_setup_failure",
                  "unknown_failure",
                ]
              description: Current or last operation status
            detail:
              type: string
              description: Optional status detail string
            download:
              type: object
              properties:
                speed_bytes_per_sec:
                  type: integer
                  description: Current download speed in bytes per second
                received_bytes:
                  type: integer
                  description: Bytes received so far
                total_bytes:
                  type: integer
                  description: Total download size in bytes
        check:
          type: object
          properties:
            available_version:
              type: string
              description: Version of available update (empty if none)
            event:
              type: string
              enum: ["start", "stop", "none"]
              description: Current check event
            status:
              type: string
              enum: ["available", "not_available", "failure", "none"]
              description: Check result status
      example:
        install:
          is_allowed: true
          event: "none"
          action: "none"
          status: "ok"
          detail: ""
          download:
            speed_bytes_per_sec: 0
            received_bytes: 0
            total_bytes: 0
        check:
          available_version: "1.2.3"
          event: "stop"
          status: "available"

    AutoupdateSettings:
      type: object
      description: Autoupdate configuration settings. All fields are optional for POST requests.
      properties:
        is_enabled:
          type: boolean
          description: Whether automatic updates are enabled
          example: true
        interval_start:
          type: string
          description: Start of autoupdate window in HH:MM format (e.g., "08:00")
          pattern: "^([0-1][0-9]|2[0-3]):[0-5][0-9]$"
          example: "00:00"
        interval_end:
          type: string
          description: End of autoupdate window in HH:MM format (e.g., "23:59")
          pattern: "^([0-1][0-9]|2[0-3]):[0-5][0-9]$"
          example: "08:00"

    NameInfo:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          pattern: "^[a-zA-Z0-9 !()_=+;:,.?'|@#$%^&*\\[\\]{}/\\\\\"<>-]+$"
          description: Device name (letters, digits, spaces and common punctuation; no backtick or tilde)
          example: "BUSY bar"
      required:
        - name
      example:
        name: "BUSY bar"

    HttpAccessInfo:
      type: object
      properties:
        mode:
          type: string
          enum: ["disabled", "enabled", "key"]
          description: Access mode
          example: "key"
        key_valid:
          type: boolean
          description: Access key was set and is valid
          example: true

    StorageList:
      type: object
      properties:
        list:
          type: array
          items:
            $ref: "#/components/schemas/StorageListElement"
          description: Array of elements to display
      required:
        - list
      example:
        list:
          - type: "file"
            name: "test.png"
            size: 65535
          - type: "dir"
            name: "assets"

    StorageStatus:
      type: object
      properties:
        used_bytes:
          type: integer
          example: 123456
        free_bytes:
          type: integer
          example: 654321
        total_bytes:
          type: integer
          description: "Total size of the partition"
          example: 777777

    StorageListElement:
      type: object
      required:
        - type
        - name
      properties:
        type:
          type: string
          enum: [file, dir]
          description: Element type
        name:
          type: string
          pattern: "^[^\\x00-\\x1F\\\\/:*?\"<>|]+$"
          description: File or directory name
      discriminator:
        propertyName: type
        mapping:
          file: "#/components/schemas/StorageFileElement"
          dir: "#/components/schemas/StorageDirElement"

    StorageFileElement:
      allOf:
        - $ref: "#/components/schemas/StorageListElement"
        - type: object
          required:
            - size
          properties:
            size:
              type: integer
              description: File size in bytes

    StorageDirElement:
      allOf:
        - $ref: "#/components/schemas/StorageListElement"
        - type: object

    BinaryUpload:
      type: string
      format: binary
      description: Binary data upload

    FileUpload:
      type: object
      properties:
        file:
          type: string
          format: binary
          description: File to upload
      required:
        - file

    DisplayElements:
      type: object
      properties:
        application_name:
          type: string
          pattern: "^[a-zA-Z0-9._-]+$"
          description: Application ID for organizing assets
          example: "my_app"
        priority:
          type: integer
          minimum: 1
          maximum: 100
          description: >-
            Draw priority in the range [1, 100] inclusive. A draw request is
            accepted when its priority is greater than or equal to (>=) the
            priority of the currently running system app. Equal-priority requests
            from a different application_name override whatever is on screen.
            System app priority levels: stub/poweroff apps = 0 (always
            preemptable), any standard built-in app = 10, active BUSY/CUSTOM
            work session = 90. The draw API only accepts values 1–100; 0 is
            reserved for internal use.
          default: 50
        elements:
          type: array
          minItems: 1
          items:
            oneOf:
              - $ref: "#/components/schemas/TextElement"
              - $ref: "#/components/schemas/ImageElement"
              - $ref: "#/components/schemas/AnimationElement"
              - $ref: "#/components/schemas/CountdownElement"
          description: Array of elements to display
      required:
        - application_name
        - elements
      example:
        application_name: "my_app"
        elements:
          - id: "0"
            timeout: 10
            align: center
            x: 36
            y: 10
            type: text
            text: "Hello, World! Long text"
            font: medium
            color: "#FFFFFFFF"
            width: 72
            scroll_rate: 1000
            display: front
          - id: "1"
            timeout: 6
            align: top_mid
            x: 36
            y: 0
            type: text
            text: "top_mid"
            font: small
            color: "#AAFF00FF"
            display: "front"
          - id: "2"
            timeout: 6
            type: "image"
            path: "data.png"
            x: 0
            y: 0
            display: "back"

    DisplayElement:
      type: object
      required:
        - id
        - type
      properties:
        id:
          type: string
          pattern: "^[a-zA-Z0-9._-]+$"
          description: Unique identifier for the element
        timeout:
          type: integer
          minimum: 0
          description: Time in seconds the element should be displayed (0 for no timeout). Mutually exclusive with display_until.
        display_until:
          type: string
          description: The element will be hidden when system time reaches the specified Unix timestamp (in seconds). Mutually exclusive with timeout.
        type:
          type: string
          enum: [text, image, animation, countdown]
          description: Type of display element
        x:
          type: integer
          minimum: -4096
          maximum: 4095
          description: X coordinate of selected anchor point relative to top-left of display
          default: 0
        y:
          type: integer
          minimum: -4096
          maximum: 4095
          description: Y coordinate of selected anchor point relative to top-left of display
          default: 0
        display:
          type: string
          enum: [front, back]
          description: Which display to show the element on (for dual-display devices)
          default: front
        align:
          type: string
          description: Anchor point of element. Also use `x` and `y` to position element.
          enum:
            - top_left
            - top_mid
            - top_right
            - mid_left
            - center
            - mid_right
            - bottom_left
            - bottom_mid
            - bottom_right
      discriminator:
        propertyName: type
        mapping:
          text: "#/components/schemas/TextElement"
          image: "#/components/schemas/ImageElement"
          animation: "#/components/schemas/AnimationElement"
          countdown: "#/components/schemas/CountdownElement"

    TextElement:
      allOf:
        - $ref: "#/components/schemas/DisplayElement"
        - type: object
          required:
            - text
            - font
          properties:
            text:
              type: string
              minLength: 1
              pattern: "^[\\x20-\\x7E]+$"
              description: Text content to display (printable ASCII only; fonts are bitmap ASCII)
            font:
              type: string
              description: One of the available fonts to display the text in
              enum:
                - small
                - medium
                - medium_condensed
                - big
            color:
              type: string
              description: "Color to display the text in, in #RRGGBBAA format"
              pattern: "^#[a-fA-F0-9]{8}$"
              default: "#FFFFFFFF"
            width:
              type: integer
              minimum: 1
              description: Width of the label
            scroll_rate:
              type: integer
              minimum: 0
              description: Scroll rate in pixels per minute

    ImageElement:
      allOf:
        - $ref: "#/components/schemas/DisplayElement"
        - type: object
          oneOf:
            - required:
                - path
              properties:
                path:
                  type: string
                  pattern: "^[a-zA-Z0-9._/-]+$"
                  description: Path to the image file in the app's assets
            - required:
                - stock_path
              properties:
                stock_path:
                  type: string
                  pattern: "shared/[a-z0-9_]+$"
                  description: Stock image file name

    AnimationElement:
      allOf:
        - $ref: "#/components/schemas/DisplayElement"
        - type: object
          allOf:
            - oneOf:
                - properties:
                    path:
                      type: string
                      pattern: "^[a-zA-Z0-9._/-]+$"
                      description: Path to the animation file in the app's assets
                - properties:
                    stock_path:
                      type: string
                      pattern: "shared/[a-z0-9_]+$"
                      description: Stock animation file name
            - properties:
                loop:
                  type: boolean
                  description: Whether to loop the requested part of the animation
                  default: false
                await_previous_end:
                  type: boolean
                  description: If the element has been created before and this flag is true, the previous range will finish before the requested one starts.
                  default: false
                section:
                  type: string
                  description: Name of the section to play back. Specifying "default" selects the entire animation.

    CountdownElement:
      allOf:
        - $ref: "#/components/schemas/DisplayElement"
        - type: object
          required:
            - timestamp
            - direction
            - show_hours
          properties:
            timestamp:
              type: string
              pattern: "^[0-9]+$"
              description: "Seconds-based Unix UTC timestamp to count down or up to. Note: it's a number in a string."
            color:
              type: string
              description: "Color to display the text in, in #RRGGBBAA format"
              pattern: "^#[a-fA-F0-9]{8}$"
              default: "#FFFFFFFF"
            direction:
              type: string
              enum: [time_left, time_since]
              description: Whether to count up or down
            show_hours:
              type: string
              enum: [when_non_zero, always]
              description: When to show the hours position

    DisplayBrightnessInfo:
      type: object
      properties:
        value:
          type: string
          description: Displays brightness (0-100/auto)
          example: "auto"

    AudioVolumeInfo:
      type: object
      properties:
        volume:
          type: number
          description: Audio volume value (0-100)
          example: 50

    TimestampInfo:
      type: object
      properties:
        timestamp:
          type: string
          description: ISO 8601 formatted timestamp with timezone
          example: "2025-10-02T14:30:45+04:00"
      required:
        - timestamp

    TimezoneInfo:
      type: object
      properties:
        name:
          type: string
          description: "Time zone name"
          example: "Bangalore"
        offset:
          type: string
          description: "Time zone offset from UTC"
          example: "+05:30"
        abbr:
          type: string
          description: "Time zone abbreviation"
          example: "IST"
      required:
        - name
        - offset
        - abbr

    Status:
      type: object
      properties:
        device:
          $ref: "#/components/schemas/StatusDevice"
        firmware:
          $ref: "#/components/schemas/StatusFirmware"
        system:
          $ref: "#/components/schemas/StatusSystem"
        power:
          $ref: "#/components/schemas/StatusPower"

    StatusDevice:
      type: object
      properties:
        serial_number:
          type: string
          description: Device serial number
          example: "203638485431500400123456"
        usb_mac:
          type: string
          description: MAC of USB ethernet device
          example: "0c:fa:22:21:2a:31"
        wifi_mac:
          type: string
          description: WIFI MAC
          example: "0c:fa:22:21:2a:31"
        ble_mac:
          type: string
          description: BLE MAC
          example: "0c:fa:22:21:2a:31"
        otp_valid:
          type: boolean
          description: Is OTP data valid
          example: true
        otp_model:
          type: string
          description: Device model code
          example: "BB.1"
        otp_timestamp:
          type: integer
          description: Production timestamp
          example: 1767225600
      required:
        - serial_number
        - usb_mac
        - otp_valid

    StatusFirmware:
      type: object
      properties:
        version:
          type: string
          description: Firmware version
          example: "1.0.0"
        target:
          type: integer
          description: Firmware target code
          example: 22
        branch:
          type: string
          description: Git branch name
          example: "main"
        build_date:
          type: string
          description: Build date
          example: "2024-01-01"
        commit_hash:
          type: string
          description: Git commit hash (may include -dirty suffix)
          example: "abc123def456-dirty"
        nwp_version:
          type: string
          description: Radio firmware version
          example: "1711.2.14.5.2.0.7"
      required:
        - version
        - target
        - branch
        - build_date
        - commit_hash

    StatusSystem:
      type: object
      properties:
        api_semver:
          type: string
          description: API SemVer
          example: "0.0.0"
        uptime:
          type: string
          description: System uptime
          example: "00d 00h 04m 13s"
        boot_time:
          type: integer
          description: System boot timestamp
          example: 1767225600
        auto_update_enabled:
          type: boolean
          description: Is auto-update enabled
          example: true
      required:
        - api_semver
        - uptime
        - boot_time
        - auto_update_enabled

    StatusPower:
      type: object
      properties:
        state:
          type: string
          enum: [discharging, charging, charged]
          description: Power state
          example: "discharging"
        battery_charge:
          type: integer
          description: Battery charge percent
          example: 99
        battery_voltage:
          type: integer
          description: Battery voltage in mV
          example: 4183
        battery_current:
          type: integer
          description: Battery current in mA
          example: -180
        usb_voltage:
          type: integer
          description: USB voltage in mV
          example: 4843
      required:
        - state
        - battery_charge
        - battery_voltage
        - battery_current
        - usb_voltage

    WifiSecurityMethod:
      type: string
      example: "WPA3"
      enum: [Open, WPA, WPA2, WEP, WPA/WPA2, WPA3, WPA2/WPA3, Unsupported]

    WifiIpMethod:
      type: string
      example: "dhcp"
      enum: ["dhcp", "static"]

    WifiIpType:
      type: string
      example: "ipv4"
      enum: ["ipv4", "ipv6"]

    Network:
      type: object
      properties:
        ssid:
          type: string
          example: "42"
        security:
          $ref: "#/components/schemas/WifiSecurityMethod"
        rssi:
          type: integer
          example: 58

    StatusResponse:
      type: object
      description: |
        Wi-Fi status. Only `state` is always present.
        Fields `ssid`, `bssid`, `channel`, `rssi`, `security`, and `ip_config` are only included when state is "connected".
      required:
        - state
      properties:
        state:
          type: string
          example: disconnected
          enum:
            - unknown
            - disconnected
            - connected
            - connecting
            - disconnecting
            - reconnecting
        ssid:
          type: string
          description: Only present when connected
          example: Your_WIFI_SSID
        bssid:
          type: string
          description: Only present when connected
          pattern: "^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$"
          example: "EC:5A:00:0B:55:1D"
        channel:
          type: integer
          description: Only present when connected
          example: 3
        rssi:
          type: integer
          description: Only present when connected
          example: -43
        security:
          description: Only present when connected
          $ref: "#/components/schemas/WifiSecurityMethod"
        ip_config:
          type: object
          description: Only present when connected
          properties:
            ip_method:
              $ref: "#/components/schemas/WifiIpMethod"
            ip_type:
              $ref: "#/components/schemas/WifiIpType"
            address:
              type: string
              example: 192.168.50.5

    ConnectRequestConfig:
      type: object
      properties:
        ssid:
          type: string
          example: Your_WIFI_SSID
        password:
          type: string
          example: Your_WIFI_Pass
        security:
          $ref: "#/components/schemas/WifiSecurityMethod"
        ip_config:
          type: object
          properties:
            ip_method:
              $ref: "#/components/schemas/WifiIpMethod"
            ip_type:
              type: string
              example: ipv4
              enum:
                - ipv4
                - ipv6
            address:
              type: string
              example: 192.168.50.5
            mask:
              type: string
              example: 255.255.255.0
            gateway:
              type: string
              example: 192.168.50.1

    NetworkResponse:
      type: object
      properties:
        count:
          type: integer
          example: 1
        networks:
          type: array
          items:
            $ref: "#/components/schemas/Network"

    ScreenResponse:
      type: string
      description: Frame for requested display encoded in base64
      format: base64

    AccountInfo:
      type: object
      properties:
        linked:
          type: boolean
          example: true
        id:
          type: string
          example: "12345678-9abc-def0-1234-56789abcdef0"
        email:
          type: string
          example: "name@example.com"
        user_id:
          type: string
          example: "12345678-9abc-def0-1234-56789abcdef0"

    AccountStatus:
      type: object
      properties:
        status:
          type: string
          example: "connected"
          enum: ["error", "disconnected", "connected"]

    AccountProfile:
      type: object
      properties:
        profile:
          type: string
          example: "dev"
          enum: ["dev", "prod", "local", "custom"]
        custom_url:
          type: string
          description: Only present when profile is "custom"
          example: "mqtts://mqtt.example.com:8883"
      required:
        - profile

    AccountLink:
      type: object
      properties:
        code:
          type: string
          example: "ABCD"
        expires_at:
          type: integer
          example: 1761060863

    BleStatusResponse:
      type: object
      properties:
        status:
          type: string
          enum:
            [
              "reset",
              "initialization",
              "disabled",
              "enabled",
              "connectable",
              "connected",
              "internal error",
            ]
          example: connected
        address:
          type: string
          description: Remote device address. Only present when status is "connected".
          example: 50:DA:D6:FE:DD:A9
      required:
        - status

    BusySnapshot:
      type: object
      properties:
        snapshot:
          allOf:
            - oneOf:
                - $ref: "#/components/schemas/BusySnapshotNotStarted"
                - $ref: "#/components/schemas/BusySnapshotInfinite"
                - $ref: "#/components/schemas/BusySnapshotSimple"
                - $ref: "#/components/schemas/BusySnapshotInterval"
            - type: object
              properties:
                busy_bar_settings:
                  $ref: "#/components/schemas/BusyBarSettings"
              required:
                - busy_bar_settings
        snapshot_timestamp_ms:
          type: integer
          example: 1761582532251
      required:
        - snapshot
        - snapshot_timestamp_ms

    BusySnapshotNotStarted:
      type: object
      properties:
        type:
          type: string
          const: "NOT_STARTED"
      required:
        - type

    BusySnapshotInfinite:
      type: object
      properties:
        type:
          type: string
          const: "INFINITE"
        card_id:
          type: string
          format: uuid
          example: "00000000-0000-0000-0000-000000000000"
        is_paused:
          type: boolean
          example: false
      required:
        - type
        - card_id
        - is_paused

    BusySnapshotSimple:
      type: object
      properties:
        type:
          type: string
          const: "SIMPLE"
        card_id:
          type: string
          format: uuid
          example: "00000000-0000-0000-0000-000000000000"
        time_left_ms:
          type: integer
          example: 9000
        is_paused:
          type: boolean
          example: false
      required:
        - type
        - card_id
        - time_left_ms
        - is_paused

    BusySnapshotInterval:
      type: object
      properties:
        type:
          type: string
          const: "INTERVAL"
        card_id:
          type: string
          format: uuid
          example: "00000000-0000-0000-0000-000000000000"
        current_interval:
          type: integer
          example: 1
        current_interval_time_total_ms:
          type: integer
          example: 60000
        current_interval_time_left_ms:
          type: integer
          example: 42690
        is_paused:
          type: boolean
          example: false
        interval_settings:
          $ref: "#/components/schemas/BusyTimerIntervalSettings"
      required:
        - type
        - card_id
        - current_interval
        - current_interval_time_total_ms
        - current_interval_time_left_ms
        - is_paused
        - interval_settings

    BusyProfile:
      type: object
      properties:
        sort_order:
          type: integer
          example: -1
        title:
          type: string
          example: "study"
        id:
          type: string
          format: uuid
          example: "00000000-0000-0000-0000-000000000000"
        timer_settings:
          oneOf:
            - $ref: "#/components/schemas/BusyTimerInfiniteSettings"
            - $ref: "#/components/schemas/BusyTimerSimpleSettings"
            - $ref: "#/components/schemas/BusyTimerIntervalSettings"
        busy_bar_settings:
          $ref: "#/components/schemas/BusyBarSettings"
        profile_timestamp_ms:
          type: integer
          example: 1761582532251
      required:
        - sort_order
        - title
        - timer_settings
        - profile_timestamp_ms
        - id
        - busy_bar_settings

    BusyProfileSlot:
      type: string
      enum:
        - "busy"
        - "custom"
      example: "busy"

    BusyTimerInfiniteSettings:
      type: object
      properties:
        type:
          type: string
          const: "INFINITE"
      required:
        - type

    BusyTimerSimpleSettings:
      type: object
      properties:
        type:
          type: string
          const: "SIMPLE"
        total_time_ms:
          type: integer
          example: 300000
      required:
        - type
        - total_time_ms

    BusyTimerIntervalSettings:
      type: object
      properties:
        type:
          type: string
          const: "INTERVAL"
        interval_work_ms:
          type: integer
          example: 120000
        interval_rest_ms:
          type: integer
          example: 60000
        interval_work_cycles_count:
          type: integer
          example: 3
        is_autostart_enabled:
          type: boolean
          example: false
      required:
        - type
        - interval_work_ms
        - interval_rest_ms
        - interval_work_cycles_count
        - is_autostart_enabled

    BusyBarSettings:
      type: object
      properties:
        theme:
          type: string
          example: "on_air"
        show_work_phase_only:
          type: boolean
          example: false
        trigger_smart_home:
          type: boolean
          example: true
      required:
        - theme
        - show_work_phase_only
        - trigger_smart_home

    TimezoneListResponse:
      type: object
      properties:
        list:
          type: array
          items:
            $ref: "#/components/schemas/TimezoneInfo"

    SmartHomePairingInfo:
      type: object
      properties:
        fabric_count:
          type: integer
          example: 1
          description: 'Number of smart homes (Matter "fabrics") that this device is paired with ("commissioned into")'
        latest_pairing_status:
          type: object
          properties:
            value:
              type: string
              enum:
                - never_started
                - started
                - completed_successfully
                - failed
              description: 'Latest state of smart home pairing (Matter "commissioning") process. Note: "never_started" only refers to the current power cycle of the device; this status is not recorded across reboots.'
              example: "completed_successfully"
            timestamp:
              type: integer
              description: "UTC Unix second timestamp of latest state update. Only present when a status update has occurred."
              example: 1769436711
    SmartHomePairingPayload:
      type: object
      description: Set of information for pairing with a Matter smart home
      properties:
        available_until:
          type: string
          description: 'Pairing with ("commissioning into") a Matter smart home using the provided payload is possible before this UTC Unix millisecond timestamp. Note: it''s a number in a string.'
          example: "1769437579000"
        qr_code:
          type: string
          description: 'Payload of the QR code for pairing with ("commissioning into") a smart home'
          example: "MT:YNDA0-O913..VV7I000"
        manual_code:
          type: string
          description: 'Manual code for pairing with ("commissioning into") a smart home'
          example: "1155-360-0377"
    SmartHomeSwitchState:
      type: object
      properties:
        state:
          type: boolean
          description: "State of emulated switch."
          example: false
        startup:
          type: string
          enum:
            - "off"
            - "on"
            - toggle
            - last
          description: "State of emulated switch on startup. Never sent by the server, but can be specified by the client."

tags:
  - name: System
    description: System information and control
  - name: Time
    description: Time-related methods
  - name: Updater
    description: Firmware update control
  - name: Wi-Fi
    description: Allows to operate with Wi-Fi
  - name: Assets
    description: Asset file management and display control
  - name: Streaming
    description: Screen streaming
  - name: Settings
    description: Device settings
  - name: Input
    description: Input events
  - name: BLE
    description: Allows to operate with BLE
  - name: Account
    description: Account linking and MQTT status
  - name: Busy
    description: BUSY timer control
