{
    "openapi": "3.0.0",
    "info": {
        "title": "HamQTH API",
        "description": "Callbook, DXCC, DX cluster, log and solar data API of HamQTH. Answers are JSON, or XML of the same structure\nwith `format=xml`; errors are problem details JSON. Endpoints with a lock need a token: call\n`POST /api/v2/login`, then **Authorize** with the token. The guide with examples is on\nhttps://www.hamqth.com/developers.\n",
        "version": "2"
    },
    "paths": {
        "/api/v2/callbook/{callsign}/activity": {
            "get": {
                "tags": [
                    "Callbook"
                ],
                "summary": "Recent activity of a callsign",
                "operationId": "get_api_v2_activity",
                "parameters": [
                    {
                        "name": "callsign",
                        "in": "path",
                        "description": "e.g. OK2CQR",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "pattern": "[A-Za-z0-9]+(/[A-Za-z0-9]+)*"
                        }
                    },
                    {
                        "name": "format",
                        "in": "query",
                        "description": "json (default) or xml",
                        "required": false,
                        "schema": {
                            "description": "json (default) or xml",
                            "type": "string",
                            "default": "json",
                            "enum": [
                                "json",
                                "xml"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Spots and QSOs",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Activity"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No token, or an expired one",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Callsign not found",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "Bearer": []
                    }
                ]
            }
        },
        "/api/v2/callbook/{callsign}": {
            "get": {
                "tags": [
                    "Callbook"
                ],
                "summary": "Callbook lookup",
                "description": "A portable callsign finds the home record when it has none of its own. Counted as an API lookup.",
                "operationId": "get_api_v2_callbook",
                "parameters": [
                    {
                        "name": "callsign",
                        "in": "path",
                        "description": "e.g. OK2CQR; portable forms like OK2CQR/P work too",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "pattern": "[A-Za-z0-9]+(/[A-Za-z0-9]+)*"
                        }
                    },
                    {
                        "name": "include",
                        "in": "query",
                        "description": "bio: add the biography as plain text",
                        "required": false,
                        "schema": {
                            "description": "bio: add the biography as plain text",
                            "type": "string",
                            "nullable": true,
                            "default": null,
                            "enum": [
                                "bio"
                            ]
                        }
                    },
                    {
                        "name": "app",
                        "in": "query",
                        "description": "name of your program, for the lookup statistics",
                        "required": false,
                        "schema": {
                            "title": "the calling program, for the lookup statistics (v1: prg)",
                            "description": "name of your program, for the lookup statistics",
                            "type": "string",
                            "example": "swagger-test",
                            "nullable": true,
                            "default": null,
                            "maxLength": 64
                        },
                        "example": "swagger-test"
                    },
                    {
                        "name": "format",
                        "in": "query",
                        "description": "json (default) or xml",
                        "required": false,
                        "schema": {
                            "description": "json (default) or xml",
                            "type": "string",
                            "default": "json",
                            "enum": [
                                "json",
                                "xml"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The record",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CallbookRecord"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No token, or an expired one",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Callsign not found",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Invalid parameter",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "Bearer": []
                    }
                ]
            }
        },
        "/api/v2/dxcc": {
            "get": {
                "tags": [
                    "DXCC"
                ],
                "summary": "DXCC of a callsign, or a DXCC entity",
                "description": "Send either callsign (with an optional QSO date) or entity.",
                "operationId": "get_api_v2_dxcc",
                "parameters": [
                    {
                        "name": "callsign",
                        "in": "query",
                        "description": "the callsign (or send entity)",
                        "required": false,
                        "schema": {
                            "description": "the callsign (or send entity)",
                            "type": "string",
                            "pattern": "[\\x21-\\x7e]{1,40}",
                            "example": "U3AP",
                            "nullable": true,
                            "default": null
                        },
                        "example": "U3AP"
                    },
                    {
                        "name": "entity",
                        "in": "query",
                        "description": "instead of a callsign: a DXCC entity by its number",
                        "required": false,
                        "schema": {
                            "description": "instead of a callsign: a DXCC entity by its number",
                            "type": "integer",
                            "example": 503,
                            "nullable": true,
                            "default": null,
                            "maximum": 999,
                            "minimum": 1
                        },
                        "example": 503
                    },
                    {
                        "name": "date",
                        "in": "query",
                        "description": "QSO date YYYY-MM-DD, default today: old prefixes and deleted entities resolve as on that day",
                        "required": false,
                        "schema": {
                            "description": "QSO date YYYY-MM-DD, default today: old prefixes and deleted entities resolve as on that day",
                            "type": "string",
                            "example": "1990-01-01",
                            "nullable": true,
                            "default": null
                        },
                        "example": "1990-01-01"
                    },
                    {
                        "name": "format",
                        "in": "query",
                        "description": "json (default) or xml",
                        "required": false,
                        "schema": {
                            "description": "json (default) or xml",
                            "type": "string",
                            "default": "json",
                            "enum": [
                                "json",
                                "xml"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "With callsign: the callsign's DXCC. With entity: the DxccEntity alone.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "$ref": "#/components/schemas/DxccResult"
                                        },
                                        {
                                            "$ref": "#/components/schemas/DxccEntity"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No DXCC entity for the callsign, or no such entity",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Invalid parameter",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "The DXCC service is down for a moment",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/api/v2/log/uploads": {
            "post": {
                "tags": [
                    "Log"
                ],
                "summary": "Upload a whole log",
                "description": "Replaces the log on HamQTH. The import runs in the background: ask statusUrl for its result.",
                "operationId": "post_api_v2_log_upload",
                "parameters": [
                    {
                        "name": "format",
                        "in": "query",
                        "description": "json (default) or xml",
                        "required": false,
                        "schema": {
                            "description": "json (default) or xml",
                            "type": "string",
                            "default": "json",
                            "enum": [
                                "json",
                                "xml"
                            ]
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "multipart/form-data": {
                            "schema": {
                                "required": [
                                    "file"
                                ],
                                "properties": {
                                    "file": {
                                        "description": "ADIF (.adi, .adif), or ADIF compressed in zip, gz, tar.gz, tar.bz2, rar, 7z; at most 20 MB",
                                        "type": "string",
                                        "format": "binary"
                                    },
                                    "callsign": {
                                        "description": "the log of another callsign you manage; your own when left out",
                                        "type": "string"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "Queued for import (statusUrl also in the Location header)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/UploadAccepted"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No token, or an expired one",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Not a callsign you manage",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "No file, or a file that cannot be imported (format, size)",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "The upload could not be stored for a moment",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "Bearer": []
                    }
                ]
            }
        },
        "/api/v2/log/uploads/{id}": {
            "get": {
                "tags": [
                    "Log"
                ],
                "summary": "Result of a log upload",
                "description": "Ask again until status is done or failed.",
                "operationId": "get_api_v2_log_upload_status",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "pattern": "\\d+"
                        }
                    },
                    {
                        "name": "format",
                        "in": "query",
                        "description": "json (default) or xml",
                        "required": false,
                        "schema": {
                            "description": "json (default) or xml",
                            "type": "string",
                            "default": "json",
                            "enum": [
                                "json",
                                "xml"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The upload and its import",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/UploadStatus"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No token, or an expired one",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such upload of yours",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "Bearer": []
                    }
                ]
            }
        },
        "/api/v2/login": {
            "post": {
                "tags": [
                    "Login"
                ],
                "summary": "Log in for a token",
                "operationId": "post_api_v2_login",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/LoginRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The token",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LoginToken"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Wrong callsign or password",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "callsign or password missing",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Too many wrong passwords; wait Retry-After seconds",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/api/v2/log/qso": {
            "put": {
                "tags": [
                    "Log"
                ],
                "summary": "Change a QSO in the log",
                "description": "\"original\" identifies the logged QSO, \"qso\" is the whole new QSO.",
                "operationId": "put_api_v2_qso_update",
                "parameters": [
                    {
                        "name": "format",
                        "in": "query",
                        "description": "json (default) or xml",
                        "required": false,
                        "schema": {
                            "description": "json (default) or xml",
                            "type": "string",
                            "default": "json",
                            "enum": [
                                "json",
                                "xml"
                            ]
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/QsoRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The QSO as stored",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoredQso"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No token, or an expired one",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Not a callsign you manage",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "The original QSO is not in the log",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The changed QSO is another logged QSO",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Invalid field",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "The DXCC service is down for a moment",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "Bearer": []
                    }
                ]
            },
            "post": {
                "tags": [
                    "Log"
                ],
                "summary": "Add a QSO to the log",
                "description": "call, qso_date, time_on and band or freq are required. Without dxcc it is resolved from the callsign on the QSO date.",
                "operationId": "post_api_v2_qso_insert",
                "parameters": [
                    {
                        "name": "format",
                        "in": "query",
                        "description": "json (default) or xml",
                        "required": false,
                        "schema": {
                            "description": "json (default) or xml",
                            "type": "string",
                            "default": "json",
                            "enum": [
                                "json",
                                "xml"
                            ]
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/QsoRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The QSO as stored",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/StoredQso"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No token, or an expired one",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Not a callsign you manage",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The QSO is in the log already",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Invalid field",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "The DXCC service is down for a moment",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "Bearer": []
                    }
                ]
            },
            "delete": {
                "tags": [
                    "Log"
                ],
                "summary": "Delete a QSO from the log",
                "description": "The QSO by its ADIF fields in the query string. USB / LSB QSOs are stored as SSB.",
                "operationId": "delete_api_v2_qso_delete",
                "parameters": [
                    {
                        "name": "call",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "example": "DL1ABC"
                        },
                        "example": "DL1ABC"
                    },
                    {
                        "name": "qso_date",
                        "in": "query",
                        "description": "YYYYMMDD or YYYY-MM-DD",
                        "required": false,
                        "schema": {
                            "title": "YYYYMMDD or YYYY-MM-DD",
                            "description": "YYYYMMDD or YYYY-MM-DD",
                            "type": "string",
                            "example": "20240105"
                        },
                        "example": "20240105"
                    },
                    {
                        "name": "time_on",
                        "in": "query",
                        "description": "HHMM or HH:MM, UTC",
                        "required": false,
                        "schema": {
                            "title": "HHMM or HH:MM, UTC",
                            "description": "HHMM or HH:MM, UTC",
                            "type": "string",
                            "example": "1200"
                        },
                        "example": "1200"
                    },
                    {
                        "name": "band",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "example": "20M"
                        },
                        "example": "20M"
                    },
                    {
                        "name": "mode",
                        "in": "query",
                        "description": "as logged; USB / LSB are stored as SSB",
                        "required": false,
                        "schema": {
                            "description": "as logged; USB / LSB are stored as SSB",
                            "type": "string",
                            "example": "CW"
                        },
                        "example": "CW"
                    },
                    {
                        "name": "callsign",
                        "in": "query",
                        "description": "the log of another callsign you manage; your own when left out",
                        "required": false,
                        "schema": {
                            "title": "the log of another callsign you manage; your own when left out",
                            "description": "the log of another callsign you manage; your own when left out",
                            "type": "string",
                            "nullable": true,
                            "default": null,
                            "maxLength": 30
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "Deleted"
                    },
                    "401": {
                        "description": "No token, or an expired one",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Not a callsign you manage",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "The QSO is not in the log",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Invalid or missing field",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "Bearer": []
                    }
                ]
            }
        },
        "/api/v2/rbn": {
            "get": {
                "tags": [
                    "DX cluster"
                ],
                "summary": "Reverse Beacon Network spots",
                "description": "One row per heard signal, with the filters of the RBN tab. Lists are comma separated; left out = all. In XML a skimmer is <skimmer call=\"\u2026\" snr=\"\u2026\"/>.",
                "operationId": "get_api_v2_rbn",
                "parameters": [
                    {
                        "name": "bands",
                        "in": "query",
                        "description": "comma separated: 160M, 80M, 60M, 40M, 30M, 20M, 17M, 15M, 12M, 10M, 6M, 2M; all when left out",
                        "required": false,
                        "schema": {
                            "description": "comma separated: 160M, 80M, 60M, 40M, 30M, 20M, 17M, 15M, 12M, 10M, 6M, 2M; all when left out",
                            "type": "string",
                            "example": "20M,40M",
                            "nullable": true,
                            "default": null
                        },
                        "example": "20M,40M"
                    },
                    {
                        "name": "modes",
                        "in": "query",
                        "description": "comma separated: CW, RTTY, PSK31, PSK63; all when left out",
                        "required": false,
                        "schema": {
                            "description": "comma separated: CW, RTTY, PSK31, PSK63; all when left out",
                            "type": "string",
                            "example": "CW",
                            "nullable": true,
                            "default": null
                        },
                        "example": "CW"
                    },
                    {
                        "name": "cont",
                        "in": "query",
                        "description": "continents of the spotted station, comma separated: AF, AN, AS, EU, NA, SA, OC; all when left out",
                        "required": false,
                        "schema": {
                            "description": "continents of the spotted station, comma separated: AF, AN, AS, EU, NA, SA, OC; all when left out",
                            "type": "string",
                            "nullable": true,
                            "default": null
                        }
                    },
                    {
                        "name": "fromCont",
                        "in": "query",
                        "description": "continents of the skimmer, same values",
                        "required": false,
                        "schema": {
                            "description": "continents of the skimmer, same values",
                            "type": "string",
                            "example": "EU",
                            "nullable": true,
                            "default": null
                        },
                        "example": "EU"
                    },
                    {
                        "name": "waz",
                        "in": "query",
                        "description": "CQ zones of the spotted station, comma separated; * = all",
                        "required": false,
                        "schema": {
                            "description": "CQ zones of the spotted station, comma separated; * = all",
                            "type": "string",
                            "pattern": ".*(^\\s*(\\*|\\d{1,2}(\\s*,\\s*\\d{1,2})*)\\s*$).*",
                            "default": "*"
                        }
                    },
                    {
                        "name": "itu",
                        "in": "query",
                        "description": "ITU zones of the spotted station, comma separated; * = all",
                        "required": false,
                        "schema": {
                            "description": "ITU zones of the spotted station, comma separated; * = all",
                            "type": "string",
                            "pattern": ".*(^\\s*(\\*|\\d{1,2}(\\s*,\\s*\\d{1,2})*)\\s*$).*",
                            "default": "*"
                        }
                    },
                    {
                        "name": "calls",
                        "in": "query",
                        "description": "only these callsigns (at most 30), comma separated",
                        "required": false,
                        "schema": {
                            "description": "only these callsigns (at most 30), comma separated",
                            "type": "string",
                            "example": "OK2CQR,OL7M",
                            "nullable": true,
                            "default": null
                        },
                        "example": "OK2CQR,OL7M"
                    },
                    {
                        "name": "maxAge",
                        "in": "query",
                        "description": "only reports from the last N seconds",
                        "required": false,
                        "schema": {
                            "description": "only reports from the last N seconds",
                            "type": "integer",
                            "default": 1200,
                            "maximum": 3600,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "sort",
                        "in": "query",
                        "description": "age (newest first), freq or call",
                        "required": false,
                        "schema": {
                            "description": "age (newest first), freq or call",
                            "type": "string",
                            "default": "age",
                            "enum": [
                                "freq",
                                "call",
                                "age"
                            ]
                        }
                    },
                    {
                        "name": "include",
                        "in": "query",
                        "description": "locations: add the approximate position (4-character locator) of every spotted station and skimmer",
                        "required": false,
                        "schema": {
                            "description": "locations: add the approximate position (4-character locator) of every spotted station and skimmer",
                            "type": "string",
                            "nullable": true,
                            "default": null,
                            "enum": [
                                "locations"
                            ]
                        }
                    },
                    {
                        "name": "format",
                        "in": "query",
                        "description": "json (default) or xml",
                        "required": false,
                        "schema": {
                            "description": "json (default) or xml",
                            "type": "string",
                            "default": "json",
                            "enum": [
                                "json",
                                "xml"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The signals",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/RbnSpotList"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Invalid parameter",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/api/v2/solar": {
            "get": {
                "tags": [
                    "Solar"
                ],
                "summary": "Solar conditions",
                "description": "Solar flux, Boulder and Kiel A index, K index, sunspot number, aurora and the solar activity and geomagnetic field forecast from DK0WCY, refreshed every 5 minutes.",
                "operationId": "get_api_v2_solar",
                "parameters": [
                    {
                        "name": "format",
                        "in": "query",
                        "description": "json (default) or xml",
                        "required": false,
                        "schema": {
                            "description": "json (default) or xml",
                            "type": "string",
                            "default": "json",
                            "enum": [
                                "json",
                                "xml"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The latest values",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Solar"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Invalid parameter",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "No values read from DK0WCY yet",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/api/v2/spots": {
            "get": {
                "tags": [
                    "DX cluster"
                ],
                "summary": "DX cluster spots",
                "description": "Newest first, with the filters of the DX cluster tab. Lists are comma separated; left out = all.",
                "operationId": "get_api_v2_spots",
                "parameters": [
                    {
                        "name": "bands",
                        "in": "query",
                        "description": "comma separated: <160M, 160M, 80M, 60M, 40M, 30M, 20M, 17M, 15M, 12M, 10M, 6M, 4M, 2M, 1.25M, 70CM, 33CM+; all when left out",
                        "required": false,
                        "schema": {
                            "description": "comma separated: <160M, 160M, 80M, 60M, 40M, 30M, 20M, 17M, 15M, 12M, 10M, 6M, 4M, 2M, 1.25M, 70CM, 33CM+; all when left out",
                            "type": "string",
                            "example": "20M,40M",
                            "nullable": true,
                            "default": null
                        },
                        "example": "20M,40M"
                    },
                    {
                        "name": "modes",
                        "in": "query",
                        "description": "comma separated: CW, SSB, DIGI; all when left out. A spot of unknown mode passes any mode filter",
                        "required": false,
                        "schema": {
                            "description": "comma separated: CW, SSB, DIGI; all when left out. A spot of unknown mode passes any mode filter",
                            "type": "string",
                            "example": "CW",
                            "nullable": true,
                            "default": null
                        },
                        "example": "CW"
                    },
                    {
                        "name": "cont",
                        "in": "query",
                        "description": "continents of the spotted station, comma separated: AF, AN, AS, EU, NA, SA, OC; all when left out",
                        "required": false,
                        "schema": {
                            "description": "continents of the spotted station, comma separated: AF, AN, AS, EU, NA, SA, OC; all when left out",
                            "type": "string",
                            "example": "NA,SA",
                            "nullable": true,
                            "default": null
                        },
                        "example": "NA,SA"
                    },
                    {
                        "name": "fromCont",
                        "in": "query",
                        "description": "continents of the spotter, same values",
                        "required": false,
                        "schema": {
                            "description": "continents of the spotter, same values",
                            "type": "string",
                            "example": "EU",
                            "nullable": true,
                            "default": null
                        },
                        "example": "EU"
                    },
                    {
                        "name": "waz",
                        "in": "query",
                        "description": "CQ zones of the spotted station, comma separated; * = all",
                        "required": false,
                        "schema": {
                            "description": "CQ zones of the spotted station, comma separated; * = all",
                            "type": "string",
                            "pattern": ".*(^\\s*(\\*|\\d{1,2}(\\s*,\\s*\\d{1,2})*)\\s*$).*",
                            "example": "14,15",
                            "default": "*"
                        },
                        "example": "14,15"
                    },
                    {
                        "name": "itu",
                        "in": "query",
                        "description": "ITU zones of the spotted station, comma separated; * = all",
                        "required": false,
                        "schema": {
                            "description": "ITU zones of the spotted station, comma separated; * = all",
                            "type": "string",
                            "pattern": ".*(^\\s*(\\*|\\d{1,2}(\\s*,\\s*\\d{1,2})*)\\s*$).*",
                            "example": "27,28",
                            "default": "*"
                        },
                        "example": "27,28"
                    },
                    {
                        "name": "calls",
                        "in": "query",
                        "description": "only these callsigns (at most 30), comma separated; a callsign also matches its portable forms",
                        "required": false,
                        "schema": {
                            "description": "only these callsigns (at most 30), comma separated; a callsign also matches its portable forms",
                            "type": "string",
                            "example": "OK2CQR,OL7M",
                            "nullable": true,
                            "default": null
                        },
                        "example": "OK2CQR,OL7M"
                    },
                    {
                        "name": "lotw",
                        "in": "query",
                        "description": "only stations using LoTW",
                        "required": false,
                        "schema": {
                            "description": "only stations using LoTW",
                            "type": "boolean",
                            "default": false
                        }
                    },
                    {
                        "name": "eqsl",
                        "in": "query",
                        "description": "only stations using eQSL",
                        "required": false,
                        "schema": {
                            "description": "only stations using eQSL",
                            "type": "boolean",
                            "default": false
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "number of spots",
                        "required": false,
                        "schema": {
                            "description": "number of spots",
                            "type": "integer",
                            "default": 60,
                            "maximum": 200,
                            "minimum": 1
                        }
                    },
                    {
                        "name": "include",
                        "in": "query",
                        "description": "locations: add the approximate position (4-character locator) of every spotted station and spotter",
                        "required": false,
                        "schema": {
                            "description": "locations: add the approximate position (4-character locator) of every spotted station and spotter",
                            "type": "string",
                            "nullable": true,
                            "default": null,
                            "enum": [
                                "locations"
                            ]
                        }
                    },
                    {
                        "name": "format",
                        "in": "query",
                        "description": "json (default) or xml",
                        "required": false,
                        "schema": {
                            "description": "json (default) or xml",
                            "type": "string",
                            "default": "json",
                            "enum": [
                                "json",
                                "xml"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The spots",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/SpotList"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Invalid parameter",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/api/v2/verify": {
            "get": {
                "tags": [
                    "Log"
                ],
                "summary": "Is a QSO in a log uploaded to HamQTH?",
                "description": "Simple award verification: is a QSO with mycall in the log of hiscall?",
                "operationId": "get_api_v2_verify",
                "parameters": [
                    {
                        "name": "mycall",
                        "in": "query",
                        "description": "the callsign asking (the one in the log of hiscall)",
                        "required": false,
                        "schema": {
                            "description": "the callsign asking (the one in the log of hiscall)",
                            "type": "string",
                            "example": "J49C"
                        },
                        "example": "J49C"
                    },
                    {
                        "name": "hiscall",
                        "in": "query",
                        "description": "the station whose log is checked",
                        "required": false,
                        "schema": {
                            "description": "the station whose log is checked",
                            "type": "string",
                            "example": "OK2CQR"
                        },
                        "example": "OK2CQR"
                    },
                    {
                        "name": "date",
                        "in": "query",
                        "description": "QSO date YYYY-MM-DD",
                        "required": false,
                        "schema": {
                            "description": "QSO date YYYY-MM-DD",
                            "type": "string",
                            "example": "2013-06-20"
                        },
                        "example": "2013-06-20"
                    },
                    {
                        "name": "band",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "example": "12M"
                        },
                        "example": "12M"
                    },
                    {
                        "name": "time",
                        "in": "query",
                        "description": "QSO start HH:MM UTC, must match exactly",
                        "required": false,
                        "schema": {
                            "description": "QSO start HH:MM UTC, must match exactly",
                            "type": "string",
                            "pattern": ".*(^([01]\\d|2[0-3]):?[0-5]\\d$).*",
                            "example": "12:00",
                            "nullable": true,
                            "default": null
                        },
                        "example": "12:00"
                    },
                    {
                        "name": "mode",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "example": "CW",
                            "nullable": true,
                            "default": null,
                            "maxLength": 8
                        },
                        "example": "CW"
                    },
                    {
                        "name": "format",
                        "in": "query",
                        "description": "json (default) or xml",
                        "required": false,
                        "schema": {
                            "description": "json (default) or xml",
                            "type": "string",
                            "default": "json",
                            "enum": [
                                "json",
                                "xml"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The answer",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/VerifyResult"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Invalid or missing parameter",
                        "content": {
                            "application/problem+json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Problem"
                                }
                            }
                        }
                    }
                },
                "security": []
            }
        }
    },
    "components": {
        "schemas": {
            "Problem": {
                "description": "An error (RFC 9457). `violations` only for an invalid parameter (422).",
                "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                ],
                "properties": {
                    "type": {
                        "type": "string"
                    },
                    "title": {
                        "type": "string"
                    },
                    "status": {
                        "type": "integer"
                    },
                    "detail": {
                        "type": "string"
                    },
                    "violations": {
                        "type": "array",
                        "items": {
                            "properties": {
                                "propertyPath": {
                                    "type": "string"
                                },
                                "title": {
                                    "type": "string"
                                }
                            },
                            "type": "object"
                        }
                    }
                },
                "type": "object"
            },
            "FormatQuery": {
                "properties": {
                    "format": {
                        "description": "json (default) or xml",
                        "type": "string",
                        "default": "json",
                        "enum": [
                            "json",
                            "xml"
                        ]
                    }
                },
                "type": "object"
            },
            "CallbookQuery": {
                "properties": {
                    "include": {
                        "description": "bio: add the biography as plain text",
                        "type": "string",
                        "nullable": true,
                        "default": null,
                        "enum": [
                            "bio"
                        ]
                    },
                    "app": {
                        "title": "the calling program, for the lookup statistics (v1: prg)",
                        "description": "name of your program, for the lookup statistics",
                        "type": "string",
                        "example": "swagger-test",
                        "nullable": true,
                        "default": null,
                        "maxLength": 64
                    },
                    "format": {
                        "description": "json (default) or xml",
                        "type": "string",
                        "default": "json",
                        "enum": [
                            "json",
                            "xml"
                        ]
                    }
                },
                "type": "object"
            },
            "DxccQuery": {
                "properties": {
                    "callsign": {
                        "description": "the callsign (or send entity)",
                        "type": "string",
                        "pattern": "[\\x21-\\x7e]{1,40}",
                        "example": "U3AP",
                        "nullable": true,
                        "default": null
                    },
                    "entity": {
                        "description": "instead of a callsign: a DXCC entity by its number",
                        "type": "integer",
                        "example": 503,
                        "nullable": true,
                        "default": null,
                        "maximum": 999,
                        "minimum": 1
                    },
                    "date": {
                        "description": "QSO date YYYY-MM-DD, default today: old prefixes and deleted entities resolve as on that day",
                        "type": "string",
                        "example": "1990-01-01",
                        "nullable": true,
                        "default": null
                    },
                    "format": {
                        "description": "json (default) or xml",
                        "type": "string",
                        "default": "json",
                        "enum": [
                            "json",
                            "xml"
                        ]
                    }
                },
                "type": "object"
            },
            "LoginRequest": {
                "required": [
                    "callsign",
                    "password"
                ],
                "properties": {
                    "callsign": {
                        "description": "your HamQTH callsign",
                        "type": "string",
                        "example": "OK2CQR",
                        "maxLength": 30
                    },
                    "password": {
                        "type": "string",
                        "format": "password"
                    }
                },
                "type": "object"
            },
            "QsoRequest": {
                "properties": {
                    "callsign": {
                        "description": "the log of another callsign you manage; your own when left out",
                        "type": "string",
                        "nullable": true,
                        "default": null,
                        "maxLength": 30
                    },
                    "qso": {
                        "description": "ADIF fields, lower-case ADIF names, ADIF values",
                        "type": "object",
                        "example": {
                            "call": "DL1ABC",
                            "qso_date": "20240105",
                            "time_on": "1200",
                            "band": "20M",
                            "mode": "CW",
                            "freq": "14.025",
                            "rst_sent": "599",
                            "rst_rcvd": "579",
                            "dxcc": "230"
                        },
                        "default": [],
                        "additionalProperties": {
                            "type": "string"
                        }
                    },
                    "original": {
                        "description": "PUT only: the QSO as it is in the log now (call, qso_date, time_on, band, mode)",
                        "type": "object",
                        "example": {
                            "call": "DL1ABC",
                            "qso_date": "20240105",
                            "time_on": "1200",
                            "band": "20M",
                            "mode": "CW"
                        },
                        "nullable": true,
                        "default": null,
                        "additionalProperties": {
                            "type": "string"
                        }
                    }
                },
                "type": "object"
            },
            "QsoKeyQuery": {
                "required": [
                    "call",
                    "qso_date",
                    "time_on",
                    "band",
                    "mode"
                ],
                "properties": {
                    "call": {
                        "type": "string",
                        "example": "DL1ABC"
                    },
                    "qso_date": {
                        "title": "YYYYMMDD or YYYY-MM-DD",
                        "description": "YYYYMMDD or YYYY-MM-DD",
                        "type": "string",
                        "example": "20240105"
                    },
                    "time_on": {
                        "title": "HHMM or HH:MM, UTC",
                        "description": "HHMM or HH:MM, UTC",
                        "type": "string",
                        "example": "1200"
                    },
                    "band": {
                        "type": "string",
                        "example": "20M"
                    },
                    "mode": {
                        "description": "as logged; USB / LSB are stored as SSB",
                        "type": "string",
                        "example": "CW"
                    },
                    "callsign": {
                        "title": "the log of another callsign you manage; your own when left out",
                        "description": "the log of another callsign you manage; your own when left out",
                        "type": "string",
                        "nullable": true,
                        "default": null,
                        "maxLength": 30
                    }
                },
                "type": "object"
            },
            "RbnQuery": {
                "properties": {
                    "bands": {
                        "description": "comma separated: 160M, 80M, 60M, 40M, 30M, 20M, 17M, 15M, 12M, 10M, 6M, 2M; all when left out",
                        "type": "string",
                        "example": "20M,40M",
                        "nullable": true,
                        "default": null
                    },
                    "modes": {
                        "description": "comma separated: CW, RTTY, PSK31, PSK63; all when left out",
                        "type": "string",
                        "example": "CW",
                        "nullable": true,
                        "default": null
                    },
                    "cont": {
                        "description": "continents of the spotted station, comma separated: AF, AN, AS, EU, NA, SA, OC; all when left out",
                        "type": "string",
                        "nullable": true,
                        "default": null
                    },
                    "fromCont": {
                        "description": "continents of the skimmer, same values",
                        "type": "string",
                        "example": "EU",
                        "nullable": true,
                        "default": null
                    },
                    "waz": {
                        "description": "CQ zones of the spotted station, comma separated; * = all",
                        "type": "string",
                        "pattern": ".*(^\\s*(\\*|\\d{1,2}(\\s*,\\s*\\d{1,2})*)\\s*$).*",
                        "default": "*"
                    },
                    "itu": {
                        "description": "ITU zones of the spotted station, comma separated; * = all",
                        "type": "string",
                        "pattern": ".*(^\\s*(\\*|\\d{1,2}(\\s*,\\s*\\d{1,2})*)\\s*$).*",
                        "default": "*"
                    },
                    "calls": {
                        "description": "only these callsigns (at most 30), comma separated",
                        "type": "string",
                        "example": "OK2CQR,OL7M",
                        "nullable": true,
                        "default": null
                    },
                    "maxAge": {
                        "description": "only reports from the last N seconds",
                        "type": "integer",
                        "default": 1200,
                        "maximum": 3600,
                        "minimum": 1
                    },
                    "sort": {
                        "description": "age (newest first), freq or call",
                        "type": "string",
                        "default": "age",
                        "enum": [
                            "freq",
                            "call",
                            "age"
                        ]
                    },
                    "include": {
                        "description": "locations: add the approximate position (4-character locator) of every spotted station and skimmer",
                        "type": "string",
                        "nullable": true,
                        "default": null,
                        "enum": [
                            "locations"
                        ]
                    },
                    "format": {
                        "description": "json (default) or xml",
                        "type": "string",
                        "default": "json",
                        "enum": [
                            "json",
                            "xml"
                        ]
                    }
                },
                "type": "object"
            },
            "SpotsQuery": {
                "properties": {
                    "bands": {
                        "description": "comma separated: <160M, 160M, 80M, 60M, 40M, 30M, 20M, 17M, 15M, 12M, 10M, 6M, 4M, 2M, 1.25M, 70CM, 33CM+; all when left out",
                        "type": "string",
                        "example": "20M,40M",
                        "nullable": true,
                        "default": null
                    },
                    "modes": {
                        "description": "comma separated: CW, SSB, DIGI; all when left out. A spot of unknown mode passes any mode filter",
                        "type": "string",
                        "example": "CW",
                        "nullable": true,
                        "default": null
                    },
                    "cont": {
                        "description": "continents of the spotted station, comma separated: AF, AN, AS, EU, NA, SA, OC; all when left out",
                        "type": "string",
                        "example": "NA,SA",
                        "nullable": true,
                        "default": null
                    },
                    "fromCont": {
                        "description": "continents of the spotter, same values",
                        "type": "string",
                        "example": "EU",
                        "nullable": true,
                        "default": null
                    },
                    "waz": {
                        "description": "CQ zones of the spotted station, comma separated; * = all",
                        "type": "string",
                        "pattern": ".*(^\\s*(\\*|\\d{1,2}(\\s*,\\s*\\d{1,2})*)\\s*$).*",
                        "example": "14,15",
                        "default": "*"
                    },
                    "itu": {
                        "description": "ITU zones of the spotted station, comma separated; * = all",
                        "type": "string",
                        "pattern": ".*(^\\s*(\\*|\\d{1,2}(\\s*,\\s*\\d{1,2})*)\\s*$).*",
                        "example": "27,28",
                        "default": "*"
                    },
                    "calls": {
                        "description": "only these callsigns (at most 30), comma separated; a callsign also matches its portable forms",
                        "type": "string",
                        "example": "OK2CQR,OL7M",
                        "nullable": true,
                        "default": null
                    },
                    "lotw": {
                        "description": "only stations using LoTW",
                        "type": "boolean",
                        "default": false
                    },
                    "eqsl": {
                        "description": "only stations using eQSL",
                        "type": "boolean",
                        "default": false
                    },
                    "limit": {
                        "description": "number of spots",
                        "type": "integer",
                        "default": 60,
                        "maximum": 200,
                        "minimum": 1
                    },
                    "include": {
                        "description": "locations: add the approximate position (4-character locator) of every spotted station and spotter",
                        "type": "string",
                        "nullable": true,
                        "default": null,
                        "enum": [
                            "locations"
                        ]
                    },
                    "format": {
                        "description": "json (default) or xml",
                        "type": "string",
                        "default": "json",
                        "enum": [
                            "json",
                            "xml"
                        ]
                    }
                },
                "type": "object"
            },
            "VerifyQuery": {
                "required": [
                    "mycall",
                    "hiscall",
                    "date",
                    "band"
                ],
                "properties": {
                    "mycall": {
                        "description": "the callsign asking (the one in the log of hiscall)",
                        "type": "string",
                        "example": "J49C"
                    },
                    "hiscall": {
                        "description": "the station whose log is checked",
                        "type": "string",
                        "example": "OK2CQR"
                    },
                    "date": {
                        "description": "QSO date YYYY-MM-DD",
                        "type": "string",
                        "example": "2013-06-20"
                    },
                    "band": {
                        "type": "string",
                        "example": "12M"
                    },
                    "time": {
                        "description": "QSO start HH:MM UTC, must match exactly",
                        "type": "string",
                        "pattern": ".*(^([01]\\d|2[0-3]):?[0-5]\\d$).*",
                        "example": "12:00",
                        "nullable": true,
                        "default": null
                    },
                    "mode": {
                        "type": "string",
                        "example": "CW",
                        "nullable": true,
                        "default": null,
                        "maxLength": 8
                    },
                    "format": {
                        "description": "json (default) or xml",
                        "type": "string",
                        "default": "json",
                        "enum": [
                            "json",
                            "xml"
                        ]
                    }
                },
                "type": "object"
            },
            "ActivitySpot": {
                "required": [
                    "source",
                    "spotter",
                    "dxcall",
                    "comment",
                    "time"
                ],
                "properties": {
                    "source": {
                        "type": "string",
                        "enum": [
                            "cluster",
                            "rbn"
                        ]
                    },
                    "spotter": {
                        "type": "string",
                        "example": "EA1DAV"
                    },
                    "dxcall": {
                        "type": "string",
                        "example": "OK2CQR"
                    },
                    "freq": {
                        "description": "kHz",
                        "type": "number",
                        "format": "float",
                        "example": 10109.5,
                        "nullable": true
                    },
                    "comment": {
                        "type": "string",
                        "example": "CW 4 dB 26 WPM CQ"
                    },
                    "time": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-10-01T18:00:09Z"
                    }
                },
                "type": "object"
            },
            "QsoInLog": {
                "required": [
                    "date",
                    "mode"
                ],
                "properties": {
                    "log": {
                        "description": "whose log it is",
                        "type": "string",
                        "example": "DL1ABC",
                        "nullable": true
                    },
                    "date": {
                        "type": "string",
                        "format": "date",
                        "example": "2026-09-30"
                    },
                    "band": {
                        "type": "string",
                        "example": "20M",
                        "nullable": true
                    },
                    "mode": {
                        "type": "string",
                        "example": "CW"
                    }
                },
                "type": "object"
            },
            "LogQso": {
                "required": [
                    "call",
                    "date",
                    "mode"
                ],
                "properties": {
                    "call": {
                        "type": "string",
                        "example": "W1AW"
                    },
                    "date": {
                        "type": "string",
                        "format": "date",
                        "example": "2026-10-01"
                    },
                    "band": {
                        "type": "string",
                        "example": "30M",
                        "nullable": true
                    },
                    "mode": {
                        "type": "string",
                        "example": "CW"
                    }
                },
                "type": "object"
            },
            "Activity": {
                "required": [
                    "callsign",
                    "spots",
                    "inLogs",
                    "log"
                ],
                "properties": {
                    "callsign": {
                        "type": "string",
                        "example": "OK2CQR"
                    },
                    "spots": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ActivitySpot"
                        }
                    },
                    "inLogs": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/QsoInLog"
                        }
                    },
                    "log": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/LogQso"
                        }
                    }
                },
                "type": "object"
            },
            "Location": {
                "properties": {
                    "lat": {
                        "type": "number",
                        "format": "float",
                        "example": 50.253446,
                        "nullable": true
                    },
                    "lon": {
                        "type": "number",
                        "format": "float",
                        "example": 14.515041,
                        "nullable": true
                    },
                    "grid": {
                        "description": "Maidenhead locator",
                        "type": "string",
                        "example": "JO70GG",
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "Address": {
                "required": [
                    "street"
                ],
                "properties": {
                    "name": {
                        "type": "string",
                        "example": "Petr Hlozek",
                        "nullable": true
                    },
                    "street": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "city": {
                        "type": "string",
                        "example": "Neratovice",
                        "nullable": true
                    },
                    "zip": {
                        "type": "string",
                        "example": "27711",
                        "nullable": true
                    },
                    "country": {
                        "type": "string",
                        "example": "Czech Republic",
                        "nullable": true
                    },
                    "dxcc": {
                        "description": "DXCC entity of the address, may differ from the station's",
                        "type": "integer",
                        "example": 503,
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "Region": {
                "properties": {
                    "district": {
                        "type": "string",
                        "example": "BME",
                        "nullable": true
                    },
                    "usState": {
                        "type": "string",
                        "nullable": true
                    },
                    "usCounty": {
                        "type": "string",
                        "nullable": true
                    },
                    "oblast": {
                        "type": "string",
                        "nullable": true
                    },
                    "dok": {
                        "description": "German DOK",
                        "type": "string",
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "Qsl": {
                "properties": {
                    "via": {
                        "description": "QSL manager",
                        "type": "string",
                        "nullable": true
                    },
                    "bureau": {
                        "type": "boolean",
                        "nullable": true
                    },
                    "direct": {
                        "type": "boolean",
                        "nullable": true
                    },
                    "lotw": {
                        "type": "boolean",
                        "nullable": true
                    },
                    "eqsl": {
                        "type": "boolean",
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "Links": {
                "properties": {
                    "web": {
                        "type": "string",
                        "nullable": true
                    },
                    "facebook": {
                        "type": "string",
                        "nullable": true
                    },
                    "twitter": {
                        "type": "string",
                        "nullable": true
                    },
                    "youtube": {
                        "type": "string",
                        "nullable": true
                    },
                    "linkedin": {
                        "type": "string",
                        "nullable": true
                    }
                },
                "type": "object"
            },
            "CallbookRecord": {
                "required": [
                    "callsign",
                    "location",
                    "address",
                    "region",
                    "qsl",
                    "links"
                ],
                "properties": {
                    "callsign": {
                        "description": "the record found (OK2CQR for OK2CQR/P without a record of its own)",
                        "type": "string",
                        "example": "OK2CQR"
                    },
                    "nick": {
                        "type": "string",
                        "example": "Petr",
                        "nullable": true
                    },
                    "name": {
                        "type": "string",
                        "example": "Petr Hlozek",
                        "nullable": true
                    },
                    "qth": {
                        "type": "string",
                        "example": "Neratovice",
                        "nullable": true
                    },
                    "dxcc": {
                        "description": "DXCC entity number",
                        "type": "integer",
                        "example": 503,
                        "nullable": true
                    },
                    "country": {
                        "type": "string",
                        "example": "Czech Republic",
                        "nullable": true
                    },
                    "continent": {
                        "type": "string",
                        "example": "EU",
                        "nullable": true
                    },
                    "cq": {
                        "description": "CQ zone",
                        "type": "integer",
                        "example": 15,
                        "nullable": true
                    },
                    "itu": {
                        "description": "ITU zone",
                        "type": "integer",
                        "example": 28,
                        "nullable": true
                    },
                    "utcOffset": {
                        "description": "hours from UTC",
                        "type": "number",
                        "format": "float",
                        "example": 1,
                        "nullable": true
                    },
                    "location": {
                        "$ref": "#/components/schemas/Location"
                    },
                    "address": {
                        "$ref": "#/components/schemas/Address"
                    },
                    "region": {
                        "$ref": "#/components/schemas/Region"
                    },
                    "iota": {
                        "type": "string",
                        "nullable": true
                    },
                    "qsl": {
                        "$ref": "#/components/schemas/Qsl"
                    },
                    "email": {
                        "type": "string",
                        "nullable": true
                    },
                    "birthYear": {
                        "type": "integer",
                        "nullable": true
                    },
                    "licensedSince": {
                        "type": "integer",
                        "nullable": true
                    },
                    "links": {
                        "$ref": "#/components/schemas/Links"
                    },
                    "picture": {
                        "description": "URL of the station's own picture",
                        "type": "string",
                        "nullable": true
                    },
                    "profile": {
                        "description": "URL of the profile on HamQTH",
                        "type": "string",
                        "example": "https://www.hamqth.com/ok2cqr",
                        "nullable": true
                    },
                    "bio": {
                        "description": "the biography as plain text; the key is there only with include=bio",
                        "type": "string",
                        "nullable": true,
                        "default": null
                    }
                },
                "type": "object"
            },
            "DxccEntity": {
                "required": [
                    "adif",
                    "name",
                    "continent",
                    "lat",
                    "lon",
                    "deleted"
                ],
                "properties": {
                    "adif": {
                        "description": "DXCC (ADIF) entity number",
                        "type": "integer",
                        "example": 503
                    },
                    "name": {
                        "type": "string",
                        "example": "Czech Republic"
                    },
                    "continent": {
                        "type": "string",
                        "example": "EU"
                    },
                    "waz": {
                        "description": "CQ zone",
                        "type": "integer",
                        "example": 15,
                        "nullable": true
                    },
                    "itu": {
                        "description": "ITU zone",
                        "type": "integer",
                        "example": 28,
                        "nullable": true
                    },
                    "lat": {
                        "type": "number",
                        "format": "float",
                        "example": 50.07
                    },
                    "lon": {
                        "type": "number",
                        "format": "float",
                        "example": 14.42
                    },
                    "utcOffset": {
                        "description": "hours from UTC (+1 for Central Europe)",
                        "type": "number",
                        "format": "float",
                        "example": 1,
                        "nullable": true
                    },
                    "deleted": {
                        "description": "a deleted entity (no longer counts for DXCC)",
                        "type": "boolean"
                    }
                },
                "type": "object"
            },
            "DxccResult": {
                "required": [
                    "callsign",
                    "date",
                    "details",
                    "continent",
                    "lat",
                    "lon",
                    "entity"
                ],
                "properties": {
                    "callsign": {
                        "type": "string",
                        "example": "U3AP"
                    },
                    "date": {
                        "description": "the day it was resolved for",
                        "type": "string",
                        "format": "date",
                        "example": "2026-10-03"
                    },
                    "details": {
                        "type": "string",
                        "example": "Russia (European), Gorod Moskva (MA), World War II. Veteran"
                    },
                    "continent": {
                        "type": "string",
                        "example": "EU"
                    },
                    "waz": {
                        "description": "CQ zone",
                        "type": "integer",
                        "example": 16,
                        "nullable": true
                    },
                    "itu": {
                        "description": "ITU zone",
                        "type": "integer",
                        "example": 29,
                        "nullable": true
                    },
                    "lat": {
                        "type": "number",
                        "format": "float",
                        "example": 55.75
                    },
                    "lon": {
                        "type": "number",
                        "format": "float",
                        "example": 37.62
                    },
                    "utcOffset": {
                        "description": "hours from UTC",
                        "type": "number",
                        "format": "float",
                        "example": 3,
                        "nullable": true
                    },
                    "entity": {
                        "$ref": "#/components/schemas/DxccEntity"
                    }
                },
                "type": "object"
            },
            "UploadAccepted": {
                "required": [
                    "id",
                    "callsign",
                    "file",
                    "format",
                    "size",
                    "status",
                    "createdAt",
                    "statusUrl"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "example": 2195
                    },
                    "callsign": {
                        "type": "string",
                        "example": "OK2CQR"
                    },
                    "file": {
                        "type": "string",
                        "example": "mylog.adi"
                    },
                    "format": {
                        "type": "string",
                        "enum": [
                            "adi",
                            "zip",
                            "gz",
                            "tar.gz",
                            "tar.bz2",
                            "rar",
                            "7z"
                        ]
                    },
                    "size": {
                        "description": "bytes",
                        "type": "integer",
                        "example": 183520
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "queued",
                            "processing",
                            "done",
                            "failed"
                        ]
                    },
                    "createdAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "finishedAt": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "statusUrl": {
                        "description": "GET it for the result of the import",
                        "type": "string",
                        "example": "https://www.hamqth.com/api/v2/log/uploads/2195"
                    }
                },
                "type": "object"
            },
            "UploadWarning": {
                "required": [
                    "type",
                    "count",
                    "example",
                    "message"
                ],
                "properties": {
                    "type": {
                        "type": "string",
                        "example": "zone"
                    },
                    "count": {
                        "description": "QSOs affected",
                        "type": "integer",
                        "example": 3
                    },
                    "example": {
                        "type": "string",
                        "example": "CQZ=99"
                    },
                    "message": {
                        "type": "string",
                        "example": "Invalid CQ/ITU zone, replaced by the zone of the DXCC entity."
                    }
                },
                "type": "object"
            },
            "RejectedRecord": {
                "required": [
                    "reason",
                    "message",
                    "record"
                ],
                "properties": {
                    "reason": {
                        "type": "string",
                        "example": "bad_call"
                    },
                    "message": {
                        "type": "string",
                        "example": "Invalid callsign X!."
                    },
                    "record": {
                        "type": "string",
                        "example": "CALL=X! QSO_DATE=20240105 TIME_ON=1200 BAND=20M MODE=CW"
                    }
                },
                "type": "object"
            },
            "Rejected": {
                "required": [
                    "total",
                    "records"
                ],
                "properties": {
                    "total": {
                        "type": "integer"
                    },
                    "records": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/RejectedRecord"
                        }
                    }
                },
                "type": "object"
            },
            "UploadStatus": {
                "required": [
                    "id",
                    "callsign",
                    "file",
                    "format",
                    "size",
                    "status",
                    "createdAt",
                    "warnings",
                    "rejected"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "example": 2195
                    },
                    "callsign": {
                        "type": "string",
                        "example": "OK2CQR"
                    },
                    "file": {
                        "type": "string",
                        "example": "mylog.adi"
                    },
                    "format": {
                        "type": "string",
                        "enum": [
                            "adi",
                            "zip",
                            "gz",
                            "tar.gz",
                            "tar.bz2",
                            "rar",
                            "7z"
                        ]
                    },
                    "size": {
                        "description": "bytes",
                        "type": "integer",
                        "example": 183520
                    },
                    "status": {
                        "description": "ask again until done or failed",
                        "type": "string",
                        "enum": [
                            "queued",
                            "processing",
                            "done",
                            "failed"
                        ]
                    },
                    "createdAt": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "finishedAt": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "qsoCount": {
                        "description": "QSOs imported",
                        "type": "integer",
                        "example": 41250,
                        "nullable": true
                    },
                    "error": {
                        "description": "why a failed import failed (the log on HamQTH was left as it was)",
                        "type": "string",
                        "nullable": true
                    },
                    "warnings": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/UploadWarning"
                        }
                    },
                    "rejected": {
                        "$ref": "#/components/schemas/Rejected"
                    }
                },
                "type": "object"
            },
            "LoginToken": {
                "required": [
                    "token",
                    "expiresIn"
                ],
                "properties": {
                    "token": {
                        "description": "send as \"Authorization: Bearer <token>\"",
                        "type": "string",
                        "example": "4f9c0d\u2026e21a"
                    },
                    "expiresIn": {
                        "description": "seconds until the token expires",
                        "type": "integer",
                        "example": 3600
                    }
                },
                "type": "object"
            },
            "StoredQso": {
                "required": [
                    "call",
                    "date",
                    "time",
                    "band",
                    "mode",
                    "dxcc"
                ],
                "properties": {
                    "call": {
                        "type": "string",
                        "example": "DL1ABC"
                    },
                    "date": {
                        "type": "string",
                        "format": "date",
                        "example": "2024-01-05"
                    },
                    "time": {
                        "description": "HH:MM UTC",
                        "type": "string",
                        "example": "12:00"
                    },
                    "band": {
                        "type": "string",
                        "example": "20M"
                    },
                    "mode": {
                        "type": "string",
                        "example": "CW"
                    },
                    "freq": {
                        "description": "MHz",
                        "type": "number",
                        "format": "float",
                        "example": 14.025,
                        "nullable": true
                    },
                    "dxcc": {
                        "description": "DXCC entity number, 0 = none",
                        "type": "integer",
                        "example": 230
                    }
                },
                "type": "object"
            },
            "RbnSkimmer": {
                "required": [
                    "call",
                    "snr"
                ],
                "properties": {
                    "call": {
                        "type": "string",
                        "example": "DK9IP"
                    },
                    "snr": {
                        "description": "dB",
                        "type": "integer",
                        "example": 24
                    }
                },
                "type": "object"
            },
            "RbnSpot": {
                "required": [
                    "dxcall",
                    "band",
                    "mode",
                    "freq",
                    "age",
                    "skimmers"
                ],
                "properties": {
                    "dxcall": {
                        "type": "string",
                        "example": "OL7M"
                    },
                    "band": {
                        "type": "string",
                        "example": "20M"
                    },
                    "mode": {
                        "type": "string",
                        "example": "CW"
                    },
                    "freq": {
                        "description": "kHz, from the newest report",
                        "type": "number",
                        "format": "float",
                        "example": 14025.3
                    },
                    "age": {
                        "description": "seconds since the newest report",
                        "type": "integer",
                        "example": 12
                    },
                    "skimmers": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/RbnSkimmer"
                        }
                    }
                },
                "type": "object"
            },
            "StationLocation": {
                "required": [
                    "call",
                    "grid",
                    "lat",
                    "lon",
                    "source"
                ],
                "properties": {
                    "call": {
                        "type": "string",
                        "example": "OK1HRA"
                    },
                    "grid": {
                        "description": "4-character Maidenhead locator (about 110 x 160 km in Europe)",
                        "type": "string",
                        "example": "JO60"
                    },
                    "lat": {
                        "description": "centre of the locator; for source dxcc the position of the prefix",
                        "type": "number",
                        "format": "float",
                        "example": 50.5
                    },
                    "lon": {
                        "type": "number",
                        "format": "float",
                        "example": 13
                    },
                    "source": {
                        "description": "skimmer: the RBN node list, callbook: the HamQTH callbook, dxcc: only the country or call area of the prefix",
                        "type": "string",
                        "example": "skimmer",
                        "enum": [
                            "skimmer",
                            "callbook",
                            "dxcc"
                        ]
                    }
                },
                "type": "object"
            },
            "RbnSpotList": {
                "required": [
                    "spots"
                ],
                "properties": {
                    "spots": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/RbnSpot"
                        }
                    },
                    "locations": {
                        "description": "only with include=locations: every spotted station and skimmer whose position is known, once",
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StationLocation"
                        },
                        "nullable": true,
                        "default": null
                    }
                },
                "type": "object"
            },
            "Solar": {
                "required": [
                    "fetchedAt",
                    "source"
                ],
                "properties": {
                    "solarFlux": {
                        "description": "solar flux index (SFI) of indicesDate, e.g. 112.2",
                        "type": "number",
                        "format": "float",
                        "nullable": true
                    },
                    "aIndex": {
                        "description": "Boulder A index of indicesDate",
                        "type": "integer",
                        "nullable": true
                    },
                    "kIndex": {
                        "description": "Kiel K index of the last 3-hour period",
                        "type": "integer",
                        "nullable": true
                    },
                    "sunspotNumber": {
                        "description": "sunspot number (SSN) of indicesDate",
                        "type": "integer",
                        "nullable": true
                    },
                    "solarActivity": {
                        "description": "forecast solar activity as DK0WCY words it: quiet, eruptive, \u2026",
                        "type": "string",
                        "nullable": true
                    },
                    "kielAIndex": {
                        "description": "Kiel A index of indicesDate",
                        "type": "integer",
                        "nullable": true
                    },
                    "currentKIndex": {
                        "description": "Kiel K index measured right now, e.g. 3.4",
                        "type": "number",
                        "format": "float",
                        "nullable": true
                    },
                    "geomagneticField": {
                        "description": "forecast geomagnetic field as DK0WCY words it: quiet, active, minor storm, \u2026",
                        "type": "string",
                        "nullable": true
                    },
                    "aurora": {
                        "description": "aurora as DK0WCY words it: no, \u2026",
                        "type": "string",
                        "nullable": true
                    },
                    "indicesDate": {
                        "description": "day of the daily indices (aIndex, kielAIndex, sunspotNumber, solarFlux)",
                        "type": "string",
                        "format": "date",
                        "example": "2026-10-04",
                        "nullable": true
                    },
                    "fetchedAt": {
                        "description": "when HamQTH read the values from DK0WCY, UTC",
                        "type": "string",
                        "example": "2026-10-05T08:25:00Z"
                    },
                    "source": {
                        "description": "where the values come from",
                        "type": "string",
                        "example": "http://dk0wcy.de/magnetogram/"
                    }
                },
                "type": "object"
            },
            "Spot": {
                "required": [
                    "spotter",
                    "dxcall",
                    "freq",
                    "band",
                    "comment",
                    "time",
                    "lotw",
                    "eqsl"
                ],
                "properties": {
                    "spotter": {
                        "type": "string",
                        "example": "W3LPL"
                    },
                    "dxcall": {
                        "type": "string",
                        "example": "A71EM"
                    },
                    "freq": {
                        "description": "kHz",
                        "type": "number",
                        "format": "float",
                        "example": 28003.6
                    },
                    "band": {
                        "type": "string",
                        "example": "10M"
                    },
                    "mode": {
                        "description": "null when unknown",
                        "type": "string",
                        "example": "CW",
                        "nullable": true,
                        "enum": [
                            "CW",
                            "SSB",
                            "DIGI"
                        ]
                    },
                    "comment": {
                        "type": "string",
                        "example": "Heard in MD"
                    },
                    "time": {
                        "type": "string",
                        "format": "date-time",
                        "example": "2026-10-03T07:58:00Z"
                    },
                    "dxcc": {
                        "description": "DXCC entity number of the spotted station",
                        "type": "integer",
                        "example": 376,
                        "nullable": true
                    },
                    "country": {
                        "type": "string",
                        "example": "Qatar",
                        "nullable": true
                    },
                    "continent": {
                        "description": "continent of the spotted station",
                        "type": "string",
                        "example": "AS",
                        "nullable": true
                    },
                    "lotw": {
                        "description": "the spotted station uses LoTW",
                        "type": "boolean"
                    },
                    "eqsl": {
                        "description": "the spotted station uses eQSL",
                        "type": "boolean"
                    }
                },
                "type": "object"
            },
            "SpotList": {
                "required": [
                    "spots"
                ],
                "properties": {
                    "spots": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Spot"
                        }
                    },
                    "locations": {
                        "description": "only with include=locations: every spotted station and spotter whose position is known, once",
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/StationLocation"
                        },
                        "nullable": true,
                        "default": null
                    }
                },
                "type": "object"
            },
            "VerifyResult": {
                "required": [
                    "log",
                    "found"
                ],
                "properties": {
                    "log": {
                        "description": "hiscall has a log on HamQTH",
                        "type": "boolean"
                    },
                    "found": {
                        "description": "the QSO is in it",
                        "type": "boolean"
                    }
                },
                "type": "object"
            }
        },
        "securitySchemes": {
            "Bearer": {
                "type": "http",
                "scheme": "bearer"
            }
        }
    },
    "tags": [
        {
            "name": "Login",
            "description": "A token for the endpoints with a lock, valid one hour"
        },
        {
            "name": "Callbook",
            "description": "Station records and their activity"
        },
        {
            "name": "DXCC",
            "description": "DXCC entity, zones and coordinates of a callsign"
        },
        {
            "name": "DX cluster",
            "description": "DX cluster and Reverse Beacon Network spots"
        },
        {
            "name": "Log",
            "description": "Online log: upload, real-time QSOs, QSO verification"
        },
        {
            "name": "Solar",
            "description": "Solar flux, A and K index, sunspot number"
        }
    ]
}