# API Reference Базовый URL: `http://:` Контент ответов: `application/json; charset=utf-8` ## GET /health Проверка состояния сервиса. ### 200 OK ```json { "status": "ok", "updated_at_utc": "2026-03-02T12:34:56+00:00", "error": "" } ``` ### 503 Service Unavailable ```json { "status": "warming_up", "updated_at_utc": null, "error": "no data yet" } ``` ## GET /result Последний итоговый результат расчета. ### 200 OK ```json { "status": "ok", "updated_at_utc": "2026-03-02T12:35:01+00:00", "data": { "timestamp_utc": "2026-03-02T12:35:01+00:00", "selected_frequency_hz": 868100000.0, "selected_frequency_mhz": 868.1, "position": { "x": 1.2, "y": 2.3, "z": 0.4 }, "rmse_m": 0.52, "frequency_table": [] }, "output_delivery": { "enabled": true, "status": "ok", "ok_count": 1, "error_count": 0, "skipped_count": 0, "servers": [] } } ``` ### 503 Service Unavailable ```json { "status": "warming_up", "updated_at_utc": null, "error": "no data yet" } ``` ## GET /frequencies Таблица решений по частотам + статус доставки. ### 200 OK ```json { "status": "ok", "updated_at_utc": "2026-03-02T12:35:01+00:00", "selected_frequency_hz": 868100000.0, "selected_frequency_mhz": 868.1, "frequency_table": [ { "frequency_hz": 433920000.0, "frequency_mhz": 433.92, "position": { "x": 1.0, "y": 2.0, "z": 0.3 }, "rmse_m": 0.65, "exact": false } ], "output_delivery": { "enabled": true, "status": "partial" } } ``` ## GET /config Возвращает текущий конфиг. Особенность: - поле `runtime.write_api_token` редактируется в ответе (`""`), - добавляется `runtime.write_api_token_set` (bool). ### 200 OK ```json { "status": "ok", "config_path": "config.json", "config": { "runtime": { "write_api_token": "", "write_api_token_set": true } } } ``` ## POST /refresh Принудительный запуск одного цикла опроса и расчета. Тело запроса: `{}` (или любой JSON-объект). ### Заголовки при включенном токене - `X-API-Token: ` или - `Authorization: Bearer ` ### 200 OK ```json { "status": "ok", "updated_at_utc": "2026-03-02T12:35:20+00:00" } ``` ### 401 Unauthorized ```json { "status": "error", "error": "unauthorized: missing or invalid API token" } ``` ### 500 Internal Server Error ```json { "status": "error", "error": "Output server(s) rejected payload: sink-a" } ``` ## POST /config Валидация и горячее применение нового конфига. Ограничения: - тело должно быть JSON-объектом, - максимальный размер `1_000_000` байт. ### Заголовки при включенном токене - `X-API-Token: ` или - `Authorization: Bearer ` ### 200 OK ```json { "status": "ok", "saved": true, "save_error": "", "restart_required": false, "applied": true, "config_path": "config.json" } ``` ### 400 Bad Request ```json { "status": "error", "error": "Config validation failed: input.receivers must contain at least 3 objects." } ``` ### 413 Payload Too Large ```json { "status": "error", "error": "Config payload too large: 1500000 bytes, max is 1000000" } ``` ### 401 Unauthorized ```json { "status": "error", "error": "unauthorized: missing or invalid API token" } ``` ## UI и статические файлы - `GET /` и `GET /ui` — веб-интерфейс. - `GET /static/*` — JS/CSS.