{
    "schemes": ["http","https"],
    "swagger": "2.0",
    "info": {
        "description": "Unified API documentation generated from Swaggo annotations in the unified server, HTTP API, and auth packages.",
        "title": "Safecast Unified Server API",
        "contact": {
            "name": "Safecast",
            "url": "https://safecast.org"
        },
        "license": {
            "name": "CC0 1.0 Universal",
            "url": "https://creativecommons.org/publicdomain/zero/1.0/"
        },
        "version": "1.0"
    },
    "host": "localhost:8765",
    "basePath": "/",
    "paths": {
        "/api": {
            "get": {
                "description": "Returns endpoint index, disclaimers, and dataset summary counts.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "core"
                ],
                "summary": "Get API overview",
                "responses": {
                    "200": {
                        "description": "Overview payload",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/backfill": {
            "post": {
                "description": "Backfills upload records from existing spectra entries.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin backfill uploads from spectra",
                "responses": {
                    "200": {
                        "description": "Backfill result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/backfill-countries": {
            "post": {
                "description": "Starts background country backfill for markers with coordinates.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin backfill marker countries",
                "responses": {
                    "200": {
                        "description": "Backfill status",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/cache": {
            "post": {
                "description": "Performs cache operations such as clear/stats via action query parameter.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin cache operations",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Cache action (e.g. clear, stats)",
                        "name": "action",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Cache operation result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/delete": {
            "post": {
                "description": "Deletes a track and associated marker data.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin delete single track",
                "parameters": [
                    {
                        "description": "Delete request payload",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "type": "object"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Delete result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/delete-multiple": {
            "post": {
                "description": "Deletes multiple tracks in one request.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin delete multiple tracks",
                "parameters": [
                    {
                        "description": "Bulk delete request payload",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "type": "object"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Delete result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/import-from-safecast": {
            "post": {
                "description": "Triggers a date-ranged Safecast import and streams progress updates.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "text/event-stream"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin import from Safecast API",
                "responses": {
                    "200": {
                        "description": "Streaming progress",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/mcp/data": {
            "get": {
                "description": "Returns paginated MCP analytics rows for a selected table. For table=mcp_query_log, the columns are tool_name, created_at, duration_ms, result_count, client_info, and params.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin MCP analytics data",
                "parameters": [
                    {
                        "enum": [
                            "chat_questions",
                            "mcp_query_log",
                            "mcp_ai_query_log"
                        ],
                        "type": "string",
                        "description": "Analytics table name",
                        "name": "table",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "integer",
                        "description": "Page size",
                        "name": "limit",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "Offset",
                        "name": "offset",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Sort column (for mcp_query_log, default is created_at)",
                        "name": "sort",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Sort order: asc or desc",
                        "name": "order",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Search term",
                        "name": "search",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Analytics rows",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid table",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Analytics unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/mcp/delete": {
            "post": {
                "description": "Deletes selected or filtered MCP analytics rows. For table=mcp_query_log, ids map to created_at values.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin MCP analytics delete",
                "parameters": [
                    {
                        "enum": [
                            "chat_questions",
                            "mcp_query_log",
                            "mcp_ai_query_log"
                        ],
                        "type": "string",
                        "description": "Analytics table name",
                        "name": "table",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "Comma-separated row IDs",
                        "name": "ids",
                        "in": "query"
                    },
                    {
                        "type": "boolean",
                        "description": "Delete all filtered rows",
                        "name": "all",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Search term when all=true",
                        "name": "search",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Delete result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Analytics unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            },
            "delete": {
                "description": "Deletes selected or filtered MCP analytics rows. For table=mcp_query_log, ids map to created_at values.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin MCP analytics delete",
                "parameters": [
                    {
                        "enum": [
                            "chat_questions",
                            "mcp_query_log",
                            "mcp_ai_query_log"
                        ],
                        "type": "string",
                        "description": "Analytics table name",
                        "name": "table",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "Comma-separated row IDs",
                        "name": "ids",
                        "in": "query"
                    },
                    {
                        "type": "boolean",
                        "description": "Delete all filtered rows",
                        "name": "all",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Search term when all=true",
                        "name": "search",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Delete result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Analytics unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/mcp/export": {
            "get": {
                "description": "Exports MCP analytics rows as CSV for a selected table. For table=mcp_query_log, rows are ordered by created_at descending.",
                "produces": [
                    "text/csv"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin MCP analytics export",
                "parameters": [
                    {
                        "enum": [
                            "chat_questions",
                            "mcp_query_log",
                            "mcp_ai_query_log"
                        ],
                        "type": "string",
                        "description": "Analytics table name",
                        "name": "table",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "Search term",
                        "name": "search",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "CSV export",
                        "schema": {
                            "type": "file"
                        }
                    },
                    "400": {
                        "description": "Invalid table",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Analytics unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/mcp/update": {
            "put": {
                "description": "Updates one or more editable fields of a single MCP analytics row. Only whitelisted columns (e.g. question, answer, source, model, country) may be modified; timestamps and computed columns are ignored.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin MCP analytics update",
                "parameters": [
                    {
                        "enum": [
                            "chat_questions",
                            "mcp_query_log",
                            "mcp_ai_query_log",
                            "qa_embeddings",
                            "location_knowledge"
                        ],
                        "type": "string",
                        "description": "Analytics table name",
                        "name": "table",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "Row key value (integer for id-keyed tables, timestamp string for log tables)",
                        "name": "id",
                        "in": "query",
                        "required": true
                    },
                    {
                        "description": "JSON object mapping editable field names to their new string values",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "type": "object"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "status: ok",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "405": {
                        "description": "Method not allowed",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "500": {
                        "description": "Update failed",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Analytics unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            },
            "post": {
                "description": "Updates one or more editable fields of a single MCP analytics row. Only whitelisted columns (e.g. question, answer, source, model, country) may be modified; timestamps and computed columns are ignored.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin MCP analytics update",
                "parameters": [
                    {
                        "enum": [
                            "chat_questions",
                            "mcp_query_log",
                            "mcp_ai_query_log",
                            "qa_embeddings",
                            "location_knowledge"
                        ],
                        "type": "string",
                        "description": "Analytics table name",
                        "name": "table",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "Row key value (integer for id-keyed tables, timestamp string for log tables)",
                        "name": "id",
                        "in": "query",
                        "required": true
                    },
                    {
                        "description": "JSON object mapping editable field names to their new string values",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "type": "object"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "status: ok",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "405": {
                        "description": "Method not allowed",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "500": {
                        "description": "Update failed",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Analytics unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/realtime/data": {
            "get": {
                "description": "Returns paginated latest realtime device readings.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin realtime device data",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Page size",
                        "name": "limit",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "Offset",
                        "name": "offset",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Sort column",
                        "name": "sort",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Sort order: asc or desc",
                        "name": "order",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Search term",
                        "name": "search",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Realtime rows",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/realtime/delete": {
            "post": {
                "description": "Deletes selected or filtered realtime measurements.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin realtime delete",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Comma-separated row IDs",
                        "name": "ids",
                        "in": "query"
                    },
                    {
                        "type": "boolean",
                        "description": "Delete all filtered rows",
                        "name": "all",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Search term when all=true",
                        "name": "search",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Delete result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            },
            "delete": {
                "description": "Deletes selected or filtered realtime measurements.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin realtime delete",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Comma-separated row IDs",
                        "name": "ids",
                        "in": "query"
                    },
                    {
                        "type": "boolean",
                        "description": "Delete all filtered rows",
                        "name": "all",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Search term when all=true",
                        "name": "search",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Delete result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/realtime/export": {
            "get": {
                "description": "Exports latest realtime device readings as CSV.",
                "produces": [
                    "text/csv"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin realtime export",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Search term",
                        "name": "search",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "CSV export",
                        "schema": {
                            "type": "file"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/tour/steps": {
            "get": {
                "description": "Returns all tour step rows for admin editing.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin tour steps list",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Sort column",
                        "name": "sort",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Sort order",
                        "name": "order",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Tour step rows",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            },
            "post": {
                "description": "Creates a new tour step row.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin tour step create",
                "responses": {
                    "201": {
                        "description": "Create result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/tour/steps/reorder": {
            "post": {
                "description": "Rewrites sort_order to match a supplied ID order.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin tour steps reorder",
                "responses": {
                    "200": {
                        "description": "Reorder result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/tour/steps/{id}": {
            "put": {
                "description": "Update (PUT) or delete (DELETE) a tour step row by ID.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin tour step update/delete",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Tour step ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/tracks": {
            "get": {
                "description": "Returns paginated track statistics for admin users.",
                "produces": [
                    "text/html"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin tracks dashboard data",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Page size",
                        "name": "limit",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "Page number",
                        "name": "page",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Free-text search",
                        "name": "search",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Detector filter",
                        "name": "detector",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "HTML admin page",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/translations": {
            "get": {
                "description": "Returns paginated translation rows for admin editing.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin translations list",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Page size",
                        "name": "limit",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "Offset",
                        "name": "offset",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Sort column",
                        "name": "sort",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Sort order",
                        "name": "order",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Search term",
                        "name": "search",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Language code filter",
                        "name": "lang",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Translation rows",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            },
            "post": {
                "description": "Creates a translation row or updates existing key/language pair.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin translation create",
                "responses": {
                    "201": {
                        "description": "Create result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/translations/reload": {
            "post": {
                "description": "Reloads in-memory translations from database.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin translations reload",
                "responses": {
                    "200": {
                        "description": "Reload result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "500": {
                        "description": "Reload failed",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/translations/{id}": {
            "put": {
                "description": "Updates translation value by translation row ID.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin translation update",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Translation row ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Update result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            },
            "delete": {
                "description": "Deletes translation row by ID.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin translation delete",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Translation row ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Delete result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/uploads": {
            "get": {
                "description": "Returns paginated upload records for admin users.",
                "produces": [
                    "text/html"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin uploads dashboard data",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Page size",
                        "name": "limit",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "Page number",
                        "name": "page",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Filter by internal user ID",
                        "name": "user_id",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Free-text search",
                        "name": "search",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "HTML admin page",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/admin/users": {
            "get": {
                "description": "Returns paginated user list for admin users.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin list users",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Page size",
                        "name": "limit",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "Offset",
                        "name": "offset",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Search term",
                        "name": "search",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "User rows",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/api/admin/users/create": {
            "post": {
                "description": "Creates a user account as admin.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin create user",
                "parameters": [
                    {
                        "description": "Create-user payload",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/auth.AdminCreateUserRequest"
                        }
                    }
                ],
                "responses": {
                    "201": {
                        "description": "Create result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "409": {
                        "description": "Duplicate user",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/api/admin/users/{id}": {
            "put": {
                "description": "Updates user fields by user ID.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin update user",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "User ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "description": "Update-user payload; fields are optional. Includes password and external_id.",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/auth.AdminUpdateUserRequest"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Update result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "404": {
                        "description": "User not found",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            },
            "delete": {
                "description": "Deletes user by ID.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin delete user",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "User ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Delete result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid user ID",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            },
            "patch": {
                "description": "Updates user fields by user ID.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin update user",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "User ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "description": "Update-user payload; fields are optional. Includes password and external_id.",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/auth.AdminUpdateUserRequest"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Update result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "404": {
                        "description": "User not found",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/api/admin/users/{id}/regenerate-api-key": {
            "post": {
                "description": "Regenerates API key for a user.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin regenerate API key",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "User ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Regenerate result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/api/admin/users/{id}/reset-password": {
            "post": {
                "description": "Sends password reset/setup email for a user.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Admin reset user password",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "User ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Reset result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/api/auth/forgot-password": {
            "post": {
                "description": "Generates a password reset token and sends reset email when account exists.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "auth"
                ],
                "summary": "Request password reset",
                "parameters": [
                    {
                        "description": "Forgot-password request",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "type": "object"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Request accepted",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/api/auth/login": {
            "post": {
                "description": "Authenticates by email+password or email+API key and creates a session cookie.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "auth"
                ],
                "summary": "Login user",
                "parameters": [
                    {
                        "description": "Login request",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "type": "object"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Login success",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "403": {
                        "description": "Account disabled",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/api/auth/logout": {
            "post": {
                "description": "Deletes active session and clears the session cookie.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "auth"
                ],
                "summary": "Logout user",
                "responses": {
                    "200": {
                        "description": "Logout success",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "405": {
                        "description": "Method not allowed",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/api/auth/register": {
            "post": {
                "description": "Creates a new user account and sends an email verification token when email is configured.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "auth"
                ],
                "summary": "Register a new user",
                "parameters": [
                    {
                        "description": "Registration request",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "type": "object"
                        }
                    }
                ],
                "responses": {
                    "201": {
                        "description": "Registration created",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "403": {
                        "description": "Registration disabled",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "409": {
                        "description": "Email already exists",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/api/auth/reset-password": {
            "post": {
                "description": "Resets account password using a valid reset token.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "auth"
                ],
                "summary": "Reset password with token",
                "parameters": [
                    {
                        "description": "Reset-password request",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "type": "object"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Password reset success",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid token or request",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/api/auth/verify-email": {
            "get": {
                "description": "Verifies user email using a token and redirects to the map UI on success.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "auth"
                ],
                "summary": "Verify email address",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Verification token",
                        "name": "token",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "303": {
                        "description": "Redirect to app",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "400": {
                        "description": "Invalid token",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/api/countries": {
            "get": {
                "description": "Returns per-country measurement counts and average dose-rate metadata.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "core"
                ],
                "summary": "List country statistics",
                "responses": {
                    "200": {
                        "description": "Country stats payload",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "405": {
                        "description": "Method not allowed",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/geoip": {
            "get": {
                "description": "Returns approximate latitude/longitude for the request IP when auto-locate is enabled.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "web"
                ],
                "summary": "Resolve client GeoIP coordinates",
                "responses": {
                    "200": {
                        "description": "Latitude/longitude payload",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "number",
                                "format": "float64"
                            }
                        }
                    },
                    "204": {
                        "description": "No location available",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "405": {
                        "description": "Method not allowed",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/json/weekly.tgz": {
            "get": {
                "description": "Streams the generated TGZ archive of JSON track exports.",
                "produces": [
                    "application/gzip"
                ],
                "tags": [
                    "core"
                ],
                "summary": "Download JSON archive bundle",
                "responses": {
                    "200": {
                        "description": "Archive tarball",
                        "schema": {
                            "type": "file"
                        }
                    },
                    "503": {
                        "description": "Archive unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/latest": {
            "get": {
                "description": "Returns newest measurements near a coordinate within a radius.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "core"
                ],
                "summary": "Get latest nearby measurements",
                "parameters": [
                    {
                        "type": "number",
                        "description": "Latitude",
                        "name": "lat",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Longitude",
                        "name": "lon",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Radius in meters",
                        "name": "radius_m",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "Maximum results",
                        "name": "limit",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Nearby measurements",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid parameters",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/markers/spectra": {
            "get": {
                "description": "Returns markers that contain spectroscopy data, optionally filtered by bounding box.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "web"
                ],
                "summary": "List markers with spectra",
                "parameters": [
                    {
                        "type": "number",
                        "description": "Minimum latitude",
                        "name": "minLat",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "description": "Maximum latitude",
                        "name": "maxLat",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "description": "Minimum longitude",
                        "name": "minLon",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "description": "Maximum longitude",
                        "name": "maxLon",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Markers",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "additionalProperties": true
                            }
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/api/shorten": {
            "post": {
                "description": "Creates or previews a short link for same-host URLs.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "core"
                ],
                "summary": "Create or preview short URL",
                "parameters": [
                    {
                        "description": "Short link request body",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "type": "object"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Short link response",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid payload",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "405": {
                        "description": "Method not allowed",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/spectrum/{markerID}": {
            "get": {
                "description": "Returns spectroscopy data for a marker. Download paths are delegated to the download handler.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "web"
                ],
                "summary": "Get spectrum by marker ID",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Marker ID",
                        "name": "markerID",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Spectrum payload",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid marker ID",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "404": {
                        "description": "Spectrum not found",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/spectrum/{markerID}/download": {
            "get": {
                "description": "Downloads a spectrum as json, csv, n42, or spe.",
                "produces": [
                    "application/octet-stream"
                ],
                "tags": [
                    "web"
                ],
                "summary": "Download spectrum file",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Marker ID",
                        "name": "markerID",
                        "in": "path",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "Download format: json, csv, n42, spe",
                        "name": "format",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Spectrum file",
                        "schema": {
                            "type": "file"
                        }
                    },
                    "400": {
                        "description": "Invalid marker or format",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "404": {
                        "description": "Spectrum or format data unavailable",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/tour/steps": {
            "get": {
                "description": "Returns enabled, ordered tour steps with text resolved for the requested language.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "tour"
                ],
                "summary": "Public tour steps",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Language code (defaults to 'en')",
                        "name": "lang",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Tour steps",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "additionalProperties": true
                            }
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/track-info/{id}": {
            "get": {
                "description": "Returns username, detector, and recording date metadata for a track ID.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "web"
                ],
                "summary": "Get track metadata",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Track ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Track info payload",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Missing track ID",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/api/track/{id}": {
            "get": {
                "description": "Returns full track data in JSON, CSV, or XLSX format.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "core"
                ],
                "summary": "Get track marker data",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Track ID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Track marker payload",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "404": {
                        "description": "Track not found",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/tracks": {
            "get": {
                "description": "Returns all track summaries sorted for browsing.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "core"
                ],
                "summary": "List track summaries",
                "responses": {
                    "200": {
                        "description": "Track list payload",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/tracks/bounds": {
            "get": {
                "description": "Returns a combined min/max lat/lon bounding box for the provided track IDs.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "web"
                ],
                "summary": "Get combined bounds for tracks",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Comma-separated track IDs",
                        "name": "trackIDs",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Bounds payload",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "404": {
                        "description": "No valid tracks found",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/api/tracks/index/{index}": {
            "get": {
                "description": "Resolves a one-based track index to a track ID, then returns track marker JSON.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "core"
                ],
                "summary": "Get track marker data by index",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "One-based track index",
                        "name": "index",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Track marker payload",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid index",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "404": {
                        "description": "Track not found",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/tracks/months/{year}/{month}": {
            "get": {
                "description": "Returns track summaries for tracks that contain measurements in a given calendar month.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "core"
                ],
                "summary": "List tracks by month",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Year",
                        "name": "year",
                        "in": "path",
                        "required": true
                    },
                    {
                        "type": "integer",
                        "description": "Month (1-12)",
                        "name": "month",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Track list payload",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid year or month",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/tracks/years/{year}": {
            "get": {
                "description": "Returns track summaries for tracks that contain measurements in a given year.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "core"
                ],
                "summary": "List tracks by year",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Year",
                        "name": "year",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Track list payload",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid year",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/api/update-coordinates": {
            "post": {
                "description": "Admin-only endpoint that updates all marker coordinates for a track.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "admin"
                ],
                "summary": "Update coordinates for a track",
                "parameters": [
                    {
                        "description": "trackID, lat, lon",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "type": "object"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Update result",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/api/user/change-password": {
            "post": {
                "description": "Changes password for the authenticated user after validating current password.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "auth"
                ],
                "summary": "Change current user password",
                "parameters": [
                    {
                        "description": "Change-password request",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "type": "object"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Password changed",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid request",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "401": {
                        "description": "Unauthorized or wrong password",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/api/user/profile": {
            "get": {
                "description": "Returns profile details for the authenticated user.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "auth"
                ],
                "summary": "Get current user profile",
                "responses": {
                    "200": {
                        "description": "User profile",
                        "schema": {
                            "$ref": "#/definitions/auth.User"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/api/user/uploads": {
            "get": {
                "description": "Returns paginated uploads for the authenticated user.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "auth"
                ],
                "summary": "List current user uploads",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Page size",
                        "name": "limit",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "Offset",
                        "name": "offset",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Upload rows",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/area": {
            "get": {
                "description": "Returns historical bGeigie measurements inside the specified geographic rectangle. Falls back to Safecast REST API if no database is configured.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "historical"
                ],
                "summary": "Find radiation measurements within a bounding box",
                "parameters": [
                    {
                        "type": "number",
                        "description": "Southern boundary latitude (-90 to 90)",
                        "name": "min_lat",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Northern boundary latitude (-90 to 90)",
                        "name": "max_lat",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Western boundary longitude (-180 to 180)",
                        "name": "min_lon",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Eastern boundary longitude (-180 to 180)",
                        "name": "max_lon",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "integer",
                        "default": 100,
                        "description": "Maximum number of results (1 to 10000)",
                        "name": "limit",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Measurements with count, bbox, and source",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid or missing parameters",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/device/{id}/history": {
            "get": {
                "description": "Returns time-series radiation data from a bGeigie mobile device or fixed sensor. Queries both the markers table (bGeigie imports) and realtime_measurements table (fixed sensors).",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "historical"
                ],
                "summary": "Get historical measurements from a device",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Device identifier",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "type": "integer",
                        "default": 30,
                        "description": "Days of history to retrieve (1 to 365)",
                        "name": "days",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "default": 200,
                        "description": "Maximum number of results (1 to 10000)",
                        "name": "limit",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Device measurements with period metadata",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid parameters",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/extreme": {
            "get": {
                "description": "Find the highest or lowest radiation readings in the database with full location details. Supports excluding anomalous sources.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "analytics"
                ],
                "summary": "Find extreme radiation readings",
                "parameters": [
                    {
                        "type": "string",
                        "default": "highest",
                        "description": "Direction: 'highest' or 'lowest'",
                        "name": "direction",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "default": 10,
                        "description": "Number of results (1-100)",
                        "name": "limit",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "default": -90,
                        "description": "Southern boundary for geographic filter",
                        "name": "min_lat",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "default": 90,
                        "description": "Northern boundary for geographic filter",
                        "name": "max_lat",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "default": -180,
                        "description": "Western boundary for geographic filter",
                        "name": "min_lon",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "default": 180,
                        "description": "Eastern boundary for geographic filter",
                        "name": "max_lon",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Comma-separated device IDs to exclude (e.g., 'bGeigie-2113,bGeigie-456')",
                        "name": "exclude_devices",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "JSON array of bounding boxes to exclude (e.g., '[{\\",
                        "name": "exclude_areas",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Extreme readings with location details",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid parameters",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/feedback": {
            "post": {
                "description": "Records a thumbs-up (+1) or thumbs-down (-1) vote for a specific AI chat response. Used to reinforce the semantic Q\u0026A cache: highly-rated answers are surfaced to future similar queries.",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "analytics"
                ],
                "summary": "Submit chat response feedback",
                "parameters": [
                    {
                        "description": "JSON payload: {chat_id: integer, score: 1|-1}",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "type": "object"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "ok: true",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "boolean"
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid request — chat_id required",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "405": {
                        "description": "Method not allowed",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "500": {
                        "description": "Failed to record feedback",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/get_markers": {
            "get": {
                "description": "Returns filtered markers for map bounds and optional track/speed/time filters.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "map"
                ],
                "summary": "Get markers for viewport",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Requested map zoom",
                        "name": "zoom",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "description": "Minimum latitude",
                        "name": "minLat",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Minimum longitude",
                        "name": "minLon",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Maximum latitude",
                        "name": "maxLat",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Maximum longitude",
                        "name": "maxLon",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "Single track ID filter",
                        "name": "trackID",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Comma-separated track IDs filter",
                        "name": "trackIDs",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Comma-separated speed categories",
                        "name": "speeds",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "Start unix timestamp (seconds)",
                        "name": "dateFrom",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "End unix timestamp (seconds)",
                        "name": "dateTo",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Markers",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "additionalProperties": true
                            }
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/gpt/area": {
            "get": {
                "description": "Returns compact historical readings for a bounding box, capped to 5 results for GPT usage.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "historical"
                ],
                "summary": "Find area readings (GPT compact)",
                "parameters": [
                    {
                        "type": "number",
                        "description": "Southern latitude boundary",
                        "name": "min_lat",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Northern latitude boundary",
                        "name": "max_lat",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Western longitude boundary",
                        "name": "min_lon",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Eastern longitude boundary",
                        "name": "max_lon",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Compact reading list",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid parameters",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "405": {
                        "description": "Method not allowed",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/gpt/radiation": {
            "get": {
                "description": "Returns compact fields optimized for LLM Actions. Results are capped to 5 and include source metadata.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "historical"
                ],
                "summary": "Find nearby radiation readings (GPT compact)",
                "parameters": [
                    {
                        "type": "number",
                        "description": "Latitude in decimal degrees (-90 to 90)",
                        "name": "lat",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Longitude in decimal degrees (-180 to 180)",
                        "name": "lon",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Search radius in meters",
                        "name": "radius_m",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Compact reading list",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid parameters",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "405": {
                        "description": "Method not allowed",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/gpt/stats": {
            "get": {
                "description": "Proxies the aggregate statistics endpoint for GPT Actions.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "reference"
                ],
                "summary": "Get aggregate statistics (GPT compact)",
                "responses": {
                    "200": {
                        "description": "Aggregate statistics",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "405": {
                        "description": "Method not allowed",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/info/{topic}": {
            "get": {
                "description": "Returns static educational reference content about radiation units, safety levels, detector types, background levels, and isotopes.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "reference"
                ],
                "summary": "Get radiation reference information",
                "parameters": [
                    {
                        "enum": [
                            "units",
                            "dose_rates",
                            "safety_levels",
                            "detectors",
                            "background_levels",
                            "isotopes"
                        ],
                        "type": "string",
                        "description": "Topic to retrieve",
                        "name": "topic",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Reference content for the requested topic",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid or missing topic",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/licenses/{code}": {
            "get": {
                "description": "Returns embedded license content for supported license codes.",
                "tags": [
                    "web"
                ],
                "summary": "Download project license text",
                "parameters": [
                    {
                        "type": "string",
                        "description": "License code: mit or cc0",
                        "name": "code",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "License text",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "404": {
                        "description": "License not found",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "405": {
                        "description": "Method not allowed",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/qrpng": {
            "get": {
                "description": "Returns a QR image for query parameter `u`, referer, or current URL.",
                "produces": [
                    "image/png"
                ],
                "tags": [
                    "web"
                ],
                "summary": "Generate QR PNG",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Target URL to encode",
                        "name": "u",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "QR PNG",
                        "schema": {
                            "type": "file"
                        }
                    },
                    "500": {
                        "description": "QR generation failed",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/radiation": {
            "get": {
                "description": "Returns historical bGeigie measurements within a radius of the given coordinates, sorted by most recent. Uses PostGIS spatial index for fast queries. Falls back to Safecast REST API if no database is configured.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "historical"
                ],
                "summary": "Find radiation measurements near a location",
                "parameters": [
                    {
                        "type": "number",
                        "description": "Latitude in decimal degrees (-90 to 90)",
                        "name": "lat",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Longitude in decimal degrees (-180 to 180)",
                        "name": "lon",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "default": 1500,
                        "description": "Search radius in meters (25 to 50000)",
                        "name": "radius_m",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "default": 25,
                        "description": "Maximum number of results (1 to 10000)",
                        "name": "limit",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Radiation measurements with count, source, and query metadata",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid parameters",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/realtime_history": {
            "get": {
                "description": "Returns aggregated realtime history and summary ranges for a device.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "map"
                ],
                "summary": "Get realtime device history",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Realtime device ID",
                        "name": "device",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Realtime history payload",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Missing device",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "404": {
                        "description": "Realtime feature disabled",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/s/{code}": {
            "get": {
                "description": "Looks up a short code and redirects to its stored target URL.",
                "tags": [
                    "web"
                ],
                "summary": "Resolve short URL code",
                "responses": {
                    "302": {
                        "description": "Redirect",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "404": {
                        "description": "Code not found",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "502": {
                        "description": "Invalid redirect target",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/sensor/{id}/current": {
            "get": {
                "description": "Routes to current or history endpoint based on the path suffix. Use /current for the latest reading, /history for time-series data.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "realtime"
                ],
                "summary": "Get readings from a specific sensor",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Device identifier",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "Start date for history (YYYY-MM-DD) — required for /history",
                        "name": "start_date",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "End date for history (YYYY-MM-DD, default: today)",
                        "name": "end_date",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "default": 25,
                        "description": "Maximum number of results (1 to 1000)",
                        "name": "limit",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Sensor readings",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid parameters",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/sensor/{id}/history": {
            "get": {
                "description": "Routes to current or history endpoint based on the path suffix. Use /current for the latest reading, /history for time-series data.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "realtime"
                ],
                "summary": "Get readings from a specific sensor",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Device identifier",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "Start date for history (YYYY-MM-DD) — required for /history",
                        "name": "start_date",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "End date for history (YYYY-MM-DD, default: today)",
                        "name": "end_date",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "default": 25,
                        "description": "Maximum number of results (1 to 1000)",
                        "name": "limit",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Sensor readings",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid parameters",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/sensors": {
            "get": {
                "description": "Lists active fixed radiation sensors (Pointcast, Solarcast, bGeigieZen, etc.) with their location, type, and last reading timestamp. Requires database connection.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "realtime"
                ],
                "summary": "Discover active fixed sensors",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Filter by sensor type (e.g. Pointcast, Solarcast, bGeigieZen)",
                        "name": "type",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "default": -90,
                        "description": "Southern boundary latitude",
                        "name": "min_lat",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "default": 90,
                        "description": "Northern boundary latitude",
                        "name": "max_lat",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "default": -180,
                        "description": "Western boundary longitude",
                        "name": "min_lon",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "default": 180,
                        "description": "Eastern boundary longitude",
                        "name": "max_lon",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "default": 50,
                        "description": "Maximum number of sensors (1 to 1000)",
                        "name": "limit",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Sensor list with locations and last reading times",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid parameters",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/sensors/export": {
            "get": {
                "description": "Downloads all active fixed sensors matching the given filters in CSV, JSON, or Excel format. No row limit — returns up to 10 000 devices.",
                "produces": [
                    "text/csv",
                    "application/json",
                    "application/vnd.ms-excel"
                ],
                "tags": [
                    "realtime"
                ],
                "summary": "Export all active sensors",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Output format: csv (default), json, xlsx",
                        "name": "format",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Filter by sensor type",
                        "name": "type",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "default": -90,
                        "description": "Southern boundary",
                        "name": "min_lat",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "default": 90,
                        "description": "Northern boundary",
                        "name": "max_lat",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "default": -180,
                        "description": "Western boundary",
                        "name": "min_lon",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "default": 180,
                        "description": "Eastern boundary",
                        "name": "max_lon",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Sensor data file",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "400": {
                        "description": "Invalid parameters",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/spectra": {
            "get": {
                "description": "Returns spectroscopy metadata (filename, device model, energy range, location) without channel data. Use GET /api/spectrum/{marker_id} to fetch full channel data. Requires database connection.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "spectroscopy"
                ],
                "summary": "Browse gamma spectroscopy records",
                "parameters": [
                    {
                        "type": "number",
                        "description": "Southern boundary latitude (requires all 4 bbox params)",
                        "name": "min_lat",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "description": "Northern boundary latitude (requires all 4 bbox params)",
                        "name": "max_lat",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "description": "Western boundary longitude (requires all 4 bbox params)",
                        "name": "min_lon",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "description": "Eastern boundary longitude (requires all 4 bbox params)",
                        "name": "max_lon",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Filter by file format (e.g. spe, csv)",
                        "name": "source_format",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Filter by detector model name (partial match)",
                        "name": "device_model",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Filter by track identifier",
                        "name": "track_id",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "default": 50,
                        "description": "Maximum number of results (1 to 500)",
                        "name": "limit",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Spectroscopy records with metadata",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid parameters",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/spectrum/{marker_id}": {
            "get": {
                "description": "Returns complete gamma spectroscopy data including all channel counts for the specified measurement point. Use GET /api/spectra to find marker IDs.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "spectroscopy"
                ],
                "summary": "Get full spectroscopy channel data",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Marker/measurement identifier",
                        "name": "marker_id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Full spectroscopy channel data",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid marker_id",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "503": {
                        "description": "Database unavailable",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/stats": {
            "get": {
                "description": "Returns aggregate radiation dose-rate statistics from the Safecast database grouped by time interval. Powered by DuckDB + PostgreSQL.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "reference"
                ],
                "summary": "Get aggregate radiation statistics",
                "parameters": [
                    {
                        "enum": [
                            "year",
                            "month",
                            "overall"
                        ],
                        "type": "string",
                        "default": "year",
                        "description": "Aggregation interval: year, month, or overall",
                        "name": "interval",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Statistics data with interval and source metadata",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid interval value",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "503": {
                        "description": "Analytics engine unavailable",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/stream_markers": {
            "get": {
                "description": "Streams map markers as SSE by default, or MessagePack when requested via query/header.",
                "produces": [
                    "text/event-stream"
                ],
                "tags": [
                    "map"
                ],
                "summary": "Stream markers for viewport",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Requested map zoom",
                        "name": "zoom",
                        "in": "query"
                    },
                    {
                        "type": "number",
                        "description": "Minimum latitude",
                        "name": "minLat",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Minimum longitude",
                        "name": "minLon",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Maximum latitude",
                        "name": "maxLat",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "number",
                        "description": "Maximum longitude",
                        "name": "maxLon",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "Single track ID filter",
                        "name": "trackID",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Comma-separated track IDs filter",
                        "name": "trackIDs",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Set to msgpack for binary stream",
                        "name": "format",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Streaming response",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "500": {
                        "description": "Streaming unsupported",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/track/{id}": {
            "get": {
                "description": "Retrieves radiation measurements recorded during a specific bGeigie drive. The path ID can be used directly from a simplemap track URL (for example /trackid/{id}). This REST endpoint returns measurement rows; statistical-only summaries (min/max/percentiles/top peaks) are available via the MCP get_track tool with stats_only=true.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "historical"
                ],
                "summary": "Get all measurements from a specific track",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Track identifier (e.g. 8eh5m1)",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "type": "integer",
                        "description": "Start marker ID for filtering",
                        "name": "from",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "End marker ID for filtering",
                        "name": "to",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "default": 200,
                        "description": "Maximum number of results (1 to 10000)",
                        "name": "limit",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Measurements for the track",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid parameters",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/track/{id}/insights": {
            "get": {
                "description": "Returns positively-rated Q\u0026A pairs and curated location notes that are semantically or spatially relevant to the given bGeigie track. Requires DuckDB analytics and OpenAI embeddings. Returns empty arrays when analytics are unavailable.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "historical"
                ],
                "summary": "Get cached Q\u0026A insights for a track",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Track identifier (e.g. 8eh5m1)",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Insights and location notes for the track",
                        "schema": {
                            "$ref": "#/definitions/main.trackInsightsResponse"
                        }
                    },
                    "400": {
                        "description": "Track id required",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "404": {
                        "description": "Track not found",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "503": {
                        "description": "Database not available",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/tracks": {
            "get": {
                "description": "Lists bGeigie Import tracks (bulk radiation measurement drives). Each track represents measurements from a single bGeigie session. Can filter by year, month, and detector/device name.",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "historical"
                ],
                "summary": "Browse bGeigie measurement tracks",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "Filter by year (2000–2100)",
                        "name": "year",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "Filter by month (1–12, requires year)",
                        "name": "month",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "Filter by detector/device name (e.g., 'bGeigieZen', 'bGeigie', 'Pointcast'). Partial match supported.",
                        "name": "detector",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "default": 50,
                        "description": "Maximum number of results (1 to 50000)",
                        "name": "limit",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Track list with count and filter metadata",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid parameters",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "/tracks/{ids}": {
            "get": {
                "description": "Serves the HTML map page with multiple track IDs from a comma-separated path segment.",
                "produces": [
                    "text/html"
                ],
                "tags": [
                    "web"
                ],
                "summary": "Render map page for multiple tracks",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Comma-separated track IDs",
                        "name": "ids",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "HTML page",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "400": {
                        "description": "Track IDs missing",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/upload": {
            "post": {
                "description": "Accepts one or more files in multipart form field `files[]` and returns a track ID for async progress polling.",
                "consumes": [
                    "multipart/form-data"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "map"
                ],
                "summary": "Upload radiation files",
                "responses": {
                    "200": {
                        "description": "Upload accepted",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "400": {
                        "description": "Invalid upload",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "500": {
                        "description": "Server error",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "/upload/progress": {
            "get": {
                "description": "Streams upload progress events for a previously submitted upload track ID.",
                "produces": [
                    "text/event-stream"
                ],
                "tags": [
                    "map"
                ],
                "summary": "Stream upload progress",
                "parameters": [
                    {
                        "type": "string",
                        "description": "Upload tracking ID returned by /upload",
                        "name": "trackid",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "SSE stream",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "400": {
                        "description": "Missing trackid",
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        }
    },
    "definitions": {
        "auth.AdminCreateUserRequest": {
            "type": "object",
            "properties": {
                "email": {
                    "type": "string",
                    "example": "user@example.com"
                },
                "password": {
                    "type": "string",
                    "example": "StrongPass123!"
                },
                "requires_password_setup": {
                    "type": "boolean",
                    "example": false
                },
                "send_welcome_email": {
                    "type": "boolean",
                    "example": true
                },
                "username": {
                    "type": "string",
                    "example": "jane_doe"
                }
            }
        },
        "auth.AdminUpdateUserRequest": {
            "type": "object",
            "properties": {
                "email": {
                    "type": "string",
                    "example": "updated@example.com"
                },
                "email_verified": {
                    "type": "boolean",
                    "example": true
                },
                "external_id": {
                    "type": "string",
                    "example": "auth0|abc123"
                },
                "is_active": {
                    "type": "boolean",
                    "example": true
                },
                "is_admin": {
                    "type": "boolean",
                    "example": false
                },
                "password": {
                    "type": "string",
                    "example": "NewStrongPass123!"
                },
                "username": {
                    "type": "string",
                    "example": "updated_name"
                }
            }
        },
        "auth.User": {
            "type": "object",
            "properties": {
                "api_key": {
                    "type": "string"
                },
                "created_at": {
                    "type": "integer"
                },
                "email": {
                    "type": "string"
                },
                "email_verified": {
                    "type": "boolean"
                },
                "external_id": {
                    "type": "string"
                },
                "external_source": {
                    "type": "string"
                },
                "id": {
                    "type": "integer"
                },
                "is_active": {
                    "type": "boolean"
                },
                "is_admin": {
                    "type": "boolean"
                },
                "last_login_at": {
                    "type": "integer"
                },
                "requires_password_setup": {
                    "type": "boolean"
                },
                "updated_at": {
                    "type": "integer"
                },
                "username": {
                    "type": "string"
                }
            }
        },
        "main.trackInsight": {
            "type": "object",
            "properties": {
                "answer": {
                    "type": "string"
                },
                "chat_id": {
                    "type": "integer"
                },
                "feedback_score": {
                    "type": "integer"
                },
                "question": {
                    "type": "string"
                },
                "similarity_score": {
                    "type": "number"
                }
            }
        },
        "main.trackInsightsResponse": {
            "type": "object",
            "properties": {
                "insights": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/main.trackInsight"
                    }
                },
                "location_notes": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/main.trackLocationNote"
                    }
                },
                "track_id": {
                    "type": "string"
                }
            }
        },
        "main.trackLocationNote": {
            "type": "object",
            "properties": {
                "feedback_score": {
                    "type": "integer"
                },
                "lat": {
                    "type": "number"
                },
                "lon": {
                    "type": "number"
                },
                "note": {
                    "type": "string"
                },
                "source_chat_id": {
                    "type": "integer"
                }
            }
        }
    },
    "tags": [
        {
            "description": "Core /api dataset and track endpoints",
            "name": "core"
        },
        {
            "description": "Web utility endpoints used by the map UI",
            "name": "web"
        },
        {
            "description": "Authentication and user account endpoints",
            "name": "auth"
        },
        {
            "description": "Admin-only endpoints",
            "name": "admin"
        },
        {
            "description": "Map data and streaming endpoints",
            "name": "map"
        }
    ]
}