{
    "schemes": [
        "https"
    ],
    "swagger": "2.0",
    "info": {
        "description": "API for accessing permitted sites and requesting site feedback.\n\n## Getting API Key\n\nIn order to get an API key you first need to register on the [BTES site](https://ems.btes.hu/) by reaching out to [info@btes.hu](mailto:info@btes.hu). After registering and recieving the appropriate permissions the API keys can be generated at the [Developers Portal](https://ems.btes.hu/developers). Store these API keys securely\n\n## Authentication\n\nInclude your API key in the `X-API-Key` header when calling the API.\n\n```http\nX-API-Key: YOUR_API_KEY\nAccept: application/json\n```\n\nExample request (replace the API key before running):\n\n```sh\ncurl 'https://ems.btes.hu/api/developers/beta/sites' \\\n  -H \"X-API-Key: $DEV_API_KEY\" \\\n  -H 'Accept: application/json'\n```\n",
        "title": "BTES Developer API",
        "contact": {},
        "version": "beta"
    },
    "host": "ems.btes.hu",
    "basePath": "/api/developers/beta",
    "paths": {
        "/sites": {
            "get": {
                "security": [
                    {
                        "ApiKeyAuth": []
                    }
                ],
                "description": "Returns the sites accessible to the API key owner. The returned id field should be used as `siteID` parameter for further requests to identify the site. Errors are JSON objects with an errors field containing the message.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "developer"
                ],
                "summary": "List accessible sites",
                "operationId": "developer-list-sites",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.DeveloperSitesResponse"
                        }
                    },
                    "401": {
                        "description": "Missing, invalid, or revoked API key",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "404": {
                        "description": "Site lookup failed",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "500": {
                        "description": "Internal server error",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    }
                }
            }
        },
        "/sites/{siteID}/control": {
            "post": {
                "security": [
                    {
                        "ApiKeyAuth": []
                    }
                ],
                "description": "Sends a one-off solar/storage command. Supply a flat JSON object. Setpoint policies require power values: positive storage power charges, negative discharges. Solar setpoints and power limits must be nonnegative. Peak-shaving-only requires all four site thresholds.\nCommands expire at the configured fallback timeout; omitted policies may revert to defaults. The off policy disables limit guarding. A timeout does not prove failure: do not blindly retry.\nResponse state contains only grid, solar, and storage. Missing sections are null; unavailable measurements are omitted. Power is in watts, energy in watt-hours, and daily totals use UTC.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "developer"
                ],
                "summary": "Control solar and storage",
                "operationId": "developer-control-site",
                "parameters": [
                    {
                        "enum": [
                            "application/json"
                        ],
                        "type": "string",
                        "default": "application/json",
                        "description": "JSON request media type",
                        "name": "Content-Type",
                        "in": "header",
                        "required": true
                    },
                    {
                        "minimum": 1,
                        "type": "integer",
                        "description": "Site ID",
                        "name": "siteID",
                        "in": "path",
                        "required": true
                    },
                    {
                        "description": "Solar/storage control fields",
                        "name": "control",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/api.LiveControlRequest"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.LiveResponse"
                        }
                    },
                    "400": {
                        "description": "Invalid site ID, JSON or control fields",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "401": {
                        "description": "Missing, invalid, or revoked API key",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "403": {
                        "description": "No access to this site",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "415": {
                        "description": "Content-Type must be application/json",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "500": {
                        "description": "Internal server error",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "502": {
                        "description": "Unable to complete the control request",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "503": {
                        "description": "Site is temporarily unavailable",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "504": {
                        "description": "Timed out waiting for live feedback; command outcome may be unknown",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    }
                }
            }
        },
        "/sites/{siteID}/feedback": {
            "get": {
                "security": [
                    {
                        "ApiKeyAuth": []
                    }
                ],
                "description": "Returns only state and responseCode. State contains grid, solar, and storage measurements. Missing components are null; unavailable measurements are omitted. Power is in watts, energy in watt-hours, and daily totals use UTC.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "developer"
                ],
                "summary": "Get site feedback",
                "operationId": "developer-get-site-feedback",
                "parameters": [
                    {
                        "minimum": 1,
                        "type": "integer",
                        "description": "Site ID",
                        "name": "siteID",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Site feedback and available device measurements",
                        "schema": {
                            "$ref": "#/definitions/api.SiteFeedbackResponse"
                        }
                    },
                    "400": {
                        "description": "Invalid site ID",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "401": {
                        "description": "Missing, invalid, or revoked API key",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "403": {
                        "description": "No access to this site",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "500": {
                        "description": "Internal server error",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "502": {
                        "description": "Failed to retrieve site feedback",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "503": {
                        "description": "Site is temporarily unavailable",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "504": {
                        "description": "Timed out waiting for site feedback",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    }
                }
            }
        },
        "/sites/{siteID}/schedules": {
            "get": {
                "security": [
                    {
                        "ApiKeyAuth": []
                    }
                ],
                "description": "Lists schedules for date (dd/mm/yyyy), defaulting to today in UTC. created_at, start_time, and end_time use UTC RFC 3339 strings (YYYY-MM-DDTHH:mm:ssZ). The source and market fields are omitted.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "developer"
                ],
                "summary": "List site schedules",
                "operationId": "developer-list-site-schedules",
                "parameters": [
                    {
                        "minimum": 1,
                        "type": "integer",
                        "description": "Site ID",
                        "name": "siteID",
                        "in": "path",
                        "required": true
                    },
                    {
                        "type": "string",
                        "example": "18/09/2026",
                        "description": "Date in dd/mm/yyyy; defaults to today in UTC",
                        "name": "date",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/api.ListSchedulesResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "state": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/definitions/api.ScheduleListState"
                                                },
                                                {
                                                    "type": "object",
                                                    "properties": {
                                                        "schedules": {
                                                            "type": "array",
                                                            "items": {
                                                                "$ref": "#/definitions/api.ScheduleState"
                                                            }
                                                        }
                                                    }
                                                }
                                            ]
                                        }
                                    }
                                }
                            ]
                        }
                    },
                    "400": {
                        "description": "Invalid site ID or date",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "401": {
                        "description": "Missing, invalid, or revoked API key",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "403": {
                        "description": "No access to this site",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "500": {
                        "description": "Internal server error",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "502": {
                        "description": "Request failed, was rejected, or returned invalid feedback",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "503": {
                        "description": "Site is temporarily unavailable",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "504": {
                        "description": "Timed out waiting for schedules",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    }
                }
            },
            "post": {
                "security": [
                    {
                        "ApiKeyAuth": []
                    }
                ],
                "description": "Creates a solar/storage schedule. Supply UTC RFC 3339 times ending in Z with whole-second precision; end_time must follow start_time.\nSolar policies: setpoint, feed-in-restriction, cost, off. Storage policies: setpoint, peak-shaving-only, cost, self-consumption, off. Peak shaving requires configured site thresholds; off disables limit guarding.\nSetpoint requires power_setpoint_w: positive storage power charges, negative discharges; solar power must be nonnegative. remove_overlap may delete overlapping schedules. A timeout does not prove creation failed: do not blindly retry.\nOptional site_import and site_export specify site import and export limits in watts. Omitted limits are not sent; explicit zero values are sent.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "developer"
                ],
                "summary": "Create a site schedule",
                "operationId": "developer-create-site-schedule",
                "parameters": [
                    {
                        "enum": [
                            "application/json"
                        ],
                        "type": "string",
                        "default": "application/json",
                        "description": "JSON request media type",
                        "name": "Content-Type",
                        "in": "header",
                        "required": true
                    },
                    {
                        "minimum": 1,
                        "type": "integer",
                        "description": "Site ID",
                        "name": "siteID",
                        "in": "path",
                        "required": true
                    },
                    {
                        "description": "Schedule to create",
                        "name": "schedule",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/api.CreateScheduleRequest"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Schedule created",
                        "schema": {
                            "$ref": "#/definitions/api.CreateScheduleResponse"
                        }
                    },
                    "400": {
                        "description": "Invalid JSON, timestamps, or schedule parameters",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "401": {
                        "description": "Missing, invalid, or revoked API key",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "403": {
                        "description": "No access to this site",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "415": {
                        "description": "Content-Type must be application/json",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "500": {
                        "description": "Internal server error",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "502": {
                        "description": "Unable to confirm schedule creation",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "503": {
                        "description": "Site is temporarily unavailable",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "504": {
                        "description": "Request timed out; creation outcome is unknown",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    }
                }
            }
        },
        "/sites/{siteID}/schedules/active": {
            "get": {
                "security": [
                    {
                        "ApiKeyAuth": []
                    }
                ],
                "description": "Retrieves the active solar/storage schedule; state may be null. created_at, start_time, and end_time use UTC RFC 3339 strings (YYYY-MM-DDTHH:mm:ssZ), matching schedule creation. The source and market fields are omitted.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "developer"
                ],
                "summary": "Get the active site schedule",
                "operationId": "developer-get-active-site-schedule",
                "parameters": [
                    {
                        "minimum": 1,
                        "type": "integer",
                        "description": "Site ID",
                        "name": "siteID",
                        "in": "path",
                        "required": true
                    },
                    {
                        "enum": [
                            "solar",
                            "storage"
                        ],
                        "type": "string",
                        "description": "Device group",
                        "name": "device_type",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/api.ActiveScheduleResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "state": {
                                            "$ref": "#/definitions/api.ScheduleState"
                                        }
                                    }
                                }
                            ]
                        }
                    },
                    "400": {
                        "description": "Invalid site ID or missing/unsupported device_type",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "401": {
                        "description": "Missing, invalid, or revoked API key",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "403": {
                        "description": "No access to this site",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "500": {
                        "description": "Internal server error",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "502": {
                        "description": "Request failed, was rejected, or returned invalid feedback",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "503": {
                        "description": "Site is temporarily unavailable",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "504": {
                        "description": "Timed out waiting for active schedule",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    }
                }
            }
        },
        "/sites/{siteID}/schedules/batch": {
            "post": {
                "security": [
                    {
                        "ApiKeyAuth": []
                    }
                ],
                "description": "Sends all schedules in one command. Each item uses the same fields, policies, and validation as POST /sites/{siteID}/schedules, including optional site_import and site_export limits in watts.\nSupply UTC RFC 3339 times ending in Z with whole-second precision; end_time must follow start_time. Solar policies: setpoint, feed-in-restriction, cost, off. Storage policies: setpoint, peak-shaving-only, cost, self-consumption, off. Setpoint requires power_setpoint_w; only storage permits negative power. Peak shaving requires configured site thresholds; off disables limit guarding.\nThe schedules array must be nonempty. There is no schedule-count limit imposed by this endpoint. All items are validated before publishing; an invalid item returns HTTP 400 with its zero-based schedules[index] and reason. Unknown fields are rejected. Optional limits preserve explicit zero values.\nEach schedule without remove_overlap=true is checked against every other batch item of the same device_type, regardless of array position. An overlap rejects the batch before publishing and identifies both zero-based indexes. All overlapping items must explicitly enable remove_overlap. Adjacent intervals and overlaps between different device types are allowed; input order is preserved. Existing controller schedules are still checked by the controller.\nremove_overlap may delete overlapping schedules. Atomicity and rollback are not guaranteed. Rejection, invalid feedback, or timeout may leave some schedules created; do not blindly retry. Returned schedule IDs are not guaranteed to follow input order.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "developer"
                ],
                "summary": "Create a batch of site schedules",
                "operationId": "developer-create-site-schedules-batch",
                "parameters": [
                    {
                        "enum": [
                            "application/json"
                        ],
                        "type": "string",
                        "default": "application/json",
                        "description": "JSON request media type",
                        "name": "Content-Type",
                        "in": "header",
                        "required": true
                    },
                    {
                        "minimum": 1,
                        "type": "integer",
                        "description": "Site ID",
                        "name": "siteID",
                        "in": "path",
                        "required": true
                    },
                    {
                        "description": "Schedules to create",
                        "name": "batch",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/api.CreateSchedulesRequest"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Batch creation acknowledged",
                        "schema": {
                            "$ref": "#/definitions/api.CreateSchedulesResponse"
                        }
                    },
                    "400": {
                        "description": "Invalid JSON, empty batch, or invalid schedule at the specified zero-based index; nothing published",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "401": {
                        "description": "Missing, invalid, or revoked API key",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "403": {
                        "description": "No access to this site",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "415": {
                        "description": "Content-Type must be application/json",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "500": {
                        "description": "Internal server error",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "502": {
                        "description": "Batch rejected or creation could not be confirmed; some schedules may have been created",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "503": {
                        "description": "Site is temporarily unavailable",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "504": {
                        "description": "Request timed out; some schedules may have been created",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    }
                }
            }
        },
        "/sites/{siteID}/schedules/next": {
            "get": {
                "security": [
                    {
                        "ApiKeyAuth": []
                    }
                ],
                "description": "Retrieves the next upcoming solar/storage schedule; state may be null. created_at, start_time, and end_time use UTC RFC 3339 strings (YYYY-MM-DDTHH:mm:ssZ), matching schedule creation. The source and market fields are omitted.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "developer"
                ],
                "summary": "Get the next site schedule",
                "operationId": "developer-get-next-site-schedule",
                "parameters": [
                    {
                        "minimum": 1,
                        "type": "integer",
                        "description": "Site ID",
                        "name": "siteID",
                        "in": "path",
                        "required": true
                    },
                    {
                        "enum": [
                            "solar",
                            "storage"
                        ],
                        "type": "string",
                        "description": "Device group",
                        "name": "device_type",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/api.NextScheduleResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "state": {
                                            "$ref": "#/definitions/api.ScheduleState"
                                        }
                                    }
                                }
                            ]
                        }
                    },
                    "400": {
                        "description": "Invalid site ID or missing/unsupported device_type",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "401": {
                        "description": "Missing, invalid, or revoked API key",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "403": {
                        "description": "No access to this site",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "404": {
                        "description": "No next schedule found",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "500": {
                        "description": "Internal server error",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "502": {
                        "description": "Request failed, was rejected, or returned invalid feedback",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "503": {
                        "description": "Site is temporarily unavailable",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "504": {
                        "description": "Timed out waiting for next schedule",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    }
                }
            }
        },
        "/sites/{siteID}/schedules/{scheduleID}": {
            "get": {
                "security": [
                    {
                        "ApiKeyAuth": []
                    }
                ],
                "description": "Retrieves a schedule by its numeric ID. created_at, start_time, and end_time use UTC RFC 3339 strings (YYYY-MM-DDTHH:mm:ssZ), matching schedule creation. The source and market fields are omitted.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "developer"
                ],
                "summary": "Get a site schedule",
                "operationId": "developer-get-site-schedule",
                "parameters": [
                    {
                        "minimum": 1,
                        "type": "integer",
                        "description": "Site ID",
                        "name": "siteID",
                        "in": "path",
                        "required": true
                    },
                    {
                        "minimum": 0,
                        "type": "integer",
                        "format": "int64",
                        "description": "Numeric schedule ID",
                        "name": "scheduleID",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "allOf": [
                                {
                                    "$ref": "#/definitions/api.GetScheduleResponse"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "state": {
                                            "$ref": "#/definitions/api.ScheduleState"
                                        }
                                    }
                                }
                            ]
                        }
                    },
                    "400": {
                        "description": "Invalid site or schedule ID",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "401": {
                        "description": "Missing, invalid, or revoked API key",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "403": {
                        "description": "No access to this site",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "500": {
                        "description": "Internal server error",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "502": {
                        "description": "Request failed, was rejected, or returned invalid feedback",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "503": {
                        "description": "Site is temporarily unavailable",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "504": {
                        "description": "Timed out waiting for schedule",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    }
                }
            },
            "delete": {
                "security": [
                    {
                        "ApiKeyAuth": []
                    }
                ],
                "description": "Deletes a schedule that has not started, using its numeric schedule ID. No request body is required. A timeout does not prove deletion failed: do not blindly retry.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "developer"
                ],
                "summary": "Delete a site schedule",
                "operationId": "developer-delete-site-schedule",
                "parameters": [
                    {
                        "minimum": 1,
                        "type": "integer",
                        "description": "Site ID",
                        "name": "siteID",
                        "in": "path",
                        "required": true
                    },
                    {
                        "minimum": 0,
                        "type": "integer",
                        "format": "int64",
                        "description": "Numeric schedule ID",
                        "name": "scheduleID",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Schedule deleted",
                        "schema": {
                            "$ref": "#/definitions/api.DeleteScheduleResponse"
                        }
                    },
                    "400": {
                        "description": "Invalid site or schedule ID",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "401": {
                        "description": "Missing, invalid, or revoked API key",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "403": {
                        "description": "No access to this site",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "404": {
                        "description": "Schedule not found",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "500": {
                        "description": "Internal server error",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "502": {
                        "description": "Unable to confirm schedule deletion",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "503": {
                        "description": "Site is temporarily unavailable",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    },
                    "504": {
                        "description": "Request timed out; deletion outcome is unknown",
                        "schema": {
                            "$ref": "#/definitions/middlewares.ErrorResponse"
                        }
                    }
                }
            }
        }
    },
    "definitions": {
        "api.ActiveScheduleResponse": {
            "type": "object",
            "properties": {
                "responseCode": {
                    "type": "integer",
                    "enum": [
                        0
                    ]
                },
                "state": {
                    "type": "object",
                    "additionalProperties": {},
                    "x-nullable": true
                }
            }
        },
        "api.CreateScheduleRequest": {
            "type": "object",
            "required": [
                "device_type",
                "end_time",
                "policy",
                "start_time"
            ],
            "properties": {
                "device_type": {
                    "type": "string",
                    "enum": [
                        "solar",
                        "storage"
                    ],
                    "example": "storage"
                },
                "end_time": {
                    "type": "string",
                    "format": "date-time",
                    "example": "2026-10-01T10:30:00Z"
                },
                "policy": {
                    "description": "Must be supported by device_type. See the operation description for combinations.",
                    "type": "string",
                    "enum": [
                        "setpoint",
                        "feed-in-restriction",
                        "cost",
                        "off",
                        "peak-shaving-only",
                        "self-consumption"
                    ],
                    "example": "setpoint"
                },
                "power_setpoint_w": {
                    "description": "Required for setpoint; storage uses positive watts to charge and negative to discharge.",
                    "type": "number",
                    "example": 5000
                },
                "remove_overlap": {
                    "description": "Allows deletion of overlapping schedules. Defaults to false.",
                    "type": "boolean",
                    "default": false
                },
                "site_export": {
                    "description": "Optional site export limit, in watts.",
                    "type": "number",
                    "example": 10000
                },
                "site_import": {
                    "description": "Optional site import limit, in watts.",
                    "type": "number",
                    "example": 25000
                },
                "start_time": {
                    "type": "string",
                    "format": "date-time",
                    "example": "2026-10-01T10:15:00Z"
                }
            }
        },
        "api.CreateScheduleResponse": {
            "type": "object",
            "properties": {
                "responseCode": {
                    "type": "integer",
                    "enum": [
                        0
                    ]
                },
                "state": {
                    "$ref": "#/definitions/api.CreatedSchedule"
                }
            }
        },
        "api.CreateSchedulesRequest": {
            "type": "object",
            "required": [
                "schedules"
            ],
            "properties": {
                "schedules": {
                    "description": "At least one schedule is required. Validation errors use zero-based indexes.",
                    "type": "array",
                    "minItems": 1,
                    "items": {
                        "$ref": "#/definitions/api.CreateScheduleRequest"
                    }
                }
            }
        },
        "api.CreateSchedulesResponse": {
            "type": "object",
            "properties": {
                "responseCode": {
                    "type": "integer",
                    "enum": [
                        0
                    ]
                },
                "state": {
                    "$ref": "#/definitions/api.CreatedSchedules"
                }
            }
        },
        "api.CreatedSchedule": {
            "type": "object",
            "properties": {
                "deleted_ids": {
                    "description": "Numeric identifiers; an empty array means no schedules were removed.",
                    "type": "array",
                    "items": {
                        "type": "integer"
                    }
                },
                "schedule_id": {
                    "description": "Numeric schedule ID. Use this ID to retrieve or delete the schedule.",
                    "type": "integer",
                    "minimum": 0,
                    "example": 123
                },
                "tag": {
                    "type": "string",
                    "x-nullable": true
                }
            }
        },
        "api.CreatedSchedules": {
            "type": "object",
            "properties": {
                "deleted_ids": {
                    "description": "IDs removed by remove_overlap; an empty array means none were removed.",
                    "type": "array",
                    "items": {
                        "type": "integer"
                    }
                },
                "schedule_ids": {
                    "description": "Created schedule IDs. Their order is not guaranteed to match the input.",
                    "type": "array",
                    "items": {
                        "type": "integer"
                    }
                }
            }
        },
        "api.DeleteScheduleResponse": {
            "type": "object",
            "properties": {
                "responseCode": {
                    "type": "integer",
                    "enum": [
                        0
                    ]
                },
                "state": {
                    "$ref": "#/definitions/api.DeletedSchedule"
                }
            }
        },
        "api.DeletedSchedule": {
            "type": "object",
            "properties": {
                "message": {
                    "type": "string",
                    "example": "Schedule 123 removed successfully."
                }
            }
        },
        "api.DeveloperSitesResponse": {
            "type": "object",
            "properties": {
                "sites": {
                    "description": "Sites is null when no accessible sites were found.",
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/developer.DevSitesResponse"
                    },
                    "x-nullable": true
                }
            }
        },
        "api.GetScheduleResponse": {
            "type": "object",
            "properties": {
                "responseCode": {
                    "type": "integer",
                    "enum": [
                        0
                    ]
                },
                "state": {
                    "type": "object",
                    "additionalProperties": {}
                }
            }
        },
        "api.ListSchedulesResponse": {
            "type": "object",
            "properties": {
                "responseCode": {
                    "type": "integer",
                    "enum": [
                        0
                    ]
                },
                "state": {
                    "$ref": "#/definitions/api.ScheduleListState"
                }
            }
        },
        "api.LiveControlRequest": {
            "type": "object",
            "properties": {
                "site_startChargeBelow_W": {
                    "description": "Site power below which battery charging starts, in watts; requires peak-shaving-only.",
                    "type": "number"
                },
                "site_startDischargeAbove_W": {
                    "description": "Site power above which battery discharging starts, in watts; requires peak-shaving-only.",
                    "type": "number"
                },
                "site_stopChargeAbove_W": {
                    "description": "Site power above which battery charging stops, in watts; requires peak-shaving-only.",
                    "type": "number"
                },
                "site_stopDischargeBelow_W": {
                    "description": "Site power below which battery discharging stops, in watts; requires peak-shaving-only.",
                    "type": "number"
                },
                "solar_maxProductionPower_W": {
                    "description": "Upper limit on solar production, in watts.",
                    "type": "number",
                    "minimum": 0
                },
                "solar_policy": {
                    "description": "Solar mode: setpoint caps output; feed-in-restriction follows grid limits; cost follows prices; off disables control; fallback restores defaults.",
                    "type": "string",
                    "enum": [
                        "setpoint",
                        "feed-in-restriction",
                        "cost",
                        "off",
                        "fallback"
                    ]
                },
                "solar_power_setpoint_w": {
                    "description": "Maximum combined solar output in watts; required with solar_policy setpoint.",
                    "type": "number",
                    "minimum": 0
                },
                "storage_maxChargePower_W": {
                    "description": "Upper limit on battery charging power, in watts.",
                    "type": "number",
                    "minimum": 0
                },
                "storage_maxDischargePower_W": {
                    "description": "Upper limit on battery discharging power, in watts.",
                    "type": "number",
                    "minimum": 0
                },
                "storage_policy": {
                    "description": "Battery mode: setpoint controls power; peak-shaving-only uses site thresholds; cost follows prices; self-consumption uses surplus solar; off disables control; fallback restores defaults.",
                    "type": "string",
                    "enum": [
                        "setpoint",
                        "peak-shaving-only",
                        "cost",
                        "self-consumption",
                        "off",
                        "fallback"
                    ]
                },
                "storage_power_setpoint_w": {
                    "description": "Combined battery power in watts: positive charges, negative discharges; required with storage_policy setpoint.",
                    "type": "number",
                    "example": 1000
                }
            }
        },
        "api.LiveGridState": {
            "type": "object",
            "properties": {
                "active_power_W": {
                    "description": "Current active power measured at the grid connection, in watts.",
                    "type": "number"
                },
                "export_limit_W": {
                    "description": "Current grid export limit, in watts.",
                    "type": "number"
                },
                "import_limit_W": {
                    "description": "Current grid import limit, in watts.",
                    "type": "number"
                },
                "today_exported_energy_Wh": {
                    "description": "Energy exported to the grid since the start of the UTC day, in watt-hours.",
                    "type": "number"
                },
                "today_imported_energy_Wh": {
                    "description": "Energy imported from the grid since the start of the UTC day, in watt-hours.",
                    "type": "number"
                }
            }
        },
        "api.LiveResponse": {
            "type": "object",
            "properties": {
                "responseCode": {
                    "description": "Zero means the controller accepted the command.",
                    "type": "integer",
                    "enum": [
                        0
                    ]
                },
                "state": {
                    "$ref": "#/definitions/api.LiveState"
                }
            }
        },
        "api.LiveSolarState": {
            "type": "object",
            "properties": {
                "active_power_W": {
                    "description": "Current power generated by the controlled solar installations, in watts.",
                    "type": "number"
                },
                "capacity_W": {
                    "description": "Combined generation capacity of the controlled solar installations, in watts.",
                    "type": "number"
                },
                "constraint_ph0_label": {
                    "description": "Reasons the controller limited the requested solar power.",
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "errorCodes": {
                    "description": "Solar device identifiers mapped to lists of device error objects.",
                    "type": "object",
                    "additionalProperties": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    }
                },
                "executed_policy": {
                    "description": "Policies applied to the controlled solar installations; entries may be null when unavailable.",
                    "type": "array",
                    "items": {
                        "type": "string"
                    },
                    "example": [
                        "follow_setpoint"
                    ]
                },
                "executed_power_W": {
                    "description": "Total power requested from the solar installations by the controller, in watts; applies to the follow_setpoint policy.",
                    "type": "number"
                },
                "nr_devices": {
                    "description": "Number of controllable solar installations at the site.",
                    "type": "integer"
                },
                "today_energy_Wh": {
                    "description": "Energy generated by controlled solar installations since the start of the UTC day, in watt-hours.",
                    "type": "number"
                }
            }
        },
        "api.LiveState": {
            "type": "object",
            "properties": {
                "grid": {
                    "allOf": [
                        {
                            "$ref": "#/definitions/api.LiveGridState"
                        }
                    ],
                    "x-nullable": true
                },
                "solar": {
                    "allOf": [
                        {
                            "$ref": "#/definitions/api.LiveSolarState"
                        }
                    ],
                    "x-nullable": true
                },
                "storage": {
                    "allOf": [
                        {
                            "$ref": "#/definitions/api.LiveStorageState"
                        }
                    ],
                    "x-nullable": true
                }
            }
        },
        "api.LiveStorageState": {
            "type": "object",
            "properties": {
                "active_power_W": {
                    "description": "Current battery charge or discharge power, in watts.",
                    "type": "number"
                },
                "constraint_ph0_label": {
                    "description": "Reasons the controller limited the requested battery power.",
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "dynamic_max_charge_power_W": {
                    "description": "Estimated available charging power, in watts (positive or zero), accounting for device limits and state-of-charge headroom.",
                    "type": "number"
                },
                "dynamic_max_discharge_power_W": {
                    "description": "Estimated available discharging power, in watts (negative or zero), accounting for device limits and state-of-charge headroom.",
                    "type": "number"
                },
                "energy_capacity_Wh": {
                    "description": "Combined energy capacity of the controlled batteries, in watt-hours.",
                    "type": "number"
                },
                "energy_stored_Wh": {
                    "description": "Energy currently held in the controlled batteries, in watt-hours.",
                    "type": "number"
                },
                "errorCodes": {
                    "description": "Battery identifiers mapped to lists of device error objects.",
                    "type": "object",
                    "additionalProperties": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "additionalProperties": {}
                        }
                    }
                },
                "executed_policy": {
                    "description": "Policies applied to the controlled batteries; entries may be null when unavailable.",
                    "type": "array",
                    "items": {
                        "type": "string"
                    },
                    "example": [
                        "follow_setpoint"
                    ]
                },
                "executed_power_W": {
                    "description": "Total power requested from the batteries by the controller, in watts; applies to the follow_setpoint policy.",
                    "type": "number"
                },
                "max_charge_power_W": {
                    "description": "Maximum battery charging power, in watts.",
                    "type": "number"
                },
                "max_discharge_power_W": {
                    "description": "Maximum battery discharging power, in watts.",
                    "type": "number"
                },
                "mean_soc_perc": {
                    "description": "Capacity-weighted state of charge across the batteries, as a percentage.",
                    "type": "number"
                },
                "nr_devices": {
                    "description": "Number of controllable batteries at the site.",
                    "type": "integer"
                },
                "today_charged_Wh": {
                    "description": "Energy charged into controlled batteries since the start of the UTC day, in watt-hours.",
                    "type": "number"
                },
                "today_discharged_Wh": {
                    "description": "Energy discharged from controlled batteries since the start of the UTC day, in watt-hours.",
                    "type": "number"
                }
            }
        },
        "api.NextScheduleResponse": {
            "type": "object",
            "properties": {
                "responseCode": {
                    "type": "integer",
                    "enum": [
                        0
                    ]
                },
                "state": {
                    "type": "object",
                    "additionalProperties": {},
                    "x-nullable": true
                }
            }
        },
        "api.ScheduleListState": {
            "type": "object",
            "properties": {
                "schedules": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "additionalProperties": {}
                    }
                }
            }
        },
        "api.ScheduleState": {
            "type": "object",
            "properties": {
                "created_at": {
                    "description": "Creation time in UTC, with whole-second precision.",
                    "type": "string",
                    "format": "date-time",
                    "x-nullable": true,
                    "example": "2026-09-21T21:45:25Z"
                },
                "device_type": {
                    "type": "string",
                    "example": "solar"
                },
                "end_time": {
                    "description": "End time in UTC, in the same format as the POST schedule request.",
                    "type": "string",
                    "format": "date-time",
                    "x-nullable": true,
                    "example": "2026-09-30T10:15:00Z"
                },
                "id": {
                    "type": "integer",
                    "minimum": 0,
                    "example": 13
                },
                "isActiveBaseline": {
                    "description": "Numeric active-baseline flag, not a JSON boolean.",
                    "type": "integer",
                    "example": 0
                },
                "isNextBaseline": {
                    "description": "Numeric next-baseline flag, not a JSON boolean.",
                    "type": "integer",
                    "example": 0
                },
                "node_id": {
                    "type": "string",
                    "x-nullable": true
                },
                "policy": {
                    "type": "string",
                    "example": "setpoint"
                },
                "power_setpoint_w": {
                    "description": "Storage charging is positive and discharging is negative; solar power is nonnegative.",
                    "type": "number",
                    "x-nullable": true,
                    "example": 1000
                },
                "reactPowerTot_VAr": {
                    "type": "number",
                    "x-nullable": true
                },
                "site_export": {
                    "type": "number",
                    "x-nullable": true
                },
                "site_import": {
                    "type": "number",
                    "x-nullable": true
                },
                "site_setpoint_A": {
                    "type": "number",
                    "x-nullable": true
                },
                "site_startChargeBelow_W": {
                    "type": "number",
                    "x-nullable": true
                },
                "site_startDischargeAbove_W": {
                    "type": "number",
                    "x-nullable": true
                },
                "site_stopChargeAbove_W": {
                    "type": "number",
                    "x-nullable": true
                },
                "site_stopDischargeBelow_W": {
                    "type": "number",
                    "x-nullable": true
                },
                "start_time": {
                    "description": "Start time in UTC, in the same format as the POST schedule request.",
                    "type": "string",
                    "format": "date-time",
                    "x-nullable": true,
                    "example": "2026-09-30T10:00:00Z"
                }
            }
        },
        "api.SiteFeedbackResponse": {
            "type": "object",
            "properties": {
                "responseCode": {
                    "description": "Zero indicates success; other values indicate an unsuccessful response.",
                    "type": "integer",
                    "example": 0
                },
                "state": {
                    "allOf": [
                        {
                            "$ref": "#/definitions/api.LiveState"
                        }
                    ],
                    "x-nullable": true
                }
            }
        },
        "developer.DevSitesResponse": {
            "type": "object",
            "properties": {
                "id": {
                    "type": "integer"
                },
                "name": {
                    "type": "string"
                }
            }
        },
        "middlewares.ErrorResponse": {
            "type": "object",
            "properties": {
                "errors": {
                    "type": "string",
                    "example": "invalid site ID"
                }
            }
        }
    },
    "securityDefinitions": {
        "ApiKeyAuth": {
            "type": "apiKey",
            "name": "X-API-Key",
            "in": "header"
        }
    }
}