{
    "openapi": "3.0.0",
    "info": {
        "description": "Cloud mirror of the smarthome REST API - sensors, relays,\nschedules, and notifications for whichever Pi agent is\nregistered. Same contract `smarthome` serves locally; this\nserver exists for when the Android app isn't on the same\nnetwork as the Pi (see the top-level README).\nDemo account (always available): serial `SN123456`, otp `12345678`.",
        "title": "smarthomeapi",
        "contact": {},
        "version": "1.0"
    },
    "paths": {
        "/alarm-sensors": {
            "get": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "alarm-sensors"
                ],
                "summary": "List the authenticated device's contact/occupancy/water-leak sensors",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/api.collection-model_AlarmSensor"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/alarm-sensors/{id}": {
            "get": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "alarm-sensors"
                ],
                "summary": "Get one alarm sensor",
                "parameters": [
                    {
                        "description": "Alarm sensor ID",
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/model.AlarmSensor"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "alarm-sensors"
                ],
                "summary": "Remove an alarm sensor (and its underlying definition/MQTT subscription)",
                "parameters": [
                    {
                        "description": "Alarm sensor ID",
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "deleted"
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "*/*": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "patch": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "alarm-sensors"
                ],
                "summary": "Rename an alarm sensor",
                "parameters": [
                    {
                        "description": "Alarm sensor ID",
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/api.patchAlarmSensorRequest"
                            }
                        }
                    },
                    "description": "New name",
                    "required": true
                },
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/model.AlarmSensor"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/login": {
            "post": {
                "tags": [
                    "auth"
                ],
                "summary": "Log in with a registered serial number/OTP",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/api.loginRequest"
                            }
                        }
                    },
                    "description": "Serial number and OTP",
                    "required": true
                },
                "responses": {
                    "200": {
                        "description": "token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/notifications": {
            "get": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "notifications"
                ],
                "summary": "List the authenticated device's notifications",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/api.collection-model_Notification"
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "notifications"
                ],
                "summary": "Delete all of the authenticated device's notifications",
                "responses": {
                    "204": {
                        "description": "cleared"
                    }
                }
            }
        },
        "/notifications/{id}": {
            "get": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "notifications"
                ],
                "summary": "Get one notification",
                "parameters": [
                    {
                        "description": "Notification ID",
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/model.Notification"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "patch": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "notifications"
                ],
                "summary": "Mark a notification read",
                "parameters": [
                    {
                        "description": "Notification ID",
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/model.Notification"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/pairing/confirm": {
            "post": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "pairing"
                ],
                "summary": "Confirm a discovered device into a real sensor or devices-relay switch, choosing its name",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/api.confirmDeviceRequest"
                            }
                        }
                    },
                    "description": "deviceId (from GET /pairing/discovered) and the chosen name",
                    "required": true
                },
                "responses": {
                    "201": {
                        "description": "Created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/pairing/discovered": {
            "get": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "pairing"
                ],
                "summary": "List devices that joined while pairing was open, not yet confirmed",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/api.collection-model_DiscoveredDevice"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/pairing/start": {
            "post": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "pairing"
                ],
                "summary": "Open Zigbee permit_join for a limited time",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/api.startPairingRequest"
                            }
                        }
                    },
                    "description": "timeoutSeconds - default 120, capped at 254"
                },
                "responses": {
                    "204": {
                        "description": "pairing requested"
                    }
                }
            }
        },
        "/pairing/status": {
            "get": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "pairing"
                ],
                "summary": "Current Zigbee pairing status",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true
                                }
                            }
                        }
                    }
                }
            }
        },
        "/pairing/stop": {
            "post": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "pairing"
                ],
                "summary": "Close Zigbee permit_join early",
                "responses": {
                    "204": {
                        "description": "pairing stop requested"
                    }
                }
            }
        },
        "/register": {
            "post": {
                "tags": [
                    "auth"
                ],
                "summary": "Register a new device's serial number/OTP credential",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/api.loginRequest"
                            }
                        }
                    },
                    "description": "Serial number and 8-digit OTP",
                    "required": true
                },
                "responses": {
                    "200": {
                        "description": "message",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "bad OTP, unrecognized serial number, or serial number already registered",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/relays": {
            "get": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "relays"
                ],
                "summary": "List the authenticated device's relays",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/api.collection-model_Relay"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "relays"
                ],
                "summary": "Register a new relay module",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/api.createRelayRequest"
                            }
                        }
                    },
                    "description": "Relay module ID, optional friendly name, displayInverted, normalOpen, sensorName",
                    "required": true
                },
                "responses": {
                    "201": {
                        "description": "Created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/model.Relay"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Conflict",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/relays/{id}": {
            "get": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "relays"
                ],
                "summary": "Get one relay module",
                "parameters": [
                    {
                        "description": "Relay ID",
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/model.Relay"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "relays"
                ],
                "summary": "Delete an entire relay module",
                "parameters": [
                    {
                        "description": "Relay ID",
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "deleted"
                    },
                    "400": {
                        "description": "Bad Request",
                        "content": {
                            "*/*": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "*/*": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "patch": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "relays"
                ],
                "summary": "Update a relay module's name, displayInverted, normalOpen, and/or sensorName",
                "parameters": [
                    {
                        "description": "Relay ID",
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/api.patchRelayRequest"
                            }
                        }
                    },
                    "description": "New name, displayInverted, normalOpen, or sensorName",
                    "required": true
                },
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/model.Relay"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/relays/{relayId}/switches": {
            "post": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "relays"
                ],
                "summary": "Register a new relay channel under relayId - replaces static config.json relays entries",
                "parameters": [
                    {
                        "description": "Relay module ID",
                        "name": "relayId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/api.createRelaySwitchRequest"
                            }
                        }
                    },
                    "description": "id and label required; schedulable optional",
                    "required": true
                },
                "responses": {
                    "201": {
                        "description": "Created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/model.Relay"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/relays/{relayId}/switches/{switchId}": {
            "delete": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "relays"
                ],
                "summary": "Remove a relay channel (and its underlying MQTT feedback subscription)",
                "parameters": [
                    {
                        "description": "Relay module ID",
                        "name": "relayId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "description": "Switch ID",
                        "name": "switchId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "deleted"
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "*/*": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "patch": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "relays"
                ],
                "summary": "Rename a relay channel and/or set its schedulable flag - also how a channel is linked to a temperature sensor (label == sensor ID)",
                "parameters": [
                    {
                        "description": "Relay module ID",
                        "name": "relayId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "description": "Switch ID",
                        "name": "switchId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/api.patchRelaySwitchRequest"
                            }
                        }
                    },
                    "description": "New label and/or schedulable - either or both",
                    "required": true
                },
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/model.Relay"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/relays/{relayId}/toggle/{switchId}": {
            "post": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "relays"
                ],
                "summary": "Toggle one switch on a relay module",
                "parameters": [
                    {
                        "description": "Relay ID",
                        "name": "relayId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "description": "Switch ID",
                        "name": "switchId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "switch toggled"
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "*/*": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/schedules": {
            "get": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "schedules"
                ],
                "summary": "List the authenticated device's schedules",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/api.collection-model_Schedule"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "schedules"
                ],
                "summary": "Create a new schedule for a schedulable device",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/api.createScheduleRequest"
                            }
                        }
                    },
                    "description": "Device + fromHour/toHour",
                    "required": true
                },
                "responses": {
                    "201": {
                        "description": "Created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/model.Schedule"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "unschedulable device, or overlaps another schedule on it",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/schedules/{id}": {
            "get": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "schedules"
                ],
                "summary": "Get one schedule",
                "parameters": [
                    {
                        "description": "Schedule ID",
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/model.Schedule"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "schedules"
                ],
                "summary": "Delete a schedule (used when a client disables it)",
                "parameters": [
                    {
                        "description": "Schedule ID",
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "deleted"
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "*/*": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "patch": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "schedules"
                ],
                "summary": "Change a schedule's time window",
                "parameters": [
                    {
                        "description": "Schedule ID",
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/api.patchScheduleRequest"
                            }
                        }
                    },
                    "description": "New fromHour/fromMinute/toHour/toMinute",
                    "required": true
                },
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/model.Schedule"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "overlaps another schedule",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/sensors": {
            "get": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "sensors"
                ],
                "summary": "List the authenticated device's sensors",
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/api.collection-model_Sensor"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "sensors"
                ],
                "summary": "Register a new sensor definition (id/topic/kind) - replaces static config.json entries",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/api.createSensorRequest"
                            }
                        }
                    },
                    "description": "id, topic, kind required; format/name/defaultSetTemp optional",
                    "required": true
                },
                "responses": {
                    "201": {
                        "description": "Created",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/sensors/{id}": {
            "get": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "sensors"
                ],
                "summary": "Get one sensor",
                "parameters": [
                    {
                        "description": "Sensor ID",
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/model.Sensor"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "sensors"
                ],
                "summary": "Remove a sensor (and its underlying definition/MQTT subscription)",
                "parameters": [
                    {
                        "description": "Sensor ID",
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "deleted"
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "*/*": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "patch": {
                "security": [
                    {
                        "BasicAuth": []
                    }
                ],
                "tags": [
                    "sensors"
                ],
                "summary": "Change a sensor's setpoint and/or name",
                "parameters": [
                    {
                        "description": "Sensor ID",
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/api.patchSensorRequest"
                            }
                        }
                    },
                    "description": "New setTemp and/or name - either or both",
                    "required": true
                },
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/model.Sensor"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "servers": [
        {
            "url": "https://upanet.org/api"
        }
    ],
    "components": {
        "securitySchemes": {
            "BasicAuth": {
                "type": "http",
                "scheme": "basic"
            }
        },
        "schemas": {
            "api.collection-model_AlarmSensor": {
                "type": "object",
                "properties": {
                    "member": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/model.AlarmSensor"
                        }
                    }
                }
            },
            "api.collection-model_DiscoveredDevice": {
                "type": "object",
                "properties": {
                    "member": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/model.DiscoveredDevice"
                        }
                    }
                }
            },
            "api.collection-model_Notification": {
                "type": "object",
                "properties": {
                    "member": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/model.Notification"
                        }
                    }
                }
            },
            "api.collection-model_Relay": {
                "type": "object",
                "properties": {
                    "member": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/model.Relay"
                        }
                    }
                }
            },
            "api.collection-model_Schedule": {
                "type": "object",
                "properties": {
                    "member": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/model.Schedule"
                        }
                    }
                }
            },
            "api.collection-model_Sensor": {
                "type": "object",
                "properties": {
                    "member": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/model.Sensor"
                        }
                    }
                }
            },
            "api.confirmDeviceRequest": {
                "type": "object",
                "properties": {
                    "deviceId": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    }
                }
            },
            "api.createRelayRequest": {
                "type": "object",
                "properties": {
                    "displayInverted": {
                        "type": "boolean"
                    },
                    "id": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "normalOpen": {
                        "type": "boolean"
                    },
                    "sensorName": {
                        "type": "string"
                    }
                }
            },
            "api.createRelaySwitchRequest": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "label": {
                        "type": "string"
                    },
                    "schedulable": {
                        "type": "boolean"
                    }
                }
            },
            "api.createScheduleRequest": {
                "type": "object",
                "properties": {
                    "device": {
                        "type": "string"
                    },
                    "fromHour": {
                        "type": "integer"
                    },
                    "fromMinute": {
                        "type": "integer"
                    },
                    "toHour": {
                        "type": "integer"
                    },
                    "toMinute": {
                        "type": "integer"
                    }
                }
            },
            "api.createSensorRequest": {
                "type": "object",
                "properties": {
                    "defaultSetTemp": {
                        "type": "number"
                    },
                    "format": {
                        "type": "string"
                    },
                    "id": {
                        "type": "string"
                    },
                    "kind": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "topic": {
                        "type": "string"
                    }
                }
            },
            "api.loginRequest": {
                "type": "object",
                "properties": {
                    "otp": {
                        "type": "string"
                    },
                    "serialNumber": {
                        "type": "string"
                    }
                }
            },
            "api.patchAlarmSensorRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string"
                    }
                }
            },
            "api.patchRelayRequest": {
                "type": "object",
                "properties": {
                    "displayInverted": {
                        "type": "boolean"
                    },
                    "name": {
                        "type": "string"
                    },
                    "normalOpen": {
                        "type": "boolean"
                    },
                    "sensorName": {
                        "type": "string"
                    }
                }
            },
            "api.patchRelaySwitchRequest": {
                "type": "object",
                "properties": {
                    "label": {
                        "type": "string"
                    },
                    "schedulable": {
                        "type": "boolean"
                    }
                }
            },
            "api.patchScheduleRequest": {
                "type": "object",
                "properties": {
                    "fromHour": {
                        "type": "integer"
                    },
                    "fromMinute": {
                        "type": "integer"
                    },
                    "toHour": {
                        "type": "integer"
                    },
                    "toMinute": {
                        "type": "integer"
                    }
                }
            },
            "api.patchSensorRequest": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "setTemp": {
                        "type": "number"
                    }
                }
            },
            "api.startPairingRequest": {
                "type": "object",
                "properties": {
                    "timeoutSeconds": {
                        "type": "integer"
                    }
                }
            },
            "model.AlarmSensor": {
                "type": "object",
                "properties": {
                    "batteryLevel": {
                        "type": "integer"
                    },
                    "id": {
                        "type": "string"
                    },
                    "kind": {
                        "description": "\"contact\" | \"occupancy\" | \"water_leak\" | \"vibration\"",
                        "type": "string"
                    },
                    "lastUpdated": {
                        "description": "epoch millis",
                        "type": "integer"
                    },
                    "linkQuality": {
                        "type": "integer"
                    },
                    "name": {
                        "description": "Name defaults to ID (same convention Sensor.Name already used before\nthis field existed) until explicitly renamed via\nPATCH /api/alarm-sensors/{id} - see store.SetAlarmSensorName.",
                        "type": "string"
                    },
                    "triggered": {
                        "type": "boolean"
                    }
                }
            },
            "model.DiscoveredDevice": {
                "type": "object",
                "properties": {
                    "discoveredAt": {
                        "description": "epoch millis",
                        "type": "integer"
                    },
                    "id": {
                        "description": "Zigbee2mqtt friendly_name at discovery time (its ieee_address, until confirm renames it)",
                        "type": "string"
                    },
                    "isActuator": {
                        "type": "boolean"
                    },
                    "kind": {
                        "description": "\"temperature\" | \"contact\" | \"occupancy\" | \"water_leak\" | \"vibration\" | \"\" for an actuator or an undetermined kind",
                        "type": "string"
                    },
                    "manufacturer": {
                        "type": "string"
                    },
                    "model": {
                        "type": "string"
                    },
                    "topic": {
                        "description": "Topic is zigbee2mqtt/<ID> - informational; confirm derives the real\ndefinition's topic from the chosen name instead (see\napi.confirmDevice), since renaming the device changes its topic too.",
                        "type": "string"
                    }
                }
            },
            "model.Notification": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "isRead": {
                        "type": "boolean"
                    },
                    "message": {
                        "type": "string"
                    },
                    "timestamp": {
                        "description": "epoch millis",
                        "type": "integer"
                    },
                    "title": {
                        "type": "string"
                    }
                }
            },
            "model.Relay": {
                "type": "object",
                "properties": {
                    "displayInverted": {
                        "type": "boolean"
                    },
                    "id": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "normalOpen": {
                        "type": "boolean"
                    },
                    "sensorName": {
                        "type": "string"
                    },
                    "switches": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/model.RelaySwitch"
                        }
                    }
                }
            },
            "model.RelaySwitch": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "isOn": {
                        "type": "boolean"
                    },
                    "label": {
                        "type": "string"
                    },
                    "schedulable": {
                        "type": "boolean"
                    }
                }
            },
            "model.Schedule": {
                "type": "object",
                "properties": {
                    "fromHour": {
                        "description": "0..23",
                        "type": "integer"
                    },
                    "fromMinute": {
                        "description": "0..59",
                        "type": "integer"
                    },
                    "id": {
                        "type": "string"
                    },
                    "sensorName": {
                        "description": "historical name from the Android app; really the target device name",
                        "type": "string"
                    },
                    "toHour": {
                        "description": "0..23",
                        "type": "integer"
                    },
                    "toMinute": {
                        "description": "0..59",
                        "type": "integer"
                    }
                }
            },
            "model.Sensor": {
                "type": "object",
                "properties": {
                    "batteryLevel": {
                        "type": "integer"
                    },
                    "currentTemp": {
                        "type": "number"
                    },
                    "humidity": {
                        "type": "number"
                    },
                    "id": {
                        "type": "string"
                    },
                    "lastUpdated": {
                        "description": "epoch millis, matches Android's Long",
                        "type": "integer"
                    },
                    "linkQuality": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "pm25": {
                        "type": "number"
                    },
                    "setTemp": {
                        "type": "number"
                    },
                    "sortOrder": {
                        "description": "SortOrder is a display hint only (see store.ListSensors) - config-set,\n0/unset means \"no preference\" and sorts after every explicitly\nordered sensor, falling back to alphabetical-by-ID same as always.\nA positive value pulls a sensor earlier, lower sorting first.",
                        "type": "integer"
                    },
                    "vocIndex": {
                        "type": "number"
                    }
                }
            }
        }
    }
}